Windows读写文件的猫腻
这里主要涉及对于回车换行的讨论。
回车:\r
换行:\n
Windows读写文件分为普通文件读写和二进制文件读写。
如果以二进制的方式读写文件(如rb, wb),将会完全的把文件内容读出来,不做任何处理。
而如果以普通方式读写文件,会对文件做一些处理,而我所了解的只有一点,就是对回车符与换行符的处理。
首先我建了4个文件:r.txt n.txt rn.txt nr.txt
r.txt的内容:hello\rworld(注'\r'表示一个字符,回车符)
n.txt的内容:hello\nworld(注'\n'表示一个字符,换行符)
rn.txt的内容:hello\r\nworld(注'\r\n'表示两个字符,回车符和换行符)
nr.txt的内容:hello\n\rworld(注'\n\r'表示两个字符,换行符和回车符)
然后,我用普通方式读文件 fp = fopen(name, "r");
r.txt中读到的内容:hello\rworld,没变
n.txt中读到的内容:hello\nworld,没变
rn.txt中读到的内容:hello\nworld,改变了,少了'\r'
nr.txt中读到的内容:hello\n\rworld,没变
得出结论:在以普通方式读取文件时,Windows只对'\r\n'(注意是连续的两个字符,而且就是这个顺序)做处理,
处理的结果是撇掉'\r'只留一个'\n'。
然后,我又把四个文件都清空,用普通方式写文件 fp = fopen(name, "w");
r.txt:fprintf(fp, "hello\rworld");
n.txt:fprintf(fp, "hello\nworld");
rn.txt:fprintf(fp, "hello\r\nworld");
nr.txt:fprintf(fp, "hello\n\rworld");
最后我用文本编辑器(SublimeText)以十六进制形式查看这四个文件,
r.txt中实际写入的内容:hello\rworld,没变
n.txt中实际写入的内容:hello\r\nworld,'\n'被扩展成了'\r\n'
rn.txt中实际写入的内容:hello\r\r\nworld,'\n'被扩展成了'\r\n'
nr.txt中实际写入的内容:hello\r\n\rworld,'\n'被扩展成了'\r\n'
得出结论:在以普通方式写文件时,Windows自动将'\n'字符扩展成'\r\n',
所以如果你这时再以fprintf(fp, "hello\r\nworld");这种方式向文件中写数据,就会多写一个'\r',
虽然'\r'是不可打印字符,我们看不见,但它确实被写到文件中了,而且有些编辑器会检测到这个多出来的'\r',
从而以特别的方式显示出来,很是有碍观瞻。现在知道了原理,相信你也能很轻松的解决这种问题了。
补充:由于历史原因,Windows,linux,Mac OS三大平台对于换行的表示(这里说的是在文本文件中的表示)很不统一,
Windows的正规表示法是'\r\n',即用回车符+换行符来表示换行,
Linux的表示则比较简洁,只用一个'\n'换行符就够了,
Mac也很简洁,但它是用一个'\r'回车符来表示换行。
好在代码编辑器都比较智能(如SublimeText),对这三种换行形式都能正确地识别出来。