我有一个包含500万条记录(5列和500万行)的大型文本文件。文件图像如下所示
对于拆分,我使用了线程的概念。我创建了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();
}
}
代码工作正常。这里并行写入不同的文件。但是对于阅读,我已经将整个内容存储在一个数组中,然后通过不同的线程传递,以便使用索引进行写入。我想使用线程并行执行这两项任务(读取较大的文件并写入不同的小文件)。
答案 0 :(得分:3)
使用单个帖子,你几乎肯定会做得更好。
首先,必须顺序读取文本文件。没有捷径可以让你跳过去找到第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
进行通信。基本上,输入线程会将行放入队列,输出线程将从队列中读取并输出文件。从理论上讲,读取时间与写入时间重叠,但事实是队列填满了,读者最终不得不等待写作线程。你的某些性能会提高,但不会达到你所期望的水平。