小心!!!
这是一篇记录使用fgets和fwrite分割文件时,而踩到的坑------乱码
我们总是容易信心膨胀,导致了爆炸。于是就有了这篇踩坑的文章。
最近学习了c语言的基本用法 和函数。感觉还行,所以就迫不及待地写了一个文件大小分割的demo。然后就是各种问题啊、各种乱码。
最终被打后,心疼的完成了这个内容是纯中文的文件分割demo:
https://github.com/Hi-LookOut/c-language/tree/master/splitFile
下面说下导致乱码的问题:
主要三点:
1).读的文件编码集与存储文件的编码集不对应。
基础知识:https://blog.csdn.net/silently_frog/article/details/96494434(最好使用utf-8)
由于我读取的文件是格式是ANSI,而输出文件也必须是ANSI.除非手动转码。
2).由于我存在文件中只用中文字,用的ANSI编码,每个中文字占两个字节。在文件分割时,一定要考虑每一个分割文 件最后一个中文字所占的两字节是否被分割。
举个例子: 将存有 :我不敢说也不敢问啊 9个字的文件分到2个文件中,如果是 按总字节数除以2的话,后面就乱 码。
9个文字占18个字节, 平分的话一个文件9个字节,但是我们要显示一个char,需要2个字节,于是第一个文件最后一 个是乱码。而第二个文件都是乱码。
3).读取文件中含有中文有含有字母等占字节不同的字符。导致分割时不好计算每个分割文件的大小。容易导致问题2的 情况出现。
4).c字符数组问题,导致我们用fgets与fwrite函数时所产生的问题。
先说 fgets的问题
fgets的实现
我们注意看23行 --n>0
n代表读取字节的个数,这样就导致我们只循环了n-1次,说明我们只取了n-1个字节。
举个例子:
我们要读取一个文件中(我爱你)三个文字,那么n=6,如果用fgets最终只读取了5个字节,从而导致(你)显示为乱 码。解决方法当然是传入n+1。
为啥fgets会这样???
主要的原因-----还是因为在c中字符数组的最后一位必须以\0结尾。所以我们 char buff[50],其实它的容量只用49。所以 fgets会去减去1.
而 fwrite的问题
导致问题的核心都是c中字符数组最后一位\0.对于fwrite来说,它没有去掉\0,而是将其加入了每次读取的末端,并且占一 个字节,这不导致我们乱码才怪了。
解决方法:读取数组大小=读取字节数+1,且在读取后,写入前。去除读取数组中的最后一位。
最后提醒下一般我们的读取字节数应该是偶数,因为一个中文占两个字节。