使用c++读取大小为40G的txt文件,并将其中的数据进行升序排序,并输出到指定txt文件之中
时间: 2023-06-25 08:05:49 浏览: 76
处理这么大的文件,需要考虑到内存的限制,因此我们可以采用“外排序”的思路,即将文件分割成多个小文件,对每个小文件进行排序,最终将所有排序好的小文件合并成一个大文件。
以下是一个参考实现:
```c++
#include <iostream>
#include <fstream>
#include <algorithm>
#include <vector>
#include <queue>
#include <cstdio>
#include <cstring>
using namespace std;
const int MAXN = 1e7 + 5; // 每个小文件最多存储的数据量
const int MAXM = 1e6 + 5; // 外排的缓冲区大小
int N; // 数据总量
char inputPath[100], outputPath[100];
// 读取一个小文件并将其中的数据排序
void sortFile(int fileIndex) {
char inputName[100], outputName[100];
sprintf(inputName, "tmp%d.txt", fileIndex);
sprintf(outputName, "tmp%d_sorted.txt", fileIndex);
ifstream fin(inputName);
vector<int> v;
while (!fin.eof()) {
int x;
fin >> x; // 读入一个数
v.push_back(x);
if (v.size() == MAXN) {
sort(v.begin(), v.end()); // 对该小文件中的数据进行排序
ofstream fout(outputName, ios::app); // 将排序好的结果写入新文件
for (int i = 0; i < v.size(); ++i) {
fout << v[i] << endl;
}
fout.close();
v.clear();
}
}
if (!v.empty()) {
sort(v.begin(), v.end()); // 对该小文件中的数据进行排序
ofstream fout(outputName, ios::app); // 将排序好的结果写入新文件
for (int i = 0; i < v.size(); ++i) {
fout << v[i] << endl;
}
fout.close();
v.clear();
}
fin.close();
}
// 从多个小文件中选择最小的数
int getMin(vector<ifstream*>& fin, vector<int>& curVal) {
int minVal = INT_MAX, minIdx = -1;
for (int i = 0; i < fin.size(); ++i) {
if (!fin[i]->eof() && curVal[i] < minVal) {
minVal = curVal[i];
minIdx = i;
}
}
return minIdx;
}
// 将所有排序好的小文件合并成一个大文件
void mergeFiles() {
vector<ifstream*> fin;
vector<int> curVal;
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq; // 小根堆维护每个文件当前最小的数
// 打开所有排序好的小文件
for (int i = 0; i < N / MAXN + 1; ++i) {
char fileName[100];
sprintf(fileName, "tmp%d_sorted.txt", i);
fin.push_back(new ifstream(fileName));
curVal.push_back(-1);
}
// 初始化小根堆
for (int i = 0; i < fin.size(); ++i) {
if (!fin[i]->eof()) {
int x;
*fin[i] >> x;
curVal[i] = x;
pq.push(make_pair(x, i));
}
}
// 逐个输出最小值,并将对应文件的下一个数插入小根堆
ofstream fout(outputPath);
while (!pq.empty()) {
pair<int, int> p = pq.top();
pq.pop();
fout << p.first << endl;
int fileIdx = p.second;
if (!fin[fileIdx]->eof()) {
int x;
*fin[fileIdx] >> x;
curVal[fileIdx] = x;
pq.push(make_pair(x, fileIdx));
}
}
// 关闭所有打开的文件
for (int i = 0; i < fin.size(); ++i) {
fin[i]->close();
}
}
int main() {
cout << "请输入文件路径:" << endl;
cin >> inputPath;
cout << "请输入输出文件路径:" << endl;
cin >> outputPath;
// 统计数据总量
ifstream fin(inputPath);
int x;
while (!fin.eof()) {
fin >> x;
++N;
}
fin.close();
// 将大文件分割成多个小文件
ifstream fin2(inputPath);
vector<int> v;
int fileIndex = 0;
while (!fin2.eof()) {
fin2 >> x;
v.push_back(x);
if (v.size() == MAXN) {
sort(v.begin(), v.end()); // 对该小文件中的数据进行排序
char fileName[100];
sprintf(fileName, "tmp%d.txt", fileIndex++);
ofstream fout(fileName);
for (int i = 0; i < v.size(); ++i) {
fout << v[i] << endl; // 将排序好的结果写入新文件
}
fout.close();
v.clear();
}
}
if (!v.empty()) {
sort(v.begin(), v.end()); // 对该小文件中的数据进行排序
char fileName[100];
sprintf(fileName, "tmp%d.txt", fileIndex++);
ofstream fout(fileName);
for (int i = 0; i < v.size(); ++i) {
fout << v[i] << endl; // 将排序好的结果写入新文件
}
fout.close();
v.clear();
}
fin2.close();
// 对每个小文件进行排序
for (int i = 0; i < N / MAXN + 1; ++i) {
sortFile(i);
}
// 将所有排序好的小文件合并成一个大文件
mergeFiles();
cout << "排序完成!" << endl;
return 0;
}
```
注:以上代码仅供参考,具体实现可能需要根据实际情况进行调整。
阅读全文