19. september 2004 - 13:00Der er
25 kommentarer og 1 løsning
C++ og store filer (64 bit adress)
Hejsa,
jeg er igang med at lave en editor, der skal kunne håndtere op til 18 exabyte store filer. I forbindelse med dette er jeg løbet ind i et lille problem :)
---------- Kode snip ----------------
File::File(const std::string *path, const int perm) { this->file = new std::fstream(path->c_str(), perm); this->path = path; }
Jeg får følgende warning: File.cpp(13) : warning C4267: 'argument' : conversion from 'size_t' to 'std::streamsize', possible loss of data
size_t er defineret til at være 64 bit, og det vil jo så sige at 'std::streamsize' må være 'mindre'... Dette er jo ikke skide godt, når jeg skal bruge 64 bit addressering.
Er der nogen, der kender en løsning på dette problem?
Det er på en Windows NT platform (ie. 2000/XP), som benytter 64 bit addressering på OS, hvilket vil sige at filer ikke længere har en maksimal størrelse på 18 exabyte.
Begrænsningen består i at man skal bruge en integer til at holde styr på hvor man er i filen. Tidligere OS versioner brugte en 32 bit signed integer => max (2^32)/2 = 2147483648 bytes Så fandt man ud af at man kunne droppe sign => max 2^32 = 4294967294 bytes Og nu 64 bit unsigned adressering => max 2^64 = 18 millioner gigabyte (18 exabyte)
Ups... lige en fejl i det første post.. problemet er ikke hvor store klumper jeg kan læse, men fil pointeren: f.eks. i: this->file->seekg(position, std::ios_base::beg); Jeg kan kun positionere fil pointeren 2^32 byte fra starten.. og altså ikke læse mere end 4 GB, selvom det burde være muligt :/
jep.. fstream kan åbenbart kun klare 4 GB.. men der må være en 64 bit ækvivalent. Med hensyn til max filstørrelse på de pågældende system, så afhænger det af hvilken page size partitionen har.
Hmm.. seekg med et argument er også 32 bit i VC++ 7.2. Win32 API kald duer desværre ikke, da det skal være cross platform...
Måske kan det lade sig gøre med et lille hack, hvor jeg repositionerer pointeren i incrementer på 4GB.. Altså f.eks. hvis jeg skal læse inde i filen ved 8 GB og 1 MB: this->file->seekg(4294967296, std::ios_base::beg); // jmp first 4 GB this->file->seekg(4294967296, std::ios_base::cur); // jmp second 4 GB this->file->seekg(1024, std::ios_base::cur); // jmp target // start reading
[http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/_crt_fgetpos.asp] The fgetpos function gets the current value of the stream argument's file-position indicator and stores it in the object pointed to by pos. The fsetpos function can later use information stored in pos to reset the stream argument's pointer to its position at the time fgetpos was called. The pos value is stored in an internal format and is intended for use only by fgetpos and fsetpos.
> fgetpos virker altså ikke. Hvis jeg prøver halter .NET bare og siger at jeg skal kontakte programmets support team :)
Løsningen var at bruge _lseeki64:
__int64 _lseeki64( int fd, __int64 offset, int origin );
Og jeg havde set *64, men du sagde jo at du ville have en standard løsning.
Der er jo ikke meget pointe i at forkaste en Win32 API funktion der kan bruges i enhver Windows compiler for en MS VC++ specifik funktion.
Synes godt om
Ny brugerNybegynder
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.