今天我踩到了C语言的一个坑,导致我一个小时内都在找答案。
问题描述如下:
我想把本地文本文件通过C语言读取到unsigned char缓存数组中,供其他函数调用。
我采用
fopen函数只读文件,
fseek函数找到文本结尾,
ftell函数获取整个文本的长度,
rewind函数回滚指针到文本开头,
fread函数读取文件到缓存数组。
但是缓存数组的内容却和文本文件的内容不一致。
案例如下:
我的txt:
ABCDEFG
HIJKLMN
OPQRST


UTF-8格式。
文件属性如下:

26字节
20个字符,加3个换行符,3个回车符。 \n \r
注意:最后一行有换行符号。

程序:

#include <stdlib.h>
#include <stdio.h>
void main()
{FILE *fp;//定义文件流指针,用于打开读取的文件int len=0;unsigned char  test[1024*4];fp = fopen("test.txt","r");//只读方式打开文件fseek(fp, 0, SEEK_END);len = ftell(fp);rewind(fp);fread(test,1,len, fp);test[len]='\0';printf("%s\n",test);fclose(fp);//关闭文件,有打开就要有关闭system("pause");
}

ftell返回的len为26。20个字符,加3个换行符,3个回车符。 \n \r

结果如下:


是不是很奇怪?
单步调试显示缓存数组:

少了三个换行符。
原因如下:
问题应该出在了第二步fopen那里

fopen需要mode参数,即以什么模式打开文件;
默认情况下,使用ANSI格式;
使用UNICODE, UTF-8, 或 UTF-16LE等Unicode模式打开文件时,将会对读取到的内容进行转换成目标格式;也意味着转换后字节与原始字节很可能不一样;
读或写存储为UTF-8编码格式的数据时,可用文本模式或者二进制模式替代Unicode模式。

以unicode、t模式打开文件,会进行字节转换,转换后的字节数和原始字节数很可能不一样,如果要读取内容,要开启b(Open in binary)模式,

乱码是多余的垃圾值(初始化时赋的初始值)。ftell()返回值比fread()返回值大。fread返回实际得到的字符数,正常情况文本文件中\r\n读取后变成了\n,这就会导致读取的字符串小于实际文本文件中的长度。当用rb取代r时,即用二进制模式时,ftell()和fread()返回的值相同。

如果源文件是UTF-8编码的(其实不管什么编码格式文件),fopen时开启rb(read mode and open in binary)即可。

即:
fopen时开启rb(read mode and open in binary)即可读取原始内容,读到的字节数和原始字节数一致;
最新程序如下:

#include <stdlib.h>
#include <stdio.h>
void main()
{FILE *fp;//定义文件流指针,用于打开读取的文件int len=0;unsigned char  test[1024*4];fp = fopen("test.txt","rb");//只读方式打开文件fseek(fp, 0, SEEK_END);len = ftell(fp);rewind(fp);fread(test,1,len, fp);test[len]='\0';printf("%s\n",test);fclose(fp);//关闭文件,有打开就要有关闭system("pause");
}

ftell返回的len为26。20个字符,加3个换行符,3个回车符。


模式更改以后,回车符也读出来了,这才和ftell返回的字符数对的上。





C语言读取文本文件到字符数组中,和源文件文本长度不一致相关推荐

  1. C语言-输入任意多个数字,存到整型数组,支持任意间隔符,同时支持输入字母存到字符数组中

    第一次在CSDN上写博客- 记录一下想了有那么久的,这串代码 起因是做应用密码学的作业时,有Vigenere密码的加密解密.仿射密码加密解密.Playfair算法.Hill密码 因为数据量比较大,要把 ...

  2. java返回字符数组_JAVA语言实现随机返回字符串数组中的字符串

    本文主要向大家介绍了JAVA语言实现随机返回字符串数组中的字符串,通过具体的内容向大家展示,希望对大家学习JAVA语言有所帮助. //随机返回字符串数组中的字符串 public static Stri ...

  3. 将字符数组中的字符按从小到大的顺序排序

    <程序设计基础实训指导教程-c语言> ISBN 978-7-03-032846-5 p143 7.1.2 上级实训内容 [实训内容10]编写一个函数,要求用字符数组名作为参数,函数功能是将 ...

  4. 将字符数组中的字符转换为整型变量的数字 将字符串转换为数字

    首先要保证字符数组或字符串中的数据是数字,这样才能转换. 检测字符数组或字符串中是否为数字的方法: 遍历字符数组或字符串,检测是否有非数字字符,若有则无法转换,若没有则可以进行转换. 将字符数组或字符 ...

  5. C语言学习笔记——使用字符数组和实型数组分别存储学生姓名和成绩,并通过对学生成绩的排序,按名次输出

    题目来自C语言从入门到精通第三版:使用字符数组和实型数组分别存储学生姓名和成绩,并通过对学生成绩的排序,按照名次输出字符数组中对应的学生姓名 在网上大致找了一下没有看到C语言实现的版本,于是自己写了一 ...

  6. C语言指针实数组输入输出,C语言:回来两个数组中第一个元素的指针,并输出这个值...

    C语言:返回两个数组中第一个元素的指针,并输出这个值 // //  main.c //  Pointer_search // //  Created by ma c on 15/8/2. //  Co ...

  7. (c语言)编程输出二维数组中元素的最大值,要求用指针实现。

    (c语言)编程输出二维数组中元素的最大值,要求用指针实现. #include<stdio.h> #include<stdlib.h> #define N 6 //行数 #def ...

  8. 例13.14 将一组数据保存在字符数组中。

    例13.14 将一组数据保存在字符数组中. 法一: #include<iostream> #include<sstream>//这是最新的头文件 #include<cst ...

  9. 如何在字符数组中存储空白字符

    C没有为字符串定义专门的数据类型,而是把它存储在字符数组中,虽然这种方法可以有效地解决字符串存储问题,但当使用scanf函数为字符数组赋值时,含有空白符(空格.制表符.换行符)的字符串却无法完整储存. ...

最新文章

  1. scratch小游戏脚本大全_酷酷带你一起做小游戏--跳一跳
  2. 文本主题模型之非负矩阵分解(NMF)
  3. 计算机基本组成: 触发器
  4. COM 组件设计与应用(一)
  5. pythonc语言结构_C语言结构体笔记
  6. Pytorch实践中文教程(1)
  7. Object之MemberwiseClone方法
  8. 【转】设计模式六大原则——SOLID
  9. matlab用diag直接使用错误_洗脸扑的正确使用方法,你还在用错误的方式洁面吗?...
  10. (转)在Winform程序中设置管理员权限及为用户组添加写入权限
  11. java.lang.ClassNotFoundException: javax.servlet.SessionCookieConfig
  12. 内部类异常-NoClassDefFoundError
  13. 赶个项目,博客稍后更新
  14. sony android mp3播放器,劲能小钢炮!Sony ZX505 播放器动耳听:云音乐也HiFi
  15. String类12个常用的方法
  16. 微信小程序图片(单图多图上传显示)
  17. 鸟与虫(五)豆瓣我想看高分电影
  18. Orbit Downloader 小巧无广告的下载工具,超赞的在线视频下载能力,比迅雷清爽多了!
  19. Codeforeces #710 div3题解报告
  20. linux之ps命令--进程快照

热门文章

  1. 不同文件(扩展名)的打开方式
  2. 科大讯飞麦克风阵列(6麦)上手体验
  3. 采编系统服务器架构,遂宁日报新闻采编系统的设计与实现
  4. 计算机应用稿件改后重审,论文投稿,外审意见是修后再审,修后再审过后,编辑告诉我要再修改然后再审,返回来的稿件是我修后的原稿,这是什么情况。求知道的专家同仁指点迷津...
  5. 访问终端工具类TerminalUtils
  6. 安装pygraphviz库的波折历经
  7. 2012年9月TIOBE编程语言排行榜:Objective-C继续推进
  8. java除零异常_为什么Java除以0.0时不会抛出异常?
  9. 海外市场增长快速,爱贝激战跨境支付蓝海
  10. 软件加密系统Themida常见问题集锦—Themida是否支持命令行保护?