这个问题思考方式和方向不太正常,题目问的不明所以,问题描述所展现的也和题目描述不一致。特别是问题描述中提到:
“打开test.txt文件,发现文件末尾有个空格”
“在windows上该如何正确使用fwrite()函数,才能让生成的文本文件在linux上打开读取也格式正确呢?”
过于武断的得出判断,以及过于不太正常的思考解决问题的方向。
“打开test.txt文件,发现文件末尾有个空格”。那是不是空格,不能用鼠标划拉一下就武断得出结论。如果一个文件中出现特殊字符(不能常规显示),那么应该用稍微专业一点的工具来判断它是什么字符。这对于程序员调试问题很重要,比如:
$ cat -A file.txt This is test^@
注意后面是没有换行的,因为写的程序就是:
char str[] = "This is test"; fwrite(str, 1, sizeof(str), fp);
写入的就是"This is test",fwrite不会帮你加 或 等,所以这是一个没有换行的内容,也就不涉及 的问题。
然后再说结尾的那个所谓的“空格”是什么。用稍微专业一点的工具把文件内容显示出来,如:
$ od -c file.txt 0000000 T h i s i s t e s t 0000015
就会看到文件的结尾实际上多了一个' '。所以所谓的“空格”其实是这个' '。至于为什么会有这个' ',请仔细想想sizeof(str)是多少吧,换成strlen(str)再试试。
“在windows上该如何正确使用fwrite()函数,才能让生成的文本文件在linux上打开读取也格式正确呢?”
fwrite只是单纯的让它写什么字符,它就写什么字符。如果要让一行的结尾是 ,就是写"This is test ",如果想让结尾是 ,就写"This is test "。
比如:
#include <stdio.h> #include <string.h> int main() { char str[] = "This is test
"; FILE* fp; fp = fopen("file.txt", "wb"); fwrite(str, 1, strlen(str), fp); fclose(fp); return(0); }
编译执行就会得到:
$ od -c file.txt 0000000 T h i s i s t e s t
0000015
结尾是 。比如修改为:
... char str[] = "This is test
"; ...
编译执行后就会得到:
$ od -c file.txt 0000000 T h i s i s t e s t
0000016
结尾就是 。根本没有什么在windows上“正确使用fwrite()函数”的特殊做法,也就不存在问题中的要“解决windows上用fwrite向文件写入内容时结尾的 问题”。因为本来问题中的程序也没写 ,其次fwrite写不写 完全看你自己写没写。
(感谢@恨铁不成钢琴 指出上面程序fopen时未使用"b"参数时的问题,为了表述明确些,我做了如下补充说明)
注意上面的程序在fopen的时候使用了"wb"的参数,"b"这个参数在Windows系统下是有意义的:
b Open in binary (untranslated) mode; translations involving carriage-return and line feed characters are suppressed.
表示不要以translated模式打开文件,translated模式(也叫text模式),是windows为了让fopen标准函数的行为和其它系统一致而实现的。在fopen的posix标准中对它的定义没有明确的限制,参考下面链接:
所以Windows系统用这个参数来表示Binary mode,也就是untranslated mode。那么translate的什么呢?translate就是 和 。说直白了就是windows为了兼容自己 结尾和其它 结尾的系统的差异,默认(不使用b参数)的情况下会将 转换为 。比如上述程序如果写成:
char str[] = "This is test
"; fp = fopen("file.txt", "w");
也就是fopen时不使用"b"参数,那么这个程序在Linux上编译执行会写入"This is test ",在Windows上编译执行会写入"This is test "。这样这个程序可以在不修改的情况下达到在 结尾和 结尾的系统上都能写入正确的换行符号。
而如果写成:
fp = fopen("file.txt", "wb");
则对Linux系统没有影响,对Windows系统则让其不做 到 的转换。这样做也可以在保证不修改程序的情况下,让不同的系统都有一致的行为。
也就是说不使用b参数保证了文本换行时在不同系统的兼容性,使用b参数保证了程序行为在不同系统的一致性,所以是否使用"b"参数,程序员要根据自己程序的需要决定。
说完这个问题本身的问题。最后我们回到Windows和Linux不兼容的 问题上来。
我们不知道提问者所要写的软件面向的是怎样的需求,如果需求是“在windows上写一个纯文本文件,然后Linux能正常读取,反之也是”。这个需求可以看成三个部分:
Windows Linux +--------------+ +-------------+ | | trans2Linux | | | Read/Write | ---------------> | Read/Write | | pure text | <--------------- | pure text | | file | trans2Windows | file | | | | | +--------------+ +-------------+
那么功能部分就可以包括:
而这个问题原始可能就是想问第二个,关于Windows和Linux间文件内容转换的问题。结果非要把一个问题A变成问题C来问,问成了如何让fwrite解决 和 不兼容的问题。结果就是问的人不明白,听的人也不明白到底要干嘛,不知道的以为你要改标准实现。
关于怎么做到兼容Windows和Linux文本格式的问题,其实是有实现的,比如Linux下的dos2unix软件:
比如我得到一个Windows下的文件:
$ od -c dosfile 0000000 T h i s ' s a t e s t
T 0000020 h i s ' s a t e s t t o o 0000040
B l a b l a b l a b l a
0000060
可以看到每一行的结尾都是 ,那么我要把它转换为Linux可以正常查看的格式,可以执行:
$ dos2unix -n dosfile unixfile dos2unix: converting file dosfile to file unixfile in Unix format...
然后就可以看到:
$ od -c unixfile 0000000 T h i s ' s a t e s t
T h 0000020 i s ' s a t e s t t o o
0000040 B l a b l a b l a b l a
0000055
每一行的结尾都变成了 。
当然除了 和 的差异以外,还可能存在很多别的差异。dos2unix工具都可以帮忙解决,并且还可以用于Mac系统。具体请查看dos2unix的文档,我就不详细介绍了。
即使不用dos2unix工具,你就是想把结尾的 都换成 来达到Linux兼容的目的,那一个简单粗暴的文本替换命令也是可以的,比如:
$ sed 's/
$//' dosfile > unixfile2 $ od -c unixfile2 0000000 T h i s ' s a t e s t
T h 0000020 i s ' s a t e s t t o o
0000040 B l a b l a b l a b l a
0000055
怎么实现这个功能可以论证讨论,你也可以自己设计实现这样的功能,这不是问题的关键。问题的关键是你得能正常的分析需求,正常的拆解需求为合适的功能模块,合理的设计实现……这些才是一个程序员应该具备的。你不是甲方爸爸,你不能用一个乱成一团的需求把自己绕进去。只有甲方爸爸才可以提出这样的需求和问题:
而程序员首先要合理的拆分需求:
然后设计成一个个合理的独立的功能块:
被各种朋友嘲笑订阅太低,比如跳舞:哥均订比你高订高,比如香蕉:我有四五万均订,七万高订,比如某表姐:日订阅破十一万人民币,比如三少:我每个月订阅都有好几十万呢,都是零花钱,比如奥斯卡:断更涨订阅,真的涨订阅……
感觉特别屈辱。
最屈辱的是经常有些新人跑过来,兴高采烈的说:蛤蟆哥哥,我均订破万了。你嫉妒的恨不得掐死他……