在窗口上查找 c++ 中的大文件

Seeking large file in c++ on windows

本文关键字:文件 c++ 窗口 查找      更新时间:2023-10-16

我正在编写一个小工具来解析Windows上的xfs文件系统。对于小尺寸图像<5GB,我的实用程序工作正常:我能够列出所有文件和目录。但是当我尝试解析 30GB>的大型 xfs 图像时。它给出了错误的结果。我正在使用_fseeki64和_ftelli64来寻找和恐惧来阅读特定的块。我注意到的一件事是_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 寻求分组编号 = 2和 m_fileSystemInfo.块大小 = 4096。

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

更新::

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

所以。

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

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

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

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

适用于_fseeki64和__ftelli64。

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

使用CreateFile打开文件并SetFilePointerEx查找

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