我发现在VS2010中,当打开4294967295字节的文件时,seekg功能无法正常工作。
我正在使用简单的代码:
#include <iostream>
#include <fstream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
std::ifstream file;
// cmd: fsutil file createnew tmp.txt 4294967295
file.open(L"c:/tmp.txt", ifstream::in | ifstream::binary);
if(!file.is_open())
return -1;
file.seekg(0, std::ios::end);
auto state = file.rdstate();
// this condition shoots only when size of the file is equal to 4294967295
if((state & ifstream::failbit)==ifstream::failbit)
{
std::cout << "seekg failed";
}
// after seekg failed, tellg returns 0
std::streampos endPos = file.tellg();
return 0;
}
4294967294和4294967296文件的相同代码没有任何问题。
有人知道这个问题的解决方案吗?
更新
看起来这个问题就在这里:
template<class _Statetype>
class fpos
{
__CLR_OR_THIS_CALL operator streamoff() const
{ // return offset
return ((streamoff)(_Myoff + _FPOSOFF(_Fpos)));
}
}
完全在
_FPOSOFF(_Fpos)
,其中
#define _FPOSOFF(fp) ((long)(fp))
所以它需要4294967295并将其转换为-1!
换句话说,这样的代码将失败
//returns -1, even if sizeof(fpos_t)=8
fpos_t pos = _FPOSOFF(4294967295);
_Myoff,_Fpos,streamoffset是64位
如果所有类型都是64位,为什么他们会进行此转换!?我不知道))
答案 0 :(得分:7)
内部流实现有一个const'_BADOFF',它等于0xffffffff,当搜索失败时返回。在这种情况下,搜索成功,但搜索的返回值等于失败代码,这导致流包装器错误地设置其失败代码。
_BADOFF被定义为64位类型,它被赋予了一个愚蠢的值。
作为一种解决方法,您可以寻找1字节短路,然后读取一个字节。
file.seekg(-1, std::ios::end);
char temp; file >> temp;
但请注意,此错误将在任何时候显示特定的文件偏移量,因此如果您在随机位置搜索较大的文件,它仍然可能会出现问题。例如,如果您的文件大一个字节,则此-1搜索将失败,因此这不是一般解决方案。
OP已经延长了他们的问题,所以我会扩展我的答案。是的,在比较之前使用不安全的转换来转换搜索值。这似乎不会影响在文件中超出该点的搜索能力,因为它仅用于与错误值进行比较 - 流中仍然具有正确的偏移量。然而,它似乎确实是_BADOFF首先可疑的根本原因,因为_BADOFF在源中被设置为'-1',并且将遭受相同的转换,截断为0xffffffff。因此修复libs可能是为了修复强制转换(假设没有其他副作用),但为了解决问题,你只需要避免寻找底部的位置设置了32位。从我能看到的情况来看,它将寻求超越这一点。
答案 1 :(得分:5)
这确实是Visual C ++ 2010中的一个错误。两年前在Microsoft Connect上报告过:"std::fstream
use 32-bit int as pos_type even on x64 platform"(错误的标题不正确;症状实际上是由{{1}中的这个错误引起的})。
在Visual C ++ 2012中修复了此错误,其中_FPOSOFF
定义为:
_FPOSOFF
如果能够这样做,建议您升级到Visual C ++ 2012。
答案 2 :(得分:1)
目前有两个不太好的解决方案
在stdio.h中修复
#define _FPOSOFF(fp)((long long)(fp))
转到VS2012(这也很难过)
这是一个错误,并在Visual Studio 2012中修复:_FPOSOFF现在转换为long long,因此&gt;避免截断。 - 詹姆斯麦克尼利斯