为什么我的程序在Windows和Linux上产生不同的结果,关于ifstream的文件读取?

时间:2012-03-22 07:05:51

标签: c++ ifstream

我有一个程序如下所示。为此,我有几个问题:

1)。 为什么它会在不同平台上产生不同的结果?我稍后会粘贴屏幕截图。

2)。 我正在使用fail()方法来检查“file.read()”是否失败。这是正确的吗?我使用fail()方法,因为this web page说明了这一点:

  

如果设置了failbit或badbit,则该函数返回true。在输入操作期间,除了达到文件结尾之外的某些错误 时,至少会设置其中一个标志。

但后来我读了这个关于istream :: read()here的页面。它说eofbit和failbit总是在同一时间设置.. 这是否意味着正常的EOF情况也会导致fail()返回true?这似乎与“除了达到文件结束之外”相冲突。

有谁可以帮我澄清我应该如何使用这些方法?我应该使用bad()吗?

我的节目

#include <iostream>
#include <fstream>
using namespace std;

#ifdef WIN32
char * path="C:\\Workspace\\test_file.txt";
#else
char * path="/home/robin/Desktop/temp/test_file.txt";
#endif

int main(int argc, char * argv[])
{
    ifstream file;

    file.open(path);
    if (file.fail())
    {
        cout << "File open failed!" << endl;
        return -1;  // If the file open fails, quit!
    }

    // Calculate the total length of the file so I can allocate a buffer
    file.seekg(0, std::ios::end);
    size_t fileLen = file.tellg();
    cout << "File length: " << fileLen << endl;
    file.seekg(0, std::ios::beg);

    // Now allocate the buffer
    char * fileBuf = new (std::nothrow) char[fileLen+1];
    if (NULL == fileBuf)
        return -1;
    ::memset((void *)fileBuf, 0, fileLen+1);    // Zero the buffer

    // Read the file into the buffer
    file.read(fileBuf, fileLen);
    cout << "eof: " << file.eof() << endl
         << "fail: " << file.fail() << endl
         << "bad: " << file.bad() << endl;
    if (file.fail())
    {
        cout << "File read failed!" << endl;
        delete [] fileBuf;
        return -1;
    }

    // Close the file
    file.close();

    // Release the buffer
    delete [] fileBuf;

    return 0;
}

test_file.txt内容(以“vim -b”显示。这是一个非常简单的文件):

test_file.txt content

Windows上的结果(Visual Studio 2008 SP1):

Windows result

Linux上的结果(gcc 4.1.2):

Linux result

2 个答案:

答案 0 :(得分:9)

  

这是否意味着正常的EOF情况也会导致fail()返回true?这似乎与“除了达到文件结束之外”相冲突。

我建议使用一个没有错误的引用。

http://en.cppreference.com/w/cpp/io/basic_ios/fail说:

  

如果关联流上发生错误,则返回true。具体而言,如果在true中设置badbitfailbit,则返回rdstate()

C ++标准说:

  

返回: true如果在badbit中设置了failbit或rdstate()

除了文件结尾之外没有“东西”。尝试读取文件末尾的操作也会导致failbit设置。 eofbit仅用于将特定的失败原因与其他原因区分开来(并不像人们最初想的那样有用)。


  

我正在使用fail()方法来检查“file.read()”是否失败。这是对的吗?

您只需测试转化为bool

if(file) { // file is not in an error state

它与!fail()同义,但它更有用,因为您可以使用它来直接测试读取操作的结果而无需额外的括号(!(stream >> x).fail()之类的东西变得笨拙):

if(file.read(fileBuf, fileLen)) { // read succeeded

您会注意到对流的所有读取操作都会返回流本身,这是允许您执行此操作的。


  

为什么它会在不同的平台上产生不同的结果?

您在Windows和Linux之间看到的差异是因为文件在文本模式下打开:新行字符将由实现静默转换。这意味着组合"\r\n"(在Windows中用于换行)将在Windows中转换为单个'\n'字符,使文件只有8个字符。请注意vim如何在第一行的末尾显示^M:这是'\r'部分。在Linux中,换行只是'\n'

如果要保留原始文件,则应以二进制模式打开文件:

file.open(path, std::ios_base::in | std::ios_base::binary);

答案 1 :(得分:2)

我想,不同执行的问题是DOS(Window)与UNIX文本文件约定。

在DOS中,一行以<CR><LF>结尾,并以'\n'一起读/写。因此,在Windows中,您的文件最后,但在UNIX中没有,因为剩下一个字符。