一个读取文件大小的很诡异的问题(版主、高人、大神进来看看)

vcf_reader 2014-08-08 05:40:02
读取并处理一个大的文本文件(超过2GB),因为耗时较长,需要在界面上显示一个进度条。
为了显示进度条,就应该取得文件本身的大小,取得文件大小共有两种方法。
但是发现一个很诡异的现象,只要取大小,运行必然出错。
说明:以下示例代码中的变量都是有明确含义的(比如有实际的文件名等等)。这里只是简化了取得实际文件名的那些对分析问题没有什么帮助的代码。

情况一,下面的代码执行到 file.GetLength() 这儿就会出错,说“一个无效的句柄关联到——文件”。
有人可能会说,你的文件没打开。对不起,文件打开是成功的(两个方法验证过:1、在 file.Open(fileName,CFile::modeRead) 之后调用 GetLastError() 的返回值证明文件是打开了的。2、去掉 file.GetLength() 语句之后,读取文件内容直到结束都正常了)

CString fileName;
CStdioFile file;
ULONGLONG nLength;
// Other codes
file.Open(fileName,CFile::modeRead);
nLength =file.GetLength();
AfxBeginThread(TreatData,(LPVOID)this);


情况二,换一种读取文件大小的方式。可以成功启动辅助线程。辅助线程负责读取文件内容,当文件内容读取到大约70%的时候,程序崩溃了。


CString fileName;
CStdioFile file;
ULONGLONG nLength;
CFileStatus sat;
// Other codes
file.Open(fileName,CFile::modeRead);
file.GetStatus(sat);
nLength = sat.m_size;
AfxBeginThread(TreatData,(LPVOID)this);


把问题归纳一下:
1)上述代码读取小文件没问题
2)只要不读取文件大小(去掉相应的语句),读取大文件也没问题
3)代码一、读取文件大小出错
4)代码二、文件没有全部读取,程序就崩溃。


本人百思不得其解。根据上面的1)、3)、4),感觉被操作的大文件有问题,但是联想到2),大文件应该没问题
还有,3)、4),只是换一种读取文件大小的方法(都是微软自己的方法),结果还不一样。

平台是VC2003
...全文
199 7 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
vcf_reader 2014-08-08
  • 打赏
  • 举报
回复
针对我提出的问题,强调一下: 只要不读取文件的长度,一切顺利 大文件出错,代码一,出错在取长度那一句;代码二错误在于不能把文件读完。 所谓大文件,其长度值也只需要32位(其实2G也就31位就够了) 对于小文件,比如1GB的文件,没有任何问题 辅助线程里面的数据缓冲区足够大,不会溢出。缓冲区是用CString变量,且仅仅保存一行的数据,CString会自动增长,被处理的文件每一行的大小基本固定,最长的一行是文件的第一行。文件第一行的长度大约是后续各行的三倍长度,换言之,只要第一行读取不溢出,后面的都不会溢出。 另外:文件打开是正常的,在Open之后用GetLastErrot(),返回值是成功打开!
vcf_reader 2014-08-08
  • 打赏
  • 举报
回复
引用 4 楼 zhao4zhong1 的回复:
GetFileSize The GetFileSize function retrieves the size, in bytes, of the specified file. DWORD GetFileSize( HANDLE hFile, // handle of file to get size of LPDWORD lpFileSizeHigh // pointer to high-order word for file size ); Parameters hFile Specifies an open handle of the file whose size is being returned. The handle must have been created with either GENERIC_READ or GENERIC_WRITE access to the file. lpFileSizeHigh Pointer to the variable where the high-order word of the file size is returned. This parameter can be NULL if the application does not require the high-order word. Return Values If the function succeeds, the return value is the low-order doubleword of the file size, and, if lpFileSizeHigh is non-NULL, the function puts the high-order doubleword of the file size into the variable pointed to by that parameter. If the function fails and lpFileSizeHigh is NULL, the return value is 0xFFFFFFFF. To get extended error information, call GetLastError. If the function fails and lpFileSizeHigh is non-NULL, the return value is 0xFFFFFFFF and GetLastError will return a value other than NO_ERROR. Remarks You cannot use the GetFileSize function with a handle of a nonseeking device such as a pipe or a communications device. To determine the file type for hFile, use the GetFileType function. The GetFileSize function obtains the uncompressed size of a file. Use the GetCompressedFileSize function to obtain the compressed size of a file. Note that if the return value is 0xFFFFFFFF and lpFileSizeHigh is non-NULL, an application must call GetLastError to determine whether the function has succeeded or failed. The following sample code illustrates this point: // // Case One: calling the function with // lpFileSizeHigh == NULL // Try to obtain hFile's size dwSize = GetFileSize (hFile, NULL) ; // If we failed ... if (dwSize == 0xFFFFFFFF) { // Obtain the error code. dwError = GetLastError() ; // Deal with that failure. . . . } // End of error handler // // Case Two: calling the function with // lpFileSizeHigh != NULL // Try to obtain hFile's huge size. dwSizeLow = GetFileSize (hFile, & dwSizeHigh) ; // If we failed ... if (dwSizeLow == 0xFFFFFFFF && (dwError = GetLastError()) != NO_ERROR ){ // Deal with that failure. . . . } // End of error handler. QuickInfo Windows NT: Requires version 3.1 or later. Windows: Requires Windows 95 or later. Windows CE: Requires version 1.0 or later. Header: Declared in winbase.h. Import Library: Use kernel32.lib. See Also File I/O Overview, File Functions, GetCompressedFileSize, GetFileType
我知道你的意思,你担心的这个“点”应该没有问题。有两点理由: 一、ULONGLONG 已经是64位无符号了,vc2003版的 CFile::GetLength() 返回值也正是无符号64位整数。并且我处理的那个文件的长度也只需要32位就够了。 二、执行到 CFile::GetLength() 时,错误信息不是字节溢出,而是:一个无效的文件句柄与……文件关联。当这个信息出现的时候,我当时以为是别的软件占用了这个需要打开的文件。于是采取了各种办法:重启机器,复制这个文件到其他地方,给这个文件改名……,都没有用。但是只要把 CFile::GetLength() 注释掉,就能顺利读完这个文件。问题就诡异在这里。
vcf_reader 2014-08-08
  • 打赏
  • 举报
回复
引用 2 楼 dingxz105090 的回复:
CString fileName; CStdioFile file; ULONGLONG nLength; // Other codes file.Open(fileName,CFile::modeRead); nLength =file.GetLength(); AfxBeginThread(TreatData,(LPVOID)this); 情况一除此以外暂不清楚 情况二可能是开辟的字符数组空间过小
感谢你的答复。读取文件时是读一行写一行,所以不需要很大的缓冲区。文件每一行的字符个数基本相等,而且用的是CString来作为读数据的缓冲区,CString会自动增长。 另外,一开始也说了,只要不读取文件长度,那么文件全部内容都可以顺利读完。 所以,此问题相当诡异。
赵4老师 2014-08-08
  • 打赏
  • 举报
回复
GetFileSize The GetFileSize function retrieves the size, in bytes, of the specified file. DWORD GetFileSize( HANDLE hFile, // handle of file to get size of LPDWORD lpFileSizeHigh // pointer to high-order word for file size ); Parameters hFile Specifies an open handle of the file whose size is being returned. The handle must have been created with either GENERIC_READ or GENERIC_WRITE access to the file. lpFileSizeHigh Pointer to the variable where the high-order word of the file size is returned. This parameter can be NULL if the application does not require the high-order word. Return Values If the function succeeds, the return value is the low-order doubleword of the file size, and, if lpFileSizeHigh is non-NULL, the function puts the high-order doubleword of the file size into the variable pointed to by that parameter. If the function fails and lpFileSizeHigh is NULL, the return value is 0xFFFFFFFF. To get extended error information, call GetLastError. If the function fails and lpFileSizeHigh is non-NULL, the return value is 0xFFFFFFFF and GetLastError will return a value other than NO_ERROR. Remarks You cannot use the GetFileSize function with a handle of a nonseeking device such as a pipe or a communications device. To determine the file type for hFile, use the GetFileType function. The GetFileSize function obtains the uncompressed size of a file. Use the GetCompressedFileSize function to obtain the compressed size of a file. Note that if the return value is 0xFFFFFFFF and lpFileSizeHigh is non-NULL, an application must call GetLastError to determine whether the function has succeeded or failed. The following sample code illustrates this point: // // Case One: calling the function with // lpFileSizeHigh == NULL // Try to obtain hFile's size dwSize = GetFileSize (hFile, NULL) ; // If we failed ... if (dwSize == 0xFFFFFFFF) { // Obtain the error code. dwError = GetLastError() ; // Deal with that failure. . . . } // End of error handler // // Case Two: calling the function with // lpFileSizeHigh != NULL // Try to obtain hFile's huge size. dwSizeLow = GetFileSize (hFile, & dwSizeHigh) ; // If we failed ... if (dwSizeLow == 0xFFFFFFFF && (dwError = GetLastError()) != NO_ERROR ){ // Deal with that failure. . . . } // End of error handler. QuickInfo Windows NT: Requires version 3.1 or later. Windows: Requires Windows 95 or later. Windows CE: Requires version 1.0 or later. Header: Declared in winbase.h. Import Library: Use kernel32.lib. See Also File I/O Overview, File Functions, GetCompressedFileSize, GetFileType
vcf_reader 2014-08-08
  • 打赏
  • 举报
回复
引用 1 楼 zhao4zhong1 的回复:
int _fileno( FILE *stream ); __int64 _filelengthi64( int handle );
感谢答复。但我没有用API,用的是MFC。其实MFC也无非是对API的包装。本质上没有什么区别。MFC总归还是调用了底层的API。
凌乱哥 2014-08-08
  • 打赏
  • 举报
回复
CString fileName; CStdioFile file; ULONGLONG nLength; // Other codes file.Open(fileName,CFile::modeRead); nLength =file.GetLength(); AfxBeginThread(TreatData,(LPVOID)this); 情况一除此以外暂不清楚 情况二可能是开辟的字符数组空间过小
赵4老师 2014-08-08
  • 打赏
  • 举报
回复
int _fileno( FILE *stream ); __int64 _filelengthi64( int handle );

16,548

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • AIGC Browser
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧