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

标签 c++ windows text-files stdstring

我正在使用 C++ 开发 HTML 表单处理器,主要是作为一种学习体验。我有一个小的输出缓冲区类,允许我发送 Content-Length header 。在我尝试读入和输出模板文件之前,它工作正常。它在 Windows 系统上,所以这些行当然以 \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;
}

这是测试文件:

<HTML><BODY>Hello World!</BODY></HTML>

那是 38 个字节,Windows 和我的程序以及每个人都同意,我最终在 testout.txt 中得到 38 个字节 现在,如果我添加一个换行符:

<HTML>
<BODY>Hello World!</BODY></HTML>

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

<HTML>
<BODY>
Hello World!</BODY></HTML>

Windows 显示 42 个字节,我的程序读取 42 个字节,最后我在输出文件中得到 44 个字节。因此,无论是输出到文件还是输出到 stdout,似乎每个换行符都添加了一个额外的字节。在这一点上我完全糊涂了。有什么想法吗?

[编辑]

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

<HTML>\r\r\n

最佳答案

二进制模式下的 Windows stdout

正如我上面的编辑和评论所指出的,问题根本不在于 string.length(),而是 Windows 将所有 \n 转换为 \r\n 发送到 stdout 时。它甚至对现有的 \r\n 序列执行此操作,将它们转换为 \r\r\n。谢谢你,微软,你总是比我更清楚我真正想做什么。

我的第一个解决方案,在输出之前将所有 \r\n 转换为 \n (这样当 Windows 将它们转换回 \r\n 字节数是正确的)确实不是一个理想的解决方案,因为它只处理正在读取和输出的文件,而程序直接输出的任何内容都会再次导致字节数被关闭。当然,我可以直接将 \r\n 附加到我的所有输出中(只删除它然后让 Windows 将其放回原处),但这似乎有点……笨拙。经过一夜安眠以及更多的思考和阅读之后,我决定强制 Windows 不干涉我的字节是更好的解决方案——将 stdout 更改为二进制模式。

然而,question链接到的 BoundaryImposition 没有我需要的所有信息。因此,经过大量谷歌搜索和阅读后,这里为后代提供了我确定的完整解决方案:

#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 和其他所有人的帮助,感谢你们继续用我真正需要做的事情来打败我,直到它最终卡住。

关于c++ - std::string.length() 不计算\r\n,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42764956/

相关文章:

c++ - 类型转换 malloc C++

java - 从 Windows 中的 Java 程序运行命令提示符

Android 从互联网上读取文本文件

c++ - 长时间运行的 C++ 应用程序中的内存泄漏

c++ - 为什么 C++17 中的全局内联变量和静态内联成员需要守卫?

java - java中的命名管道

java - 使用scanner/reader/bufferedreader读取文本文件以读取.txt文件中的数字

java - 如何拆分和重新排列我的字符串?

c++ - BMP文件格式混淆

c - Ubuntu/Windows 中的不同输出