gpt4 book ai didi

c# - 使用 C# 中的线程将大型文本文件(500 万条记录)并行拆分为较小的文件

转载 作者:太空宇宙 更新时间:2023-11-03 23:13:50 25 4
gpt4 key购买 nike

我有一个包含 500 万条记录(5 列和 500 万行)的大型文本文件。文件图片如下所示

Large text file to be split

对于拆分,我使用了线程的概念。我创建了 10 个线程来拆分较大的文件。我在读取较大文件时使用字符串数组来存储值。代码如下所示。

class Program
{
const string sourceFileName = @"C:\Users\Public\TestFolder\ThreadingExp\NewMarketData.txt";
const string destinationFileName = @"C:\Users\Public\TestFolder\ThreadingExp\NewMarketData-Part-{0}.txt";

static void Main(string[] args)
{
int[] index = new int[20];
index[0] = 0;
for(int i=1;i<11;i++)
{
index[i] = index[i-1]+500000;
}

//Reading Part
var sourceFile = new StreamReader(sourceFileName);
string[] ListLines = new string[5000000];
for (int i = 0; i < 5000000; i++)
{
ListLines[i] = sourceFile.ReadLine();
}

//Creating array of threads
Thread[] ArrayofThreads = new Thread[10];
for (int i = 0; i < ArrayofThreads.Length; i++)
{
ArrayofThreads[i] = new Thread(() => Writing(ListLines,index[i], index[i+1]));
ArrayofThreads[i].Start();
}

for (int i = 0; i < ArrayofThreads.Length; i++)
{
ArrayofThreads[i].Join();
}
}
static void Writing(string[] array, int a, int b)
{
//Getting the thread number
int id= Thread.CurrentThread.ManagedThreadId;

var destinationFile = new StreamWriter(string.Format(destinationFileName,id));

string line;
for (int i = a; i< b;i++ )
{
line = array[i];
destinationFile.WriteLine(line);
}

destinationFile.Close();
}

}

代码运行良好。写入不同的文件在这里是并行完成的。但是为了阅读,我将所有内容存储在一个数组中,然后通过不同的线程使用索引进行写入。我想使用线程并行执行这两项任务(读取较大的文件并写入不同的小文件)。

最佳答案

几乎可以肯定,使用单线程执行此操作会更好。

首先,您必须按顺序读取文本文件。没有捷径可以让您跳过并找到第 500,000 行,而无需先阅读前面的 499,999 行。

其次,即使您可以这样做,磁盘驱动器一次也只能处理一个请求。它不能同时从两个地方读取。因此,当您正在读取文件的一部分时,想要读取文件另一部分的线程只是坐在那里等待磁盘驱动器。

最后,除非您的输出文件位于单独的驱动器上,否则您会遇到与读取相同的问题:磁盘驱动器一次只能做一件事。

所以你最好从简单的事情开始:

const int maxLinesPerFile = 5000000;
int fileNumber = 0;
var destinationFile = File.CreateText("outputFile"+fileNumber);

int linesRead = 0;
foreach (var line in File.ReadLines(inputFile))
{
++linesRead;
if (linesRead > maxLinesPerFile)
{
destinationFile.Close();
++fileNumber;
destinationFile = File.CreateText("outputFile"+fileNumber);
}
destinationFile.WriteLine(line);
}
destinationFile.Close();

如果您的输入和输出文件位于不同的驱动器上,您可以通过使用两个线程来节省一点时间:一个用于输入,一个用于输出。他们将使用 BlockingCollection 进行通信。基本上,输入线程会将行放入队列,输出线程将从队列中读取并输出文件。理论上这会使读取时间与写入时间重叠,但事实是队列已满,读取器最终不得不在写入线程上等待。您获得了一些性能提升,但远未达到您的预期。

关于c# - 使用 C# 中的线程将大型文本文件(500 万条记录)并行拆分为较小的文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37974407/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com