std :: string.length()不计算\ r \ n

时间:2017-03-13 13:33:28

标签: c++ windows text-files stdstring

我正在使用C ++编写HTML表单处理器,主要是作为一种学习体验。我有一个输出缓冲类,允许我发送 expr min lq mean median uq max neval cld fn1(DT) 292.755855 295.047878 301.545026 295.890292 297.364117 382.01720 100 c fn2(DT) 349.139294 351.886946 371.612651 353.392465 394.686377 528.48418 100 d fn3(DT) 10.075716 10.500732 15.642757 10.767010 11.379872 79.36882 100 a fn4(DT) 7.382669 7.968354 8.494499 8.204351 8.585933 18.17826 100 a fn5(DT) 126.307694 134.317938 152.548209 135.883273 177.473529 210.14054 100 b fn6(DT) 8.540844 9.119288 9.833154 9.637090 10.055865 18.84172 100 a 标题。它工作正常,直到我尝试读入并输出模板文件。它位于Windows系统上,因此这些行当然以Content-Length终止,但是当我在缓冲区字符串上使用\r\n方法时,它不计算两个字符,我的length()结束简而言之。我尝试使用和不使用Content-Length来阅读文件,但没有区别。

[编辑]

好的,对不起,这是重现问题的最小代码:

ios::binary

这是测试文件:

#include <iostream>
#include <fstream>
#include <sys/stat.h>

using namespace std;

size_t fileSize(const char* filename) {
    struct stat st;
    if(stat(filename, &st) != 0) return 0;
    return st.st_size;
}

int main() {
    char   fName[] = "testack.html";
    char   oName[] = "testout.txt";
    int   _size;
    char *_content;

    ifstream inFile;
    inFile.open(fName, ios::binary);
    if (inFile.good()) {
        _size = fileSize(fName);
        _content = new char[_size + 1];

        inFile.read(_content, _size);
        _content[_size] = 0;
    }

    ofstream os(oName);
    os << _content;

    return 0;
}

这是38个字节,Windows和我的程序和每个人都同意,我最终在<HTML><BODY>Hello World!</BODY></HTML> 中有38个字节现在,如果我添加一个换行符:

testout.txt

Windows说它是40个字节(正如我所料),我的程序读取40个字节,最后我在输出文件中输出41个字节。第二次换行:

<HTML>
<BODY>Hello World!</BODY></HTML>
Windows说42个字节,我的程序读取42个,最后输出文件中有44个字节。因此,当我将其输出时,无论是文件还是<HTML> <BODY> Hello World!</BODY></HTML> ,似乎都会在每个换行符中添加一个额外的字节。此时我完全糊涂了。有什么想法吗?

[编辑]

而且,通过更多的测试,我发现每行添加了一个额外的\ r \ n,因此我有,例如:

stdout

1 个答案:

答案 0 :(得分:1)

二进制模式下的Windows stdout

正如我上面的编辑和评论所表明的那样,问题与string.length()完全没有关系,而是在发送到\n时Windows将所有\r\n转换为stdout 。它甚至可以使用现有的\r\n序列将其转换为\r\r\n。感谢微软,因为我总是比我更了解我真正想做的事情。

我的第一个解决方案,在输出之前将所有\r\n转换为\n(这样当Windows将它们转换回\r\n时,字节数将是正确的)真的不是一个理想的解决方案,因为它只处理正在读取和输出的文件,并且程序直接输出的任何内容再次导致字节数关闭。当然,我可以将\r\n添加到我的所有输出中(仅剥离它然后让Windows将其放回),但这似乎有点...... kludgey。经过一夜安眠和更多的思考和阅读之后,我决定强迫Windows远离我的字节是更好的解决方案 - 将stdout更改为二进制模式。

但是,BoundaryImposition链接到的question没有我需要的所有信息。所以,经过大量的谷歌搜索和阅读,这里的后代是我确定的完整解决方案:

#if defined(_WIN32) || defined(_WIN64)
#include <io.h>
#include <fcntl.h>
#endif

int main() {
    #if defined(_WIN32) || defined(_WIN64)
    setmode(fileno(stdout), O_BINARY);
    #endif
}

感谢BoundaryImposition和其他所有人的帮助,并继续用我真正需要做的事来击败我,直到它最终陷入困境。