2010-03-07 7 views
0

J'ai un fichier de 2884765579 octets. Ceci est revérifié avec cette fonction, qui renvoie ce numéro:seekg() échoue mystérieusement

size_t GetSize() { 
     const size_t current_position = mFile.tellg(); 
     mFile.seekg(0, std::ios::end); 
     const size_t ret = mFile.tellg(); 
     mFile.seekg(current_position); 
     return ret; 
    } 

-je alors:

mFile.seekg(pos, std::ios::beg); 
// pos = 2883426827, which is < than the file size, 2884765579 

Ceci définit la failbit. errno n'est pas modifié. Quelles mesures puis-je prendre pour résoudre ce problème?


Je suis absolument sûr que:

  • La taille du fichier est vraiment 2884765579
  • pos est vraiment 2884765579
  • Le failbit n'est pas réglé avant .seekg()
  • L'échec est défini juste après .seekg() et aucun autre appel n'est effectué entre
  • Le fichier est ouvert avec le drapeau binaire

EDIT: au cas où quelqu'un se jette dans le même problème .. Utilisez ce code que j'ai écrit (fonctionne sous Windows uniquement) et beaucoup moins de maux de tête pour vous :

class BinaryIFile 
{ 
public: 
    BinaryIFile(const string& path) : mPath(path), mFileSize(0) { 
     mFile = open(path.c_str(), O_RDONLY | O_BINARY); 

     if (mFile == -1) 
      FATAL(format("Cannot open %s: %s") % path.c_str() % strerror(errno)); 
    } 
    ~BinaryIFile() { 
     if (mFile != -1) 
      close(mFile); 
    } 

    string GetPath() const { return mPath; } 
    int64 GetSize() { 
     if (mFileSize) 
      return mFileSize; 

     const int64 current_position = _telli64(mFile); 
     _lseeki64(mFile, 0, SEEK_END); 
     mFileSize = _telli64(mFile); 
     _lseeki64(mFile, current_position, SEEK_SET); 

     return mFileSize; 
    } 

    int64 Read64() { return _Read<int64>(); } 
    int32 Read32() { return _Read<int32>(); } 
    int16 Read16() { return _Read<int16>(); } 
    int8 Read8() { return _Read<int8>(); } 
    float ReadFloat() { return _Read<float>(); } 
    double ReadDouble() { return _Read<double>(); } 

    void Skip(int64 bytes) { _lseeki64(mFile, bytes, SEEK_CUR); } 
    void Seek(int64 pos) { _lseeki64(mFile, pos, SEEK_SET); } 
    int64 Tell() { return _telli64(mFile); } 

    template <class T> 
    T Read() { return _Read<T>(); } 

    void Read(char *to, size_t size) { 
     const int ret = read(mFile, (void *)to, size); 
     if ((int)size != ret) 
      FATAL(format("Read error: attempted to read %d bytes, read() returned %d, errno: %s [we are at offset %d, file size is %d]") % size % ret % strerror(errno) % Tell() % GetSize()); 
    } 

    template <class T> 
    BinaryIFile& operator>>(T& val) { val = _Read<T>(); return *this; } 

private: 
    const string mPath; 
    int mFile; 
    int64 mFileSize; 

    template <class T> 
    T _Read() { T ret; if (sizeof(ret) != read(mFile, (void *)&ret, sizeof(ret))) FATAL("Read error"); return ret; } 
}; 
+0

Quel type est 'pos'? – jamesdlin

+0

Maintenant, la vraie question devient: comment obtenez-vous des positions de fichiers 64 bits sur Windows (en plus de passer à un système d'exploitation 64 bits). Je ne peux pas aider, désolé. – Tronic

+0

Oui, c'est votre problème. 'seekg' avec un argument prend un argument' streampos', et 'seekg' avec deux prend un argument' streamoff'. Ce dernier est nécessairement signé. – jamesdlin

Répondre

2

Vous pouvez rechercher avant une position donnée, donc pos est signé. Essayez-le avec des fichiers de taille 0x7fffffff et 0x80ffffff et voyez si le dernier déclenche le problème, c'est ma conjecture.

+0

wow merci je n'ai pas pensé à ça! Savez-vous s'il existe une fonction pour les recherches 64 bits? Je sais qu'il y a en C, seek64 ou similaire (pas standard), mais qu'en est-il de C++ - Windows? –

+0

En C++, les versions 64 bits pourraient être (et seraient probablement) implémentées via des surcharges, vous pouvez donc essayer d'abord d'utiliser des types 64 bits pour voir si votre implémentation les fournit. – jamesdlin

+0

Pas un expert sur Windows, mais je suppose que vous allez devoir utiliser leur interface spécifique au système d'exploitation. Ils ont une documentation assez complète en ligne. – paul

Questions connexes