以二进制和文本模式写入的文件之间的差异

jho*_*oll 55 c c++ file-io

写入以文本模式打开但在二进制模式下不会发生的文件时会发生什么转换?特别是在MS Visual C.

unsigned char buffer[256];
for (int i = 0; i < 256; i++) buffer[i]=i;
int size  = 1;
int count = 256;
Run Code Online (Sandbox Code Playgroud)

二进制模式:

FILE *fp_binary = fopen(filename, "wb");
fwrite(buffer, size, count, fp_binary);
Run Code Online (Sandbox Code Playgroud)

与文字模式:

FILE *fp_text = fopen(filename, "wt");
fwrite(buffer, size, count, fp_text);
Run Code Online (Sandbox Code Playgroud)

Jon*_*ein 49

我相信大多数平台在处理流时都会忽略"t"选项或"text-mode"选项.然而,在Windows上,情况并非如此.如果您在MSDN上查看fopen()函数的描述,您将看到指定"t"选项将产生以下效果:

  • 换行符('\n')将在输出中转换为'\ r \n"序列
  • 回车/换行序列将在输入时转换为换行符.
  • 如果在追加模式下打开文件,将检查文件的末尾是否有ctrl-z字符(字符26)并删除该字符(如果可能).它还会将该字符的存在解释为文件的结尾.从CPM时代开始,这是一个令人遗憾的延续(关于他们的孩子一直到第3代或第4代的父母的罪行).与先前声明的观点相反,不会追加ctrl-z字符.

  • 回车实际上是'\ r','\n'是换行符. (12认同)

MrZ*_*bra 28

在文本模式下,换行符"\n"可以转换为回车+换行符"\ r \n"

通常你想要以二进制模式打开.尝试在文本模式下读取任何二进制数据将无法正常工作,它将被破坏.您可以在二进制模式下读取文本正常 - 它不会自动将"\n"翻译为"\ r \n".

fopen

  • 对于阅读,翻译的工作方式与您描述的相反 - 将"\ r \n"转换为"\n". (3认同)
  • 它仅限Windows? (2认同)
  • techtonik:所有平台都允许您指定文本模式,但在unix/linux上它与二进制模式没有什么不同。只有在 Windows 上才有区别。(可能还有一些更晦涩的平台 - 您必须检查您的平台文档以确保存在) (2认同)

Sma*_*acL 5

此外,当您使用"rt"打开文件时,输入将在Crtl-Z字符上终止.

  • 是的 - 我使用"my-file-type ^ Z"之类的东西开始自己的文件格式,然后如果你从命令行"键入"/"cat"它,它只是给你文件的"魔术数字"并停止而不是向您的终端喷出二进制文件. (2认同)

Min*_*ing 5

另一个区别是当使用 fseek

如果流以二进制模式打开,则新位置正好是从文件开头(如果 origin 是 SEEK_SET)、从当前文件位置(如果 origin 是 SEEK_CUR)和从文件末尾(如果 origin 是 SEEK_END)测量的偏移字节。某些二进制流可能不支持 SEEK_END。

如果流在文本模式下打开,则 offset 的唯一支持值是零(适用于任何来源)和较早调用 std::ftell 在与同一文件关联的流上返回的值(仅适用于SEEK_SET 的起源。


Dav*_*pez 5

尽管这个问题已经得到回答并清楚地解释过,但我认为用一个简单的代码示例来展示主要问题(\n 和 \r\n 之间的翻译)会很有趣。请注意,我没有解决文件末尾的 Crtl-Z 字符的问题。

#include <stdio.h>
#include <string.h>

int main() {
    FILE *f;
    char string[] = "A\nB";
    int len;
    
    len = strlen(string);
    printf("As you'd expect string has %d characters... ", len); /* prints 3*/
    f = fopen("test.txt", "w"); /* Text mode */
    fwrite(string, 1, len, f);  /* On windows "A\r\nB" is writen */
    printf ("but %ld bytes were writen to file", ftell(f)); /* prints 4 on Windows, 3 on Linux*/ 
    fclose(f);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

如果您在 Windows 上执行该程序,您将看到打印以下消息:

As you'd expect string has 3 characters... but 4 bytes were writen to file
Run Code Online (Sandbox Code Playgroud)

当然,您也可以使用 Notepad++ 等文本编辑器打开文件并查看字符:

在此输入图像描述

在 Windows 上以文本模式读取文件时会执行逆转换。