ifstream 在行尾读取额外字符 (CR 13 LF 10)

ifstream reading extra characters (CR 13 LF 10) at end of lines

我目前正在读取一个文本文件,该文件的换行符占用 2 个字节,因为它将换行符写为 CRLF,而不仅仅是 LF。

std::fstream fileReader = std::fstream(_filename, std::ios::in);

// READ THE SIZE OF THE FILE:
fileReader.seekg(0, fileReader.end); // set reader position to the end
std::streamsize fileSize = fileReader.tellg(); // get reader position
fileReader.seekg(0, fileReader.beg); // set reader position to the start

// SET UP THE BUFFER:
std::vector<char> buffer; buffer.resize(fileSize, '[=10=]');
buffer.back() = '[=10=]';

// READ:
fileReader.read(buffer.data(), fileSize);

问题是,“fileSize”实际上是文件的大小,而不是文件中非 CF 字符的数量,这是它所期望的。

有没有办法自动获取该号码?

否则,我想二进制模式是唯一剩下的选项 - 虽然这会非常令人失望,因为我期望在不使用二进制模式时进行正确的自动格式化。 此外,.read 函数失败(fileReader 的失败位为真)

这是正常行为:

ifstream::read 期望“将被提取的字符数量”作为参数,而不是文件大小。

因为这个数量是无法预测的,而且这个函数也不提供它,使用没有 ios::binary 标志的 ifstream::read 是完全没用的,除非已知文件不包含任何 CF会让 ifstream 崩溃的角色。

(不知道其他角色是不是也让ifstream吓坏了)

我建议在 fstream 中使用 ios::binary,即使是读取文本文件,也可以在一次操作中读取它们。 可能也用于写入文件(尤其是如果您关于 Windows).

Is there a way to get that number automatically?

这不能自动完成,因为文件系统不存储文件中的行尾数。任何方法都需要通过文件检查每个字符。幸运的是,可以利用 std::fstream class 来处理大部分繁重的工作。生成的函数与您当前拥有的函数惊人地相似。您只需要获取读取的字符数即可。

// Gets the number of characters in `textfile` accounting for CR-LF being read as one character.
// The stream will be reset to the beginning when this function returns.
std::streamsize char_count(std::fstream & textfile)
{
    std::streamsize count = textfile.gcount();

    // Get an upper bound on the size.
    textfile.clear();
    textfile.seekg(0, textfile.end); // set reader position to the end
    std::streamsize fileSize = textfile.tellg(); // get reader position

    if ( textfile  &&  fileSize != -1 )
    {
        // Read the text.
        std::vector<char> buffer(fileSize);
        textfile.seekg(0, textfile.beg); // set reader position to the start
        textfile.read(buffer.data(), fileSize);

        // Get the count of characters read.
        count = textfile.gcount();
    }

    // Reset the stream.
    textfile.clear(); // Because over-reading would set some flags.
    textfile.seekg(0, textfile.beg);
    textfile.clear(); // In case the seek failed. We did promise to reset the stream.

    return count;
}

这样做似乎很浪费,然后在你有足够的字符数后重复阅读,但由于你不会告诉我们你的 real problem 这可能会让你朝着更好的方向前进。

如果您使用 std::ifstream::binary 读取文件,它会将每个字节读入内存。我觉得挺有道理的。

如果您不使用 std::ifstream::binary ifstream 会将 CRLF 转换为 LF,这使得字符串的长度(strlen 等)不同于文件大小(tellg())。这条规则很不明显...