我正在为C 的HTML表单处理器工作,主要是作为学习体验。我有一个小的输出缓冲类别类,使我可以发送Content-Length
标头。它可以正常工作,直到我尝试阅读并输出模板文件。它在Windows系统上,因此线当然是用rn
终止的,但是当我在缓冲区字符串上使用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>rrn
Windows stdout
在二进制模式下
正如上面的我的编辑和评论所示,问题根本不是string.length()
,而是在发送到stdout
时将所有n
转换为rn
。它甚至使用现有的rn
序列来完成此操作,从而将它们变成rrn
。谢谢微软,始终比我更了解我真正想做的事情。
我的第一个解决方案是在输出之前将所有rn
转换为n
(这样,当Windows将它们转换回rn
时,字节数是正确的)确实不是一个理想的解决方案,因为它仅处理已读取和输出的文件,以及输出,以及输出,以及该程序直接输出的任何输出再次导致字节计数被关闭。当然,我本来可以将rn
附加到我所有的输出中(只是将其剥离然后将Windows放回),但这似乎有点... kludgey。在睡个好觉和更多的思考和阅读之后,我决定强迫窗户远离我的字节是更好的解决方案 - 将stdout
更改为二进制模式。
但是,与之链接的边界凸进的问题没有我需要的所有信息。因此,经过大量的谷歌搜索和阅读,在这里进行后代是我解决的完整解决方案:
#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
}
感谢您的边界刺激和其他所有人的帮助,并继续用我真正需要做的事情击败我,直到最终陷入困境。