如何将文本文件分解成更小的块(在 Unix 上使用 C++)?
Posted
技术标签:
【中文标题】如何将文本文件分解成更小的块(在 Unix 上使用 C++)?【英文标题】:How could I decompose a text file in smaller chunks (using C++ on Unix)? 【发布时间】:2021-11-29 17:17:44 【问题描述】:我正在做一项学校作业,我必须使顺序代码并发。代码所做的称为MapReduce,更具体地说,它计算所有单词在所有输入文件中出现的次数。
输入:包含所有要处理的文本文件的目录。 输出:包含带有结果的文本文件的目录。我们给出的实现由 4 个阶段组成;拆分地图洗牌和减少。前 3 个必须在它们之间同时发生,当所有 3 个都完成后,Reduce 就会发生。
并发,除了发生在这三个阶段之间,还必须发生在每个阶段内。为了做到这一点,我们被告知在一定数量的线程之间分配工作(每个阶段都有它的线程)。
从现在开始,我将只讨论拆分和地图阶段,它们是 我现在遇到问题的那些。
Split 和 Map 阶段将有一个线程用于每个“分区”(它们将具有相同数量的线程,因为每个 Split 线程都会关联一个 Map 线程),并且每个文件都有一个“分区”输入目录,除了大文件,我必须每 8 MB 生成一个“分区”。
这个异常是我要解决的问题,让我再解释一件事,我会解决的。
由于 Split 和 Map 必须具有相同数量的线程,我所做的是创建一个函数来计算必须创建的分区数量,以便能够告诉 Split 和 Map 有多少线程当我启动它们时,它们必须创建。
Split 线程所做的是获取它们已分配的“分区”(如果其大小小于 8 MB,它将是一个完整的文件)并将其逐行发送到其关联的 Map 线程(通过将它们写入线程安全队列)。
好的,这是我的问题,我想让 Map 线程(从提到的队列中读取并用每一行做他们的事情,现在并不重要)从队列中读取,直到他们读取 EOF,这意味着它关联的拆分线程已结束将其“分区”写入队列,但这仅适用于代表整个文件的“分区”。
所以,我的问题是:
-
我必须使用哪些选项将文件分解为 8 MB 的块?
如何让一个线程知道何时停止读取?
由于 Map 线程将在一小部分时间内尝试从队列中读取,但拆分线程尚未写入任何内容,我如何让它们“等待”队列中写入的内容?
这是计算需要多少线程的函数,我想让它生成一个文件描述符数组,每个“分区”包含一个文件描述符
int MapReduce::getSplitNum()
int split_num = 0;
char file_path[264];
DIR* dir = opendir(InputPath);
struct dirent* entity;
unsigned char isFile =0x8; // El valor que pren entity->d_type quan es tracta d'un fitxer
while ((entity = readdir(dir)) != NULL)
// Evitem el directori que conté els fitxers (.) i el directori anterior (..).
if( strcmp(entity->d_name, ".")!=0 && strcmp(entity->d_name, "..")!=0 && entity->d_type == isFile )
struct stat file_status;
sprintf(file_path,"%s/%s",InputPath, entity->d_name);
stat(file_path, &file_status);
long file_size = file_status.st_size;
// DEBUG: printf("Fitxer: %s\t Mida: %ld\n", entity->d_name, file_status.st_size);
if (file_size < MAX_SPLIT_SIZE)
split_num++;
else
long restant = file_size - MAX_SPLIT_SIZE;
split_num = split_num + 2; // Sumem 2 perquè al ser un arxiu gran com a mínim usarà 2 splits, més els que vagi afegint el bucle while.
while (restant > MAX_SPLIT_SIZE)
restant = restant - MAX_SPLIT_SIZE;
split_num++;
closedir(dir);
return split_num;
我想会有很多分解文件的方法,但我很想知道哪种方法是“好的做法”。
谢谢!
【问题讨论】:
【参考方案1】:也许是这样的?此函数将文件分解成相等的部分,最后一个是不同的(文件的其余部分)。这可以修改为将文件分解为特定大小的块。我刚刚写了这个,它似乎对我有用,但当然还需要进一步的测试。当然,我不确定这是否是最佳解决方案。这会产生 n 个名为 0, 1, ..., n 的文件。
#include <iostream>
#include <fstream>
void decompose_file (const std::string& filepath, const int number_of_files)
std::ifstream infile(filepath);
infile.seekg(0, std::ios::end);
size_t length = infile.tellg();
infile.seekg(0, std::ios::beg);
for (int i = 0; i < number_of_files; ++i)
char * buffer;
size_t chunk_size = 0;
if (i != number_of_files - 1)
chunk_size = length / number_of_files;
else
chunk_size = length - ((number_of_files - 1) * (length / number_of_files));
buffer = new char[chunk_size];
infile.read (buffer, chunk_size);
std::ofstream outfile (std::to_string(i));
if (outfile.is_open())
outfile.write(buffer, chunk_size);
outfile.close();
delete[] buffer;
infile.close();
int main (int argc, char* argv[])
decompose_file("my_file.txt", 4);
return 0;
【讨论】:
以上是关于如何将文本文件分解成更小的块(在 Unix 上使用 C++)?的主要内容,如果未能解决你的问题,请参考以下文章