您的位置:首页 > 编程语言 > C语言/C++

c++文件读写之fread和fwrite

2015-03-31 16:05 357 查看

fwrite和fread基本语法

二进制文件和文本文件的区别

先贴出之前看到的一篇博文:/article/7049548.html

这篇博文中算是比较详细的比较了文本文件和二进制文件,我看过之后,对文本文件和二进制文件的理解就是:

1 文本文件

基于字符编码的文件,一般的都是基于ASCII码。对于平时接触到的文本编辑器,editplus或者nodepad++,在打开一个文本文件的时候,都是首先寻找该文件所在的物理地址,然后从开始位置,以8个字节为单位,转换为字符,然后显示出来(可查阅ASCII码表)。

但是,在遇到一些特殊的字符(比如’\r\n’)时,文本编辑器做出相应的操作(回车、换行)。

2.二进制文件

二进制文件是基于值存储的。不仅可以存储字符信息,也可以存一些其他的结构,不局限于文本,所有的数据类型都可以存储(比如int,double, struct结构体,甚至是类)。

但是,如果用文本编辑器去打开二进制文件,会发现是乱码。原因很简单,因为文本编辑器总是定长的去识别0、1序列,遇到8个比特,就进行字符转化。而二进制文件是不定长的,比如,如果要存储一个int类型的数据,这时候需要用4个字节来表示该数据,eg:int a = 1; 其对应的二进制值00000000 00000000 00000000 00000001,这时候,文本编辑器就会解析为:NUL NUL NUL SOH。

其实,文本文件和二进制文件在物理存储上没什么区别,都是0、1序列。只是读取规则不同。

fread & fwrite语法

fread(object &obj, int size, int count, FILE *fp);
fwrite(object &obj, int size, int count, FILE *fp);


这两个函数总是配对使用。fwrite函数往里写的时候都是以二进制值的形式写入的,而最终该文件要以文本文件读出还是以二进制文件读出,取决于读该文件的函数。

对于fread函数,可以先用fseek函数将文件的位置指针放在序列最后,这样就可以用ftell函数得到该文件的长度(单位为字节),然后使用rewind函数使得光标复位,即回到文件开始处位置。

这里首先给出一个例子:我要往文件当中写入一个int类型的数据,int b = 2; 文件是放在工程的根目录下,文件名为text.txt.

代码如下:

#include<iostream>
using namespace std;

/*
*/
void write(int *p, char *path) {
FILE *fp;
if ((fp = fopen(path, "wb")) == NULL) {
cout << "文件打开失败!" << endl;
exit(0);
}

if (fwrite(p, sizeof(int), 1, fp) != 1) {
cout << "写入失败!" << endl;
}
fclose(fp);
}

int read(char *path) {
int a;
FILE *fp;
if ((fp = fopen(path, "r")) == NULL) {
cout << "文件打开失败!" << endl;
}

fseek(fp, 0L, SEEK_END);
int len = ftell(fp);
rewind(fp);

if (fread(&a, 1, len, fp) != len) {
cout << "读取失败" << endl;
}
fclose(fp);

return a;
}

int main() {
//char *name = "I'm a student.李雷";
char *path = "./test.txt";
int b = 22;
write(&b, path);

//char *content;
int a;
a = read(path);

cout << "content:" << a << endl;

return 0;
}


代码中,只是把一个int类型的值22以二进制的方式放在了文件text.txt中,然后再读取该文件,并将读取结果打印到控制台。首先打开text.txt来看一下:



会发现是乱码,但是用函数
fread()
读取文件,可以还原文件的存取内容,下图是读取结果:



如果这里往test.txt中存取的是字符串,就同文本写入一样了。

这里给出写、读字符串的代码:

#include<iostream>
using namespace std;

/*
*/
void write(char *name, char *path) {
FILE *fp;
if ((fp = fopen(path, "wb")) == NULL) {
cout << "文件打开失败!" << endl;
exit(0);
}

if (fwrite(name, sizeof(char), strlen(name) + 1, fp) != (strlen(name) + 1)) {
cout << "写入失败!" << endl;
}
fclose(fp);
}

char *read(char *path) {
static char content[100];
FILE *fp;
if ((fp = fopen(path, "r")) == NULL) {
cout << "文件打开失败!" << endl;
}

fseek(fp, 0L, SEEK_END);
int len = ftell(fp);
rewind(fp);

if (fread(content, 1, len, fp) != len) {
cout << "读取失败" << endl;
}
fclose(fp);

return content;
}

int main() {
char *name = "I'm a student.李雷";
char *path = "./test.txt";
write(name, path);

char *content;
content = read(path);

cout << "content:" << content << endl;

return 0;
}


也可以读取struct结构体,即把结构体的对象作为一个整体,存入文件当中。

#include<iostream>
using namespace std;
#define SIZE 1

struct attribute{
int element;
attribute *next;
};

struct test {
char name[20];
int age;
attribute *head;
};

/*
将信息以二进制的方式写入txt文件中
*/
void write(test *p1, char *path) {
FILE *fp;
if ((fp = fopen(path, "w")) == NULL) {
cout << "Can't open this file!" << endl;
exit(0);
}
for (int i = 0; i < SIZE; i++) {
if (fwrite(p1, sizeof(struct test), 1, fp) != 1) {
cout << "file write error!" << endl;
}
}
fclose(fp);
}

/*
读文件
*/
void read(test *p1, char *path) {
FILE *fp;
if ((fp = fopen(path, "r")) == NULL) {
cout << "can't open this file!!" << endl;
exit(0);
}

char buffer[100];
fseek(fp, 0L, SEEK_END);    //将文件的位置指针放在最后
int len = ftell(fp);    //得到文件中所有文本的长度
rewind(fp);     //重新恢复位置指针的位置,回到文件的开头

for (int i = 0; i < SIZE; i++) {
if (fread(p1, sizeof(test), 1, fp) != 1) {
cout << "can't read this file." << endl;
}

cout << "name:" << p1->name << "\t" << "age:" << p1->age << endl;
}
fclose(fp);
}

/*
创建链表
*/
attribute *createLink(int *element, int count){
attribute *head = new attribute;
head->next = NULL;
attribute *tail;
attribute *newNode;

for (int i = 0; i < count; i++) {
newNode = new attribute;
newNode->next = NULL;
if (head->next == NULL) {
head->next = newNode;
} else {
tail->next = newNode;
}
tail = newNode;
}

return head;
}

int main() {

int *element;
element = (int *)malloc(sizeof(int) * 2);   //动态申请2个int大小的空间
for (int i = 0; i < 2; i++) {
element[i] = i + 1;
}

test *p;
char *path = "./sss.txt";
for (int i = 0; i < SIZE; i++) {
p = new test;
cin.getline(p->name, 20);   //输入姓名和年龄
cin >> p->age;
getchar();
p->head = createLink(element, 2);
}
write(p, path);

read(p, path);

return 0;
}


sss.txt中仍然是乱码:



如果以16进制查看该文件,可看到如下结果:



在这里列出与之相关的资料:

1. /article/7049548.html

2. http://www.cnblogs.com/witxjp/archive/2011/03/21/1990519.html

3. http://blog.csdn.net/athenaer/article/details/7876614

4. /article/2319277.html

5. /article/8417867.html

6. http://www.cnblogs.com/witxjp/archive/2011/03/21/1990519.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: