900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > 基于存储的C语言文件操作常规问题分析(文本文件与二进制文件)

基于存储的C语言文件操作常规问题分析(文本文件与二进制文件)

时间:2023-09-03 04:23:42

相关推荐

基于存储的C语言文件操作常规问题分析(文本文件与二进制文件)

基于存储的C语言文件操作常规问题分析(文本文件与二进制文件)

问题描述文本文件与二进制文件数据写入文本乱码问题fopen和open流式文件操作常用函数直接I/O文件操作常用函数

问题描述

我们都知道计算机中的数据都是以二进制存储的,也对不同的编码解码有所了解,比如ASCII、UNICODE、UTF-8编码等。 但当使用C语言对文件进行读写,会遇到了各种各样的问题,比如从文件中读取到的数据不是我们想要的数据,向文件中写入数据变成乱码,对C语言读写文件的各种参数不甚了解,读写位置与各种符号不好判断等问题。在程序编写的过程中只能不断查询各种读写函数的用法,不同数据类型的读写方式等。其主要原因是我们对文件的存储、编码以及读写文件的函数没有进行过系统性的了解。

文本文件与二进制文件

文本文件和二进制文件在本质上没有任何区别,都是二进制数据流。当我们使用文本工具打开一个文件时,会根据编码方式将文本数据解码,翻译成字符显示出来。所以我们使用文本工具打开文件,看到的其实都是字符。即便整个文本都是数字,那也是数字字符,所以当我们读取文件中的数据时,我们可能想读取的是该数字字符表示的值,但是使用fread和read读取到的,是文本数据本质上(物理上)存储的值,所以会发现读取到的值并不是我们想要的值。什么意思呢?

如图,我们建立一个文件,写入四行数据,第一行1 2 4 a (中间用空格隔开),但是,当我们将该文件以十六进制方式打开,会发现该文件是下图这样的:

上图是根据ASCII编码方式将二进制数据翻译成字符,显示出来给我们看的。下图是该文件真实的数据,该文件的真面目,也就是该文件的二进制形式。

包括空格,换行符等,在文件中也都对应一个字符。

现在我们写一个程序读取该文件,程序如下:

#include<stdio.h>#include<malloc.h>typedef struct{int num1;int num2;int num3;char cz;}Data,*PData;int main(int argc,char* argv[]){FILE* fp=fopen("data.txt","rb");PData pData=(PData)malloc(sizeof(Data)*2);fseek(fp,0,SEEK_SET);fread(pData,sizeof(Data),2,fp);for(int i=0;i<2;i++){printf("%x %x %x %c\n",pData[i].num1,pData[i].num2,pData[i].num3,pData[i].cz);}fclose(fp);}

该程序我们预期得到的结果是前两行的数据1 2 4 a 和 2 2 2 b,但是执行程序之后我们得到的数据见下图,和预期不符,反而和十六进制打开该文件的数据是一致的。

这是因为fread从起始位置,根据要读取数据量,将文本的二进制数据读取到我们定义的buf中。注意,读取到的不是我们用文本工具打开看到的数字字符,是该数字字符对应ASCII数据。比如结构体中的num1-num3是int型数据,四字节,第一个num1的值就是原文件中前四个字节(两个空格和字符1,字符2)对应的值。(如果不明白为什么顺序是反的,请看小端存储和大端存储)

数据写入文本乱码问题

用fwrite和write将字符串写入文件,不会出现问题,但是当我们将数据写入到文件的时候,打开文件会发现乱码了,也是同样的道理。

#include<stdio.h>#include<malloc.h>typedef struct{int num1;int num2;char cz;}Data,*PData;int main(int argc,char* argv[]){FILE* fp=fopen("data.txt","a+");PData pData=(PData)malloc(sizeof(Data)*2);for(int i=0;i<3;i++){pData[i].num1 = 1;pData[i].num2 = 2;pData[i].cz = 'f';}fseek(fp, 0, SEEK_END);fwrite(pData, sizeof(Data), 3, fp);char* str = "aabbccdd";fwrite(str, sizeof(str), fp);fclose(fp);}

上述代码向文件中写三次int型数据 1 ,2,字符 f ,再在末尾写入字符串aabbccdd,运行后打开文件如下图。

发现出现乱码,而字符f成功写入,字符串aabbccdd也没有乱码,也就是说乱码的数据是int型数据。 再查看该文件的十六进制数据,得下图

发现数据是按照int型数据的存储方式写入文件,之所以乱码是因为文本将该int型的数据按照ASCII编码的方式一个字节一个字节的解码显示,所以会出现乱码。

至于为什么字符f也会占四个字节,是因为代码运行的时候自动4字节对齐,所以结构体Data的大小sizeof(Data)的值是12。

综上所述,我们在写C语言读写文件的时候,会出现读取的数据不是想要的数据,写入的数据乱码,都是因为我们看到的是解码后的字符,即便是数字也是字符,读取的时候是该字符对应的ASCII码值。

所以,C语言对文件的读写是基于二进制文件的,当数据是字母字符和字符串时,读取写入不会存在太大问题,因为字符不存在二义性,当数据是数字时,就需要注意,数字字符和数字存在二义性。

fopen和open

fopen和open的区别主要在于C语言对文件的两种操作方式,流式文件操作和直接文件操作。

流式文件操作是将文件读取到缓冲区中,然后读写时都是和缓冲区进行交互。直接I/O文件操作不需要经过缓冲区,当然并不是全过程都不需要。

fopen和open区别详解.

流式文件操作常用函数

直接I/O文件操作常用函数

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。