在 Windows 上用 C++ 寻找大文件

Posted

技术标签:

【中文标题】在 Windows 上用 C++ 寻找大文件【英文标题】:Seeking large file in c++ on windows 【发布时间】:2013-11-15 10:40:43 【问题描述】:

我正在编写一个小工具来解析 Windows 上的 xfs 文件系统。 对于 30GB 的大型 xfs 图像时。它给出了错误的结果。 我正在使用 _fseeki64 和 _ftelli64 来寻找和 fread 来阅读特定的块。 我注意到的一件事是 _fseeki64 工作不正常。 下面是我的搜索函数,它搜索特定的组号和块号。

int FileSystemReadXFS::SeekToGroupBlock(uint16_t grpNum, uint64_t blockNum)
    
        int error = -1;
        //Seek to beginning
        if(_fseeki64(m_fileSystemInfo.fp, (__int64)0, SEEK_SET) != 0)
        
            PRINT_SEEK_ERROR;
            goto BAILOUT;
        
        __int64 currPtr = 0;
        //Seek to destination group
        if(grpNum > 0)
        
            if(_fseeki64(m_fileSystemInfo.fp, (__int64)(grpNum*m_fileSystemInfo.SizeOfBlockGroup*m_fileSystemInfo.BlockSize), SEEK_SET))
            
                PRINT_SEEK_ERROR;
                    goto BAILOUT;
            
             currPtr = _ftelli64(m_fileSystemInfo.fp);
        


        //Seek to destination block in group
        if(blockNum > 0)
        
            if(_fseeki64(m_fileSystemInfo.fp, (__int64)(blockNum*m_fileSystemInfo.BlockSize), SEEK_CUR))
            
                PRINT_SEEK_ERROR;
                goto BAILOUT;
            
            currPtr = _ftelli64(m_fileSystemInfo.fp);
        
        error = 0;
BAILOUT:
        return error;
    

但是上面的函数把我带到了错误的位置。 例如,当我想用​​ m_fileSystemInfo.SizeOfBlockGroup = 2043982 对 number = 2 进行分组时 和 m_fileSystemInfo.BlockSize = 4096。

我期待 currPrt = 2043982*4096*2 = 16744300544 (0x3E609C000),但 _ftelli64 正在返回 (0xE609C000)。 请提出可能出了什么问题。另外请建议在 c++ 中处理 Windows 上的大文件的最佳方法是什么。

更新::

我发现 seekOffset 被限制为 8154365952 (0x1e609c000) 而不是实际 尽管我使用 __int64,但值为 16744300544 (0x3e609c000)。

所以。

_int64 seekOff = (_int64)(grpNum*m_fileSystemInfo.SizeOfBlockGroup*m_fileSystemInfo.BlockSize) = 2*2043982*4096 给出 8154365952 而不是 16744300544。

我不确定原因是什么,因为一切都在 __int64 中。

【问题讨论】:

【参考方案1】:

显然问题出在寻找偏移量的计算上。它正在产生整数溢出。 因此,即使我正在处理 64 位应用程序,我也必须将所有内容都转换为 __int64。我在想编译器也许可以为我做到这一点。

__int64 grpNum = 2;
__int64 sizeOfBlockGroup = 2043982;
__int64 blockSize = 4096;
__int64 seekOffSet = grpNum*sizeOfBlockGroup*blockSize;

它适用于 _fseeki64 和 __ftelli64。

【讨论】:

在用于 64 位窗口的内存模型中,指针是 64 位,而整数是 32 位。此外,您不必将所有值设为 __int64,您只需确保如果 A * B 大于 32 位,则 A 或 B 为 __int64。【参考方案2】:

最好的办法是直接使用 Win32 API,而不是通过 C RunTime。

使用CreateFile打开文件,使用SetFilePointerEx寻找

无论如何,您调用的函数最终都会调用这些 API。在 Visual Studio 中,您有 CRT 代码,因此您可以进入 _fseeki64 并可能查看哪里出错了。

【讨论】:

我发现 2*2043982*4096 的偏移量计算被限制为 8154365952 而不是 16744300544 的实际值。我在大多数地方都使用了 __int64 但它没有帮助。

以上是关于在 Windows 上用 C++ 寻找大文件的主要内容,如果未能解决你的问题,请参考以下文章

如何在任何 Windows 计算机上运行 .exe 文件?

为啥 Windows 任务管理器在写入非常大的文件时显示内存增加?我应该担心吗? [关闭]

如何在 Mac OS 上用 C++ 实现命名管道?

使用fallocate()在Linux中快速预分配大文件

大csv文件c++解析性能

是否可以在不复制的情况下删除大文件的两端?