Avatar billede smokes Nybegynder
23. oktober 2002 - 21:06 Der er 12 kommentarer og
1 løsning

Virtuelt filsystem

Jeg skal implementere et virtual filesystem (en masse filer gemt i EN fil) til min lille game engine.. Det skal være usynligt for hovedprogrammet.. det vil sige jeg vil have funktioner ala:
My_fopen()

og alt efter om et flag er sæt bruger funktionen enten standard bibliotekets funktioner eller mit virtual filesystems.. Hvis nogen af jer har implementeret dette ville jeg gerne have lidt info om hurdles og design.. jeg har tænkt mig at gemme et Directory med filnavne, længder og offsets til filen i starten af den ene store fil som udgør filsystemet.. problemet er at hvis jeg opretter en ny virtuel fil skal jeg klemme informationen ind imellem alle de virtuelle filer og directory'et.. det kan jeg kun (såvidt jeg ved) ved at genskrive hele filen modiceret.. og det har jeg ikke tænkt mig eftersom at den skal indeholde svært mange megs *g*.. en løsning kunne være at opbevare directory'et i en seperat fil.. men det gør Quake ikke så der må være en vej udenom.. en anden ting jeg er lidt i vildrede omkring implementation af er subdirectory'er i filen.. ville blive en temmelig kompliceret struktur..
Avatar billede arne_v Ekspert
23. oktober 2002 - 21:10 #1
Jeg tror det kan blive komplekst.

Hvorfor ikke snyde lidt og tage noget ZIP
kode og bruge det d.v.s. bruge en ZIP-fil ?
Avatar billede smokes Nybegynder
23. oktober 2002 - 21:13 #2
Arne v: god ide men ZIP er alt for stort og kompliceret til mit formål.. desuden er ideen at ikke alle folk skal kunne hive filerne ud af.. det er derfor man laver sådanne systemer *s*.. også for at undgå en masse filer at holde styr på
Avatar billede soreno Praktikant
23. oktober 2002 - 21:14 #3
du kunne jo komme password på zip filen... ?
Avatar billede arne_v Ekspert
23. oktober 2002 - 21:17 #4
Jeg tror nok at et virtuelt fil-system vil være noget
større og mere kompliceret end ZIP. ZIP er jo bare at downloade
zlib og bruge.
Avatar billede smokes Nybegynder
23. oktober 2002 - 21:18 #5
soreno: ja men stadigvæk.. at inkludere et eller andet lib på flere 100 kb.. desuden er jeg interesseret i at lære af at skrive det.. mest derfor jeg skriver mine projekter.. alle tingene er gjort før og bedre af andre.. og kunne udvikles meget hurtigere med 3rd party libraries.. men hvad lærer jeg af det?.. jeg bruger heller ikke en DirectX wrapper men har skrevet min egen.. det lærte jeg meget af.. blandt andet at loade forskellige grafiske filformater.. lidt sjovere at sidde med en specifikation og så skrive sin egen loader end at hente Dr.SuperCools imageloading lib der fylder 1.5 megs og understøtter 50 formater.. hvis jeg lavede dette kommercielt for et firma.. jo da.. så ville jeg sprænge over hvor gærdet var lavest men det her er mere fordi jeg synes det er spændende og fordi mine coding skills bliver bedre hvergang jeg kaster mig ud i noget jeg ikke har prøvet før *s*
Avatar billede soreno Praktikant
23. oktober 2002 - 21:22 #6
har du så også implementeret printf i asm :-b

enhver god os-bog kommer ind på filsystemer og allokeringsmetoder, bla. gør "applied operating system consepts" (at den så ikke lige hører til de bedste det er så en anden sag). du kunne evt. opnå lidt teoretisk baggrund ved at læse lidt.. :-)
Avatar billede arne_v Ekspert
23. oktober 2002 - 21:27 #7
Prøv og tag fat i en Linux source code - der er vistnok
masser af fil-systemer !
Avatar billede smokes Nybegynder
23. oktober 2002 - 21:30 #8
soreno: har faktisk skrevet en print rutine engang i x86 assembly.. inline i turbo pascal.. sammen med en masse vinduer-i-textmode-code *g*

arne: ZIP ER et virtuelt filsystem *s*.. skal heldigvis ikke lave et ægte filsystemet.. alt hvor du har en fil som indeholder andre filer er et virtuelt filsystem.. når jeg implementerer det.. og når jeg er færdig kyler jeg sourcen i hovedet på jer *g*.. så kan i lære det *g*.. vi ses om 18 måneder *g*
Avatar billede soreno Praktikant
23. oktober 2002 - 21:41 #9
det ville nok være en fordel (hvis du beslutter dig for at lave dit eget vfs) hvis du ikke tillader en hierarkisk opbygning. hvis du har det hele i en sammenblanding (ligesom c64'eren..) så skulle vist blive lidt nemmere.
du kunne så lave en liste som ligger som det første i din fil med eks:
filID
filNavn
filOffset
filLængde
nextFil

så vil du kunne regne dig frem til alle filernes placering.

alternativt kunne du bruge zip og så xor filen med en eller anden værdi - så er der nok ikke lige nogen der gætter det er en zip fil :-)
Avatar billede smokes Nybegynder
23. oktober 2002 - 23:05 #10
Så er jeg færdig.. eller ikke helt. mangler et par funktioner men det virker *s*.. Det er ultra simpelt.. droppede emuleringen af fopen() etc.. har en funktion til at kyle en fil ind i arkivet og trække den ud igen til hukommelsen.. arkivet kan selvfølgelig indholde flere filer..
Soreno: Jeg har lavet det i to filer.. en der beskriver alle filerne.. og en der indeholder dem.. problemet med en fil er at jeg ikke kan regne ud hvordan jeg skal opdatere pakken med en ekstra fil uden at genskrive HELE pakken.. hvis du har fillisten i starten.. den er jo af variabel længde.. såvidt jeg ved er der ingen funktioner der kan indsætte data midt i en fil og skubbe resten af indholdet frem.. Hvis du ved hvordan jeg kan klare det får du pointene.. hell du får dem alligevel fordi du ved mest om emnet.. men kan du svare ville det være cool.. en fil er lidt mere pro.. gemmer navn fillængde og offset.. har tænkt mig at xor'e hele "data" filen *g*.. dejlig simpel kryptering som alligevel holder alle wannabee'ne væk.. og jeg skrev en RLE encoder igår.. den smider jeg sikkert også over.. ikke den fedeste kompression men det er hurtigt at læse og min trang til at lære stopper ved huffman encoding og lempel-ziv *g*
Avatar billede arne_v Ekspert
23. oktober 2002 - 23:08 #11
Jeg tror nok, at man normalt skriver indholds-fortegnelsen til sidst
i arkiv-filen.

Når man så tilføjer en fil, så skriver man den ned oveni
indholds-fortegnelsen og lægger en ny indholds-fortegnelse
i enden igen.
Avatar billede smokes Nybegynder
23. oktober 2002 - 23:18 #12
hmmm hvor dum er jeg *g*... lyder meget logisk.. bare at seek til EOF.. trække størrelsen af indholdsfortegnelsen fra og læse lortet.. tak arne.. bliver helt rød i hovedet af skam over ikke at have tænkt på det *g*
Avatar billede jpk Nybegynder
24. oktober 2002 - 09:03 #13
Siden du nu bruger COM, kan du jo lige så godt anvende COM's IStorage og IStream interfaces.
De kan netop anvendes til at læse og skrive compound files, altså filer der internt har hvad der kan betragtes som et filsystem. De kan indeholde filer af alle typer, samt foldere og underfoldere, nøjagtigt som man kender det fra de fleste populære operativsystemer.
Du kan netop ændre i filens interne streams, uden at genskrive hele filen...

Jeg har lavet følgende klasse (udpluk), der viser dig hvordan du kan åbne en stream i en sådan fil. Du kan derefter blot bruge metoden Read på IStream interfacet, til at læse data ind.

class CIStreamReader
{
public:
    CIStreamReader();
    long OpenStream(CString csPath, CString csInternalPath);

protected:
    IStream* m_pStream;
};


CIStreamReader::CIStreamReader()
    : m_pStream(NULL)
{
}


// OpenStream : [in] CString csPath, [in] CString csInternalPath
// Fx: MystreamReader.OpenStream("C:\\MinCompoundFil.mcf", "InternalMainFolder\\Subfolder\MyFile");
HRESULT CIStreamReader::OpenStream(CString csPath, CString csInternalPath)
{
    // Convert string to be used later
    OLECHAR wszFileName[MAX_PATH];
    mbstowcs(wszFileName, csPath, MAX_PATH);

    // Return value used throughout the function
    HRESULT hr;

    // Check for valid file type. If not, return error code
    hr = StgIsStorageFile(wszFileName);
    if(StgIsStorageFile(wszFileName) != S_OK)
        return hr;

    // Open root IStorage object
    IStorage* pStorage[2];
    hr = StgOpenStorage(wszFileName, NULL, STGM_TRANSACTED | STGM_READ | STGM_SHARE_DENY_WRITE, NULL, 0, &pStorage[0]);
    if(FAILED(hr))
    {
        pStorage[0] = pStorage[1] = NULL;
        return hr;
    }

    int nPos=0, nPos2=-1, nNr;
    int nStrIndex = 1;
    while(nPos = csInternalPath.Find('\\', nPos+1))
    {
        CString csTmp = csInternalPath.Mid(nPos2+1, nPos-nPos2-1);
        nPos2=nPos;
        if(nPos == -1)
            break;

        mbstowcs(wszFileName, csTmp, MAX_PATH);
        nNr = nStrIndex;
        ++nStrIndex %= 2;
        hr = pStorage[nStrIndex]->OpenStorage(wszFileName, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, NULL, 0, &pStorage[nNr]);
        if(FAILED(hr))
        {
            pStorage[0] = pStorage[1] = NULL;
            return E_FAIL;
        }
    }

    // Now we are at the level of the wanted stream
    CString csTmp = csInternalPath.Mid(csInternalPath.ReverseFind('\\')+1, csInternalPath.GetLength()-1);
    mbstowcs(wszFileName, csTmp, MAX_PATH);
    hr = pStorage[nNr]->OpenStream(wszFileName, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE | STGM_DIRECT, 0, &m_pStream);
    if(FAILED(hr))
    {
        pStorage[0] = pStorage[1] = NULL;
        return hr;
    }

    pStorage[0] = pStorage[1] = NULL;
    return S_OK;
}
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester