代码之家  ›  专栏  ›  技术社区  ›  Andreas Bonini

seekg()神秘地失败

  •  0
  • Andreas Bonini  · 技术社区  · 16 年前

    我有一个2884765579字节的文件。使用此函数会对其进行双重检查,返回该数字:

    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;
        }
    

    然后我这样做:

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

    这将设置故障位。 errno 没有改变。我可以采取什么步骤来解决这个问题?


    我是 绝对肯定 那就是:

    • 文件大小实际上是2884765579
    • pos 真的是2884765579
    • 之前未设置故障位。请参见kg()
    • failbit设置在.seekg()之后,并且在这两者之间不进行其他调用
    • 文件是用二进制标志打开的

    编辑 :以防有人遇到同样的问题。使用我编写的代码(仅适用于Windows)和许多不那么麻烦的代码:

    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; }
    };
    
    1 回复  |  直到 16 年前
        1
  •  2
  •   paul    16 年前

    你可以在一个给定的位置前看到KG,所以POS是签名的。试试大小为0x7fffffff和0x80fffff的文件,看看后者是否触发了问题,这是我的猜测。