[C(++)] Filesize?

Pagina: 1
Acties:

  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Is het in C of C++ mogelijk op een portable manier de size van een (geopende) file op te vragen?

Ik wil een file in een keer inlezen, maar dan moet ik wel van te voren de size weten.

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 24-08 23:08
int stat(const char *path, struct stat *sb);
int fstat(int fd, struct stat *sb);
...
The stat() function obtains information about the file pointed to by path.
...
The fstat() function obtains the same information about an open file
known by the file descriptor fd.
...
struct stat {
...
off_t st_size; /* file size, in bytes */
...
};
...
The stat() and fstat() function calls are expected to conform to ISO/IEC
9945-1:1990 (``POSIX.1'').
Ik zal het wel niet mogen zeggen, maar dit had je ook zelf in je fucking manual kunnen lezen.

[ Voor 16% gewijzigd door Soultaker op 12-02-2003 15:36 . Reden: fstat er ook maar bij gezet; daar ging het immers om :) ]


  • D2k
  • Registratie: Januari 2001
  • Laatst online: 09-01 11:25

D2k

^^
nix aan toe te voegen

Doet iets met Cloud (MS/IBM)


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 16:18

.oisyn

Moderator Devschuur®

Demotivational Speaker

hop weer open

Soultaker: als je zelf even goed in de fucking manual gekeken had had je gezien dat fstat () niet ANSI C is (wel POSIX overigens) ;)

De enige portable manier die ik me kan bedenken is de file openen, dan seeken naar het eind, en dan de positie opvragen. D'r is namelijk niet een losse functie voor geloof ik

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 24-08 23:08
Niet alleen had ik dat gezien (ik quotte dat nota bene!), maar dat leek me ook afdoende voor de topic starter. (f)stat werkt uitstekend onder UNIX, Linux en Windows, en alle andere systemen met een POSIX compliant standard C library. De topic starter vroeg ook niet om een ANSI oplossing, maar om een portable oplossing. Een POSIX functie is portable, anders mogen ze die P wel schrappen. ;)

Maar als dit topic toch weer open is, kan ik ook mijn mailtje naar de topic starter wel even toevoegen aan de thread:
> Ik was eigenlijk op zoek naar een standaard C++ functie
> (posix is niet standaard c++ toch?).
>
> En in de manual bij stream functie vond ik geen filesize functie.

Uit je bericht maakte ik op dat het je om een C OF C++ functie te doen was, en de C functies zijn redelijk goed gestandaardiseerd. Een bekende truc met C++ streams is om de seek en tell methoden te misbruiken om te bepalen waar het einde van het bestand zich bevind. Voor 'gewone' bestanden (die gewoon op je harde schijf staan) werkt dit wel aardig, al vind ik het zelf niet echt netjes (dat wil zeggen; ik gebruik bij voorkeur stat()). Je krijgt dan code als deze:

{
std::ifstream input("bestandsnaam");
input.seekg(0, std::ios::end); // pointer naar het einde van de stream
int length = input.tellg(); // positie uitlezen als bestandslengte
char *buffer = new char[length]; // buffer alloceren
input.seekg(0, std::ios::begin); // pointer terug naar het begin
input.read(buffer, length); // gegevens inlezen
}
Feitelijk is dat een uitwerking van wat jij ook al suggereert: naar het einde seeken en weer terug. Ik vind dit zoals gezegd geen fantastische oplossing, omdat je nu code schrijft die niet uitdrukt wat de bedoeling is. Ik kan me voorstellen dat seekg ook daadwerkelijk in het bestand gaat seeken. Als ik nu geen gewone file open heb, maar (bijvoorbeeld) een gecomprimmeerd bestand, dat sequentieel ingelezen wordt (als ik me niet vergis hebben onder andere OGG en GIF bestanden hier last van) kan dit een best kostbare operatie zijn. Dit voorbeeld is misschien ver gezocht, maar ik vind het reden genoeg om stat() te gebruiken waar mogelijk.

[ Voor 2% gewijzigd door Soultaker op 12-02-2003 20:20 . Reden: schrappen is met een r ]


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 21-08 17:14
Heb ik een offday, of was het resultaat van tellg mogelijkerwijs geen int? (in ISO C, POSIX is dacht ik wel altijd een numeriek type).

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 24-08 23:08
Ik geloof dat 't inderdaad, istream::pos_type (of iets dergelijks) is. Substitueer die dus maar voor int. :) Resultaat is verder hetzelfde, natuurlijk, en ik neem aan dat je die altijd veilig naar int kan casten.

  • Eelis
  • Registratie: Januari 2003
  • Laatst online: 21-02-2015
.

[ Voor 101% gewijzigd door Eelis op 18-02-2015 19:46 ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 16:18

.oisyn

Moderator Devschuur®

Demotivational Speaker

Soultaker schreef op 12 February 2003 @ 20:18:
Niet alleen had ik dat gezien (ik quotte dat nota bene!), maar dat leek me ook afdoende voor de topic starter. (f)stat werkt uitstekend onder UNIX, Linux en Windows, en alle andere systemen met een POSIX compliant standard C library.


windows is helaas niet volledig POSIX, maar de functie fstat () (wat dacht ik een #define of inline wrapper is om _fstat () omdat het geen ANSI is) bestaat idd wel :)
Maar helaas is fstat () niet te gebruiken op C++ filestreams
Ik kan me voorstellen dat seekg ook daadwerkelijk in het bestand gaat seeken. Als ik nu geen gewone file open heb, maar (bijvoorbeeld) een gecomprimmeerd bestand, dat sequentieel ingelezen wordt (als ik me niet vergis hebben onder andere OGG en GIF bestanden hier last van) kan dit een best kostbare operatie zijn. Dit voorbeeld is misschien ver gezocht, maar ik vind het reden genoeg om stat() te gebruiken waar mogelijk.
mwoa, als het een beetje goede implementatie is van een compressiestream detecteert ie dat ie 0 vanaf het eind zoekt, en dan kan ie dus, zonder iets de decompressen, gewoon naar het eind gaan en de streampos op de goede waarde zetten. Zeker als je weet dat deze techniek nogal eens gebruikt wordt om de lengte te bepalen. Just a thought :)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 21-08 17:14
Soultaker schreef op 12 February 2003 @ 21:00:
Ik geloof dat 't inderdaad, istream::pos_type (of iets dergelijks) is. Substitueer die dus maar voor int. :) Resultaat is verder hetzelfde, natuurlijk, en ik neem aan dat je die altijd veilig naar int kan casten.
streampos, een typedef. Je kan'm zeker niet altijd velig naar een int casten, sterker nog, ik ga er van uit dat bijna alle implementaties intern naar __int64/long long oid zullen gaan.
Daar komt dan nog bij, dat streampos een typedef is voor een fpos<char_traits<char>::state_type>. Dat is dus een template instantiatie, zeker geen integer.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 24-08 23:08
.oisyn schreef op 13 februari 2003 @ 10:12:
windows is helaas niet volledig POSIX, maar de functie fstat () (wat dacht ik een #define of inline wrapper is om _fstat () omdat het geen ANSI is) bestaat idd wel :)
Maar helaas is fstat () niet te gebruiken op C++ filestreams
Het ging ook alleen om dit geval. In het algemeen is de POSIX standaard een redelijk goed beginpunt, als je op zoek bent naar portable API's. Veel dingen zitten ook wel in de Windows API's, maar helaas niet allemaal.
mwoa, als het een beetje goede implementatie is van een compressiestream detecteert ie dat ie 0 vanaf het eind zoekt, en dan kan ie dus, zonder iets de decompressen, gewoon naar het eind gaan en de streampos op de goede waarde zetten. Zeker als je weet dat deze techniek nogal eens gebruikt wordt om de lengte te bepalen. Just a thought :)
Zoals ik al zei, het was een erg vergezocht voorbeeld. :) Het gaat me er vooral om dat ik liever geen code schrijf die iets anders (of in dit geval: meer) doet dan nodig is. Je doet dan namelijk aannames over hoe het onderliggende systeem werkt, waar absoluut geen garanties over gegeven zijn. Een seek op een tape zou in een bepaalde implementatie bijvoorbeeld inderdaad tot spoelen kunnen leiden, ook al wordt 'ie daarna meteen weer terug gespoeld.

Al met al vind ik Eelis' suggestie voor C++ ook erg geschikt. Wel jammer dat je een aantal reallocaties moet doen, wat er wel eens voor zou kunnen zorgen dat de gegevens een aantal keer gekopieerd moeten worden.

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 24-08 23:08
MSalters schreef op 13 February 2003 @ 10:21:
streampos, een typedef. Je kan'm zeker niet altijd velig naar een int casten, sterker nog, ik ga er van uit dat bijna alle implementaties intern naar __int64/long long oid zullen gaan.
Daar komt dan nog bij, dat streampos een typedef is voor een fpos<char_traits<char>::state_type>. Dat is dus een template instantiatie, zeker geen integer.
Nou ja, als ik even op cplusplus.com kijk, dan zie ik daar het volgende:
streampos (stream position type)
Type to express absolute positions within streams.
This type describes a class to contain all the information needed to restore an arbitrary file-position indicator within a stream. It can be constructed from or casted to an integer offset value (streamoff).

streamoff (offset type)
Type to express positions in streams.
It is generally a synonym of one of the basic integral types (typically long). It is used to represent offset positions in I/O buffers.
Ik weet niet wat ik aan "generally" heb, maar streamoff is dus wel een "integer offset value". Een harde garantie is er dus niet, maar als ik dat ding niet van/naar een integer mag casten, hoe kan ik dan ooit (bijvoorbeeld) naar byte-positie 1024 in een bestand seeken?

  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Eelis schreef op 12 februari 2003 @ 23:33:
[...]

Wat bedoel je met "in één keer"? Eén OS call? Eén lees-operatie van de HD-hardware? Waarom laat je de stream niet gewoon extracten tot ie leeg is:

C++:
1
2
3
  ostringstream oss;
  oss << ifstream(filename).rdbuf();
  string s (oss.str());
Ik wil een keer geheugen aanvragen voor de hele file en dan de hele file inlezen.
Soultaker schreef op 12 februari 2003 @ 20:18:
Niet alleen had ik dat gezien (ik quotte dat nota bene!), maar dat leek me ook afdoende voor de topic starter. (f)stat werkt uitstekend onder UNIX, Linux en Windows, en alle andere systemen met een POSIX compliant standard C library. De topic starter vroeg ook niet om een ANSI oplossing, maar om een portable oplossing. Een POSIX functie is portable, anders mogen ze die P wel schrappen. ;)
Ik wilde inderdaad liefst een C of C++ functie, maar posix zal ook wel voldoen bij gebrek aan echt beter.
Pagina: 1