在 ifstream::gcount() 的位置之后仍然存在文本

问题描述 投票:0回答:1

我编写了一个文本文件,然后将该文件读取到比该文本文件大的字符串缓冲区中。

我以为

ifstream::gcount()
的位置后面不会有任何文本,因为缓冲区是用
\0
s初始化的。

但是有文字。这怎么可能?

示例代码:

#include <iostream>
#include <string>
#include <fstream>

int main() {
    std::string path = "test.txt";

    // write to file
    std::ofstream out(path);    
    for (int i = 1; i <= 10'000; ++i) {
        std::string lineNum = std::to_string(i);
        out << lineNum + "xxxxxxxxxxxxxxx" + lineNum + "\n"; 
    } 
    out.close(); // (Just FYI: without close(), the result changes, although ofstream and ifstream are being used separately and they support RAII.)

    // read from file
    std::ifstream in(path); 
    std::string buffer;
    int bufferSize = 1'000'000; 
    buffer.resize(bufferSize); 
    in.read(buffer.data(), buffer.size()); 

    auto gc = in.gcount(); 
    auto found = buffer.find('\n', gc); 
    std::string substr = buffer.substr(gc - 10, 100); 

    std::cout << "gcount: " << gc << '\n'; 
    std::cout << "found: " << found << '\n'; 
    std::cout << "npos?: " << std::boolalpha << (found == std::string::npos) << '\n'; 
    std::cout << "substr:\n" << substr << std::endl;    
}

结果:

gcount: 237788
found: 237810
npos?: false    // I thought `found` should be the same as `string::npos`.
substr:         
xxxx10000
01xxxxxxxxxxxxxxx9601     // I thought there should be no text after `gcount()`.
9602xxxxxxxxxxxxxxx9602
9603xxxxxxxxxxxxxxx9603
9604xxxxxxxxxxxxx

在 Windows(x64) 上使用 32 位 MSVC 执行。

附注也尝试构建 64 位,但结果相同。
(使用

in.read(const_cast<char*>(buffer.data()), buffer.size());
代替
in.read(buffer.data(), buffer.size());

c++ io fstream
1个回答
0
投票

@john 的评论救了我。

罪魁祸首是不同的操作系统对换行符的解释不同。

如果用十六进制编辑器打开,我们可以看到差异。

如果在Windows中运行问题中的代码,代码写入的文件显示

0x0D 0x0A
,简单来说就是
\r\n
。但是,在 Unix 或类 Unix 操作系统(例如 Linux)中,它只是
0x0A
,这意味着
\n

但是,如果我们在使用

std::ios_base::binary
时使用
std::fstream
选项,操作系统将不会解释换行符,而只是“按原样”使用它。 因此,使用该选项,十六进制编辑器将仅显示
0x0A
,无论操作系统如何。

因此,将

ios_base::binary
选项与
ofstream
ifstream
或两者一起使用可以消除问题中描述的问题。

© www.soinside.com 2019 - 2024. All rights reserved.