20240627 处理超大文件方案
明昧 Lv7

如何读取和处理和输出一个拥有超多数据的文件

C++提供了一些用于读写大文件的库和技术,例如:

  1. 使用fstream库:C++标准库中的fstream库提供了对文件的读写操作。可以使用ifstream类进行文件的读取,使用ofstream类进行文件的写入。通过逐行或逐个字符读写文件,可以避免一次性加载整个文件到内存中。
  2. 使用mmap函数:mmap函数可以将文件映射到内存中,通过内存映射的方式进行读写操作。这种方式可以减少对内存的直接访问,提高读写效率。
  3. 使用缓冲区:可以使用缓冲区来减少对磁盘的频繁读写操作。通过设置适当的缓冲区大小,可以在一定程度上减少内存的使用量。
  4. 使用多线程:可以使用多线程来并行读写大文件,提高读写效率。通过将文件分成多个块,每个线程负责读取或写入一个块,可以充分利用多核处理器的性能。
  5. 使用异步IO:C++11引入了异步IO机制,可以通过异步方式进行文件的读写操作。异步IO可以在读写操作进行的同时执行其他任务,提高程序的并发性能。

https://cloud.tencent.com/developer/information/读写大文件C%2B%2B(内存过载)-video

使用mmap函数

https://www.cnblogs.com/TenosDoIt/p/3157596.html

http://blog.csdn.net/wcyoot/article/details/7363393

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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include <cstringt.h>
#include<vector>
#include<windows.h>
#include <ctime>
using namespace std;

const char* charString = "o6.txt";

LPCWSTR ConvertToLPCWSTR(const char* charArray) {
// 获取转换后的字符串长度
int len = MultiByteToWideChar(CP_ACP, 0, charArray, -1, NULL, 0);

// 为转换后的字符串分配内存
wchar_t* wString = new wchar_t[len];

// 执行转换
MultiByteToWideChar(CP_ACP, 0, charArray, -1, wString, len);

return wString;
}


int main()
{

LPCWSTR wideString = ConvertToLPCWSTR(charString);

clock_t start, finish;
//------------------------------------------------------内存映射方法;
start = clock();
//创建或打开文件内核对象;
HANDLE fileH = CreateFile(
wideString,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);

if (fileH == INVALID_HANDLE_VALUE)
{
cout << "error in CreateFile" << endl;
return -1;
}

const char* a = "Resource";
LPCWSTR b = ConvertToLPCWSTR(a);

//创建一个文件映射内核对象;
HANDLE mapFileH = CreateFileMapping(fileH,
NULL,
PAGE_READWRITE,
0,
0,
b);

if (mapFileH == NULL)
{
cout << "error in CreateFileMapping" << endl;
return -1;
}

//将文件数据映射到进程的地址空间;
char* mapH = (char*)MapViewOfFile(
mapFileH,
FILE_MAP_ALL_ACCESS,
0,
0,
0);

if (mapH == NULL)
{
cout << "error in MapViewOfFile" << endl;
return -1;
}

//读取数据;
char* buf = mapH;
double k;
int times = 300000*34;
for (int i = 1; i <= times; i++)
{
k = atof(buf);
buf = strstr(buf + 9, " ");
//cout<<k<<endl;
}


//关闭句柄;
UnmapViewOfFile(mapH);
CloseHandle(mapFileH);
CloseHandle(fileH);

finish = clock();
//打印耗时;
cout << "time:" << (double)(finish - start) / CLOCKS_PER_SEC << endl;

//------------------------------------------------------传统方法;
start = clock();

FILE* fp = fopen(charString, "r");
if (fp == NULL)
{
cout << "error in fopen" << endl;
return -1;
}
for (int i = 1; i <= times; i++)
{
fscanf(fp, "%lf", &k);
}
fclose(fp);

finish = clock();
cout << "time:" << (double)(finish - start) / CLOCKS_PER_SEC << endl;

delete[] wideString;

return 0;
}

缩小范围映射完全符合规范的小范围数据是ok的

但是奇怪的就是

我自己的生成数据的脚本写出来的数据总是不符合规范

反正读到后面指针老是为空的时候还在读取数据西巴


image-20240628131202516

300000*33之前的数据都没问题

300000*33之后的数据有问题,很大的问题

是不是少生成一行数据

傻了,后面生成的数据没调用过

生成超多数据的python脚本

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
import random



def generate_floats():
"""生成一个包含300000行,每行34个浮点数的列表。"""
data = []
i = 0
for _ in range(300000):
for _ in range(34):
line = ' '.join(f"{random.randint(0, 9)}.{random.randint(0, 9999999):07d}")
i+=1

print(i)
return data

def save_to_file(data, filename):
"""将生成的浮点数列表保存到文件中。"""
with open(filename, 'w') as file:
file.write(' '.join(data))

if __name__ == "__main__":
data = generate_floats()
save_to_file(data, 'o7.txt')



 Comments
Comment plugin failed to load
Loading comment plugin
Powered by Hexo & Theme Keep
Unique Visitor Page View