C/C++文件IO

版权

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <vector>
#include <algorithm>
#include <iostream>
#include "test.h"
using namespace std;

typedef struct Sys_Info
{
unsigned int vesion;
unsigned int sub_version;
char info[20];
char date[20];
} Sys_Info;12345678910111213

1. 基于C的流式文件操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
/*------operator file in the way of C stream--------*/
//operator with binary, not readable for user
void io_operator_binary()
{
/*
r 打开只读文件,该文件必须存在。
  r+ 打开可读写的文件,该文件必须存在。
  rb+ 读写打开一个二进制文件,只允许读写数据。
  rt+ 读写打开一个文本文件,允许读和写。
  w 打开只写文件,若文件存在则文件长度清为0,即该文件内容会消失。若文件不存在则建立该文件。
  w+ 打开可读写文件,若文件存在则文件长度清为零,即该文件内容会消失。若文件不存在则建立该文件。
  a 以附加的方式打开只写文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾,即文件原先的内容会被保留。(EOF符保留)
  a+ 以附加方式打开可读写的文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾后,即文件原先的内容会被保留。 (原来的EOF符不保留)
  wb 只写打开或新建一个二进制文件;只允许写数据。
  wb+ 读写打开或建立一个二进制文件,允许读和写。
  wt+ 读写打开或着建立一个文本文件;允许读写。
  at+ 读写打开一个文本文件,允许读或在文本末追加数据。
  ab+ 读写打开一个二进制文件,允许读或在文件末追加数据。
*/
FILE *fd = fopen("sys", "wb");
for(int i = 0; i < 10; ++ i)
{
Sys_Info t = {i, i * 10, "this is test", "2016-10-06"};
fwrite(&t, sizeof(Sys_Info), 1, fd);
}
fclose(fd);

fd = fopen("sys", "rb");
Sys_Info tmp[10];
for(int i = 0; i < 10; ++ i)
{
fread(&tmp[i], sizeof(Sys_Info), 1, fd);
}
/*
此函数一般用于二进制模式打开的文件中,功能是定位到流中指定的位置,原型是int fseek(FILE *stream, long offset, int whence);如果成功返回0,参数offset是移动的字符数,whence是移动的基准,取值是
符号常量 值 基准位置
SEEK_SET 0 文件开头
SEEK_CUR 1 当前读写的位置
SEEK_END 2 文件尾部
*/
fseek(fd, 5 * sizeof(Sys_Info), SEEK_SET);
Sys_Info sys_info;
fread(&sys_info, sizeof(Sys_Info), 1, fd);
fclose(fd);
}
//operator with ascii, readable for user
void io_operator_ascii()
{
FILE *fd = fopen("sys", "w");
for(int i = 0; i < 10; ++ i)
{
Sys_Info t = {i, i * 10, "this-is-test", "2016-10-06"};
/*
按格式输入到流,其原型是int fprintf(FILE *stream, const char *format[, argument, ...]);其用法和printf()相同,不过不是写到控制台,而是写到流罢了
*/
fprintf(fd, "%d %d %s %s ", t.vesion, t.sub_version, t.info, t.date);
}
fclose(fd);

fd = fopen("sys", "r");
Sys_Info tmp[10];
for(int i = 0; i < 10; ++ i)
{
/*
从流中按格式读取,其原型是int fscanf(FILE *stream, const char *format[, address, ...]);其用法和scanf()相同,不过不是从控制台读取,而是从流读取罢了。
*/
fscanf(fd, "%d%d%s%s", &tmp[i].vesion, &tmp[i].sub_version, tmp[i].info, tmp[i].date);
}
fclose(fd);
}

2.基于C的直接I/O操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
/*------operator file in the way of C std--------*/
/*
open() 打开一个文件并返回它的句柄
close() 关闭一个句柄
lseek() 定位到文件的指定位置
read() 块读文件
write() 块写文件
eof() 测试文件是否结束
filelength() 取得文件长度
rename() 重命名文件
chsize() 改变文件长度
*/
#include <io.h>
#include <fcntl.h>
void operator_c_file()
{
/*
O_RDONLY 只读方式 O_WRONLY 只写方式 O_RDWR 读/写方式
O_NDELAY 用于UNIX系统 O_APPEND 追加方式 O_CREAT 如果文件不存在就创建
O_TRUNC 把文件长度截为0 O_EXCL 和O_CREAT连用,如果文件存在返回错误 O_BINARY 二进制方式
O_TEXT 文本方式

对于多个要求,可以用"|"运算符来连接,如O_APPEND|O_TEXT表示以文本模式和追加方式打开文件。
*/
int fd = _open("c_sys",O_BINARY|O_CREAT|O_WRONLY);
for(int i = 0; i < 10; ++ i)
{
Sys_Info t = {i, i * 10, "this is test", "2016-10-06"};
_write(fd, &t, sizeof(Sys_Info));
}
_lseek(fd, 0L, SEEK_SET);
_close(fd);

fd = _open("c_sys",O_BINARY|O_RDONLY);
Sys_Info tmp[10];
for(int i = 0; i < 10; ++ i)
{
_read(fd, &tmp[i], sizeof(Sys_Info));
}
_lseek(fd, 5 * sizeof(Sys_Info), SEEK_SET);
Sys_Info sys_info;
_read(fd, &sys_info, sizeof(Sys_Info));
_close(fd);
}

3.基于C++fstream的文件操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#include <fstream>
#include <istream>
#include <ostream>
/*------operator file in the way of C++ methods--------*/
void operator_cpp_file()
{
fstream file("c_sys", ios::binary|ios::in);
/*
filename:  要打开的文件名
mode:    要打开文件的方式
access:   打开文件的属性
打开文件的方式在类ios(是所有流式I/O类的基类)中定义,常用的值如下:

ios::app:   以追加的方式打开文件
ios::ate:   文件打开后定位到文件尾,ios:app就包含有此属性
ios::binary:  以二进制方式打开文件,缺省的方式是文本方式。两种方式的区别见前文
ios::in:    文件以输入方式打开(文件=>程序)
ios::out:   文件以输出方式打开 (程序=>文件)
ios::nocreate: 不建立文件,所以文件不存在时打开失败 
ios::noreplace:不覆盖文件,所以打开文件时如果文件存在失败
ios::trunc:  如果文件存在,把文件长度设为0
可以用“或”把以上属性连接起来,如ios::out|ios::binary

打开文件的属性取值是:

0:普通文件,打开访问
1:只读文件
2:隐含文件
4:系统文件
可以用“或”或者“+”把以上属性连接起来 ,如3或1|2就是以只读和隐含属性打开文件
*/
//这里先用之前生成的c_sys做测试//
//file.open("c_sys", ios::binary|ios::in, 0);
Sys_Info tmp[10];
for(int i = 0; i < 10; ++ i)
{
file.read((char*)&tmp[i], sizeof(Sys_Info));
}
Sys_Info sys_info;
file.seekg(5 * sizeof(Sys_Info), ios::beg);
file.read((char*)&sys_info, sizeof(Sys_Info));
file.close();

ofstream out("cpp_sys");
for(int i = 0; i < 10; ++ i)
{
Sys_Info t = {i, i * 2, "just-a-test", "2016-10-06"};
out << t.vesion << " " << t.sub_version << " "
<< t.info << " " << t.date << "\n";
}
out.close();

vector<Sys_Info> v_sys;
ifstream in("cpp_sys");
while(!in.eof())
{
Sys_Info t;
in >> t.vesion >> t.sub_version >> t.info >> t.date;
v_sys.push_back(t);
}
in.close();

ofstream bout("cpp_sys_binary", ios::binary);
for(int i = 0; i < 10; ++ i)
{
Sys_Info t = {i, i * 2, "just-a-test", "2016-10-06"};
//out << t.vesion << " " << t.sub_version << " "
// << t.info << " " << t.date << "\n";
bout.write((char*)&t, sizeof(Sys_Info));
}
bout.close();

vector<Sys_Info> v_syses;
ifstream bin("cpp_sys_binary", ios::binary);
while(!bin.eof())
{
Sys_Info t;
bin.read((char*)&t, sizeof(Sys_Info));
//in >> t.vesion >> t.sub_version >> t.info >> t.date;
v_syses.push_back(t);
}
bin.close();
}

测试

1
2
3
4
5
6
7
8
9
int main() 
{
//io_operator_binary();
//io_operator_ascii();
//operator_c_file();
operator_cpp_file();
system("pause");
return 0;
}