C++:文件操作

文件操作是个啥大家都懂了,下面我给出几个文件操作示例
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
//在windows平台下避免函数不安全报错而定义的一个宏
#define _CRT_SECURE_NO_WARNINGS
#include <stdio .h>
#include <stdlib .h>
#include <string .h>
 
int main () {
    //fopen第二个参数有以下几种取值模式
    //首先是打开方式,从以下打开方式中任选一种或组合
    //    a(append)    以写方式打开文件并移动文件指针到文件尾部
    //    r(read)      以读方式打开文件,文件指针位置未知建议打开后重置文件指针
    //    w(write)     以写方式打开文件并清空文件内容
    //然后是数据类型,默认为文本方式,如果加上b则为二进制方式,区别在于,在windows环境下,不加b(文本模式)会造成:
    //    以文本方式读文件时,换行符\r\n被读成\n
    //    以文本方式写文件时,换行符\n被写成\r\n
    //最后是扩展方式,如果带+号代表如果文件不存在则新建。但我实际测试结果为,带不带+号并没什么卵用
    //示例:第二个参数为 rwb+ 代表以二进制读写方式打开文件,如果文件不存在则新建
    FILE *f = fopen ("a.txt", "rw+");
    if (f) {
        char *data = "hello";
        //写文件,不多做解释
        fwrite (data, strlen(data), 1, f);
 
        //移动文件指针到结束位置,第三个参数三种取值分别为 SEEK_SET(开始位置)、SEEK_CUR(当前位置)、SEEK_END(结束位置)
        fseek (f, 0, SEEK_END);
 
        //获取文件指针的偏移,这时候指针在末尾,含义就代表文件长度。
        //值得注意的是如果以文本方式并且有回车并且读取文件时,文件长度与读取的字节数不一样,原因上面有说明
        int len = ftell (f);
 
        //这行代码含义为移动文件指针到文件起始位置,等价于 fseek (f, 0, SEEK_SET);
        rewind (f);
 
        //其他文件操作函数不做说明,这儿给出常用列表
        //fwrite     输出一块数据到文件
        //fprintf    格式化输出到文件
        //fputc      输出一个字节到文件
        //fputs      输出一串字符串到文件
        //fread      读取一块数据到文件
        //fscanf     从文件格式化输入
        //fgetc      从文件中读取一个字符,因为文件可能结束,所以返回类型为int。如果值为 EOF 代表文件已读到最后
        //fgets      从文件中读取一串字符串
        //feof       判断文件指针是否在文件末尾
 
        //如果为多个程序同时访问文件的情况时建议加上这句。含义代表将文件缓冲区内容刷新到文件中
        //不加可能出现文件更新不及时的现象,不管是否调用这句,关闭文件时始终会刷新的
        fflush (f);
 
        //关闭文件
        fclose (f);
    } else {
        printf ("打开文件失败!");
    }
 
    system ("pause");
    return 0;
}</string></stdlib></stdio>

2、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
#include <iostream>
#include <fstream>
#include <string>
 
using namespace std;
 
int main () {
    //以读方式打开文件,第二个参数可以不填,默认 ios::in ,有以下几种取值方式
    //ios::in        代表读文件
    //ios::binary    代表二进制模式
    ifstream ifs ("a.txt");
    string s;
 
    //按分隔方式读文件并打印。分隔符可以为空格符、制表符、回车符三种,这种读取方式并不好
    //while (ifs >> s) cout << s << endl;
 
    //按行方式读取文件,这种方式值得推荐
    while (getline (ifs, s)) cout << s << endl;
 
    //读取整个文件至 std::string 中
    std::string str ((std::istreambuf_iterator<char> (ifs)), std::istreambuf_iterator<char> ());
    cout << str << endl;
 
    //按流方式读取文件还有个好处,那就是可以直接将文件内容输入/输出到结构体中,比较方便
    //其他读文件方式严重不推荐比如什么 ifs.get (); 什么什么的
 
    //获取当前文件流指针位置,对于 std::ofstream 使用 tellp 函数
    streampos p = ifs.tellg ();
 
    //移动文件指针到起始位置,对于 std::ofstream 使用 seekp 函数
    //有三个参数 含义你们都造含义 ios_base::beg、ios_base::cur、ios_base::end
    ifs.seekg (0, ios_base::beg);
 
    //关闭文件
    ifs.close ();
 
    //以写方式打开文件,第二个参数可以不填,默认 ios::out ,有以下几种取值方式
    //ios::out       代表写文件
    //ios::app       代表增加(append),含义见C里面的a模式
    //ios::binary    代表二进制模式,可以和以上任意一种方式组合使用,比如 ios::app | ios::binary 
    //               如果需要组合 out 那么可以直接简写为 ios::binary
    ofstream ofs ("a.txt");
 
    //愉快地写文件咯。注意回车最好写成 std::endl
    ofs << "asdasdasdasdasd";
 
    //关闭文件
    ofs.close ();
 
    return 0;
}

3、Win32 API 文件操作

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
#include <Windows.h>
#include <tchar.h>
 
int main () {
    //打开文件,oh my god 好多参数吓死本宝宝了
    HANDLE hFile = CreateFile (
        _T ("a.txt"),
        GENERIC_READ | GENERIC_WRITE,//文件读写方式,图省事可以 GENERIC_ALL
        FILE_SHARE_READ | FILE_SHARE_WRITE,//共享方式,如果不希望共享访问那么这儿传0
        NULL,//安全描述符,一般情况下不要设置
        OPEN_ALWAYS,//文件创建方式,有以下几种取值:
            //CREATE_NEW           如果文件存在则调用失败
            //CREATE_ALWAYS        不管文件是否存在始终创建新文件,如果文件原有数据将被覆盖
            //OPEN_EXISTING        打开文件,如果文件不存在则打开失败
            //OPEN_ALWAYS          如果文件存在则打开,如果文件不存在则新建
            //TRUNCATE_EXISTING    与 GENERIC_WRITE 同时存在,一旦打开则文件被截短为0字节
        FILE_ATTRIBUTE_NORMAL,//文件属性,如果想玩玩隐藏文件之类的那么输入 FILE_ATTRIBUTE_ 然后看自动提示
        NULL//文件模板句柄,传NULL就行了
    );
 
    //Windows平台文件调用传递路径,仅做参考,看不懂可以不用管:
    //CreateFile -> ZwCreateFile -> NtCreateFile -> 汇编sysenter指令进入驱动层 -> ZwCreateFile -> NtCreateFile -> IoCreateFile -> Irp消息 -> 捕获Irp消息的钩子,如果未处理则继续传递 -> 文件系统驱动 -> 硬件抽象层驱动 -> 硬件
 
    //小技巧:常数类型在判断时写在前面,避免等号写成一个时出错并且还找不到bug
    if (INVALID_HANDLE_VALUE != hFile) {
        char* data = "aaaaaaaaaaaaaaaaaaaaa";
 
        //写文件,参数太少不解释
        DWORD dw;//已写字节数
        WriteFile (hFile, data, lstrlenA(data), &dw, NULL);
 
        //设置文件指针,第四个参数的三种取值方式:FILE_BEGIN、FILE_CURRENT、FILE_END
        SetFilePointer (hFile, 0, NULL, FILE_BEGIN);
 
        //读文件
        char buf [MAX_PATH];
        ReadFile (hFile, buf, 10, &dw, NULL);
 
        //关闭文件
        CloseHandle (hFile);
    }
 
    return 0;
}

以上三个为阻塞模型文件操作示例,相对来说写法简单,除了阻塞文件操作之外还有种单线程异步操作模型,这种模型相对较复杂,但可以使IO效率最大化,对于高手来说值得尝试。
具体写法为:Windows平台上,IO函数调用全部加上Ex,比如 WriteFileEx ,这类函数将会立即返回,并且在IO操作完毕后通过异步回调通知主线程;其次是跨平台Boost.afio库,github地址为 https://github.com/ned14/boost.afio,写法类似异步boost.asio。

Published by

fawdlstty

又一只萌萌哒程序猿~~

发表评论

电子邮件地址不会被公开。 必填项已用*标注