【问题标题】:looking for way to read and search file fast in c#寻找在 C# 中快速读取和搜索文件的方法
【发布时间】:2011-10-23 14:15:44
【问题描述】:

我有 100Mb 的文本文件,我需要检查每一行是否有特殊单词。 我正在寻找快速的方法。

所以我把文件分成 10 份:

public void ParseTheFile(BackgroundWorker bg)
    {

        Lines = File.ReadAllLines(FilePath);
        this.size = Lines.Length;
        chankSise=size/10;

        reports reportInst = new reports(bg,size);

        ParserThread [] ParserthreadArray = new ParserThread[10];

        for (int i = 0; i <ParserthreadArray.Length; i++)
        {
            ParserthreadArray[i] = new ParserThread((reportInst));
            ParserthreadArray[i].Init(SubArray(Lines,i * chankSise, chankSise), OutputPath);

        }

        Thread oThread0 = new Thread(ParserthreadArray[0].run);
        oThread0.IsBackground = true;
        Thread oThread1 = new Thread(ParserthreadArray[1].run);
        oThread1.IsBackground = true;
        Thread oThread2 = new Thread(ParserthreadArray[2].run);
        oThread2.IsBackground = true;
        Thread oThread3 = new Thread(ParserthreadArray[3].run);
        oThread3.IsBackground = true;
        Thread oThread4 = new Thread(ParserthreadArray[4].run);
        oThread4.IsBackground = true;
        Thread oThread5 = new Thread(ParserthreadArray[5].run);
        oThread5.IsBackground = true;
        Thread oThread6 = new Thread(ParserthreadArray[6].run);
        oThread6.IsBackground = true;
        Thread oThread7 = new Thread(ParserthreadArray[7].run);
        oThread7.IsBackground = true;
        Thread oThread8 = new Thread(ParserthreadArray[8].run);
        oThread8.IsBackground = true;
        Thread oThread9 = new Thread(ParserthreadArray[9].run);
        oThread9.IsBackground = true;

        oThread0.Start();
        oThread1.Start();
        oThread2.Start();
        oThread3.Start();
        oThread4.Start();
        oThread5.Start();
        oThread6.Start();
        oThread7.Start();
        oThread8.Start();
        oThread9.Start();

        oThread0.Join();
        oThread1.Join();
        oThread2.Join();
        oThread3.Join();
        oThread4.Join();
        oThread5.Join();
        oThread6.Join();
        oThread7.Join();
        oThread8.Join();
        oThread9.Join();

这是初始化方法:

public void Init(string [] olines,string outputPath)
    {
        Lines = olines;
        OutputPath = outputPath+"/"+"ThreadTemp"+threadID;
    }

这是 SubArray 方法:

public string [] SubArray(string [] data, int index, int length)
    {
        string [] result = new string[length];
        Array.Copy(data, index, result, 0, length);
        return result;
    }

每个线程都这样做:

 public void run()
    {

        if (!System.IO.Directory.Exists(OutputPath))
        {
            System.IO.Directory.CreateDirectory(OutputPath);
            DirectoryInfo dir = new DirectoryInfo(OutputPath);
            dir.Attributes |= FileAttributes.Hidden;
        }



        this.size = Lines.Length;
        foreach (string line in Lines)
        {



            bgReports.sendreport(allreadychecked);

            allreadychecked++;
            hadHandlerOrEngine = false;
            words = line.Split(' ');
            if (words.Length>4)
            {
                for (int i = 5; i < words.Length; i++)
                {
                    if (words[i] == "Handler" | words[i] == "Engine")
                    {

                        hadHandlerOrEngine = true;
                        string num = words[1 + i];
                        int realnum = int.Parse(num[0].ToString());
                        cuurentEngine = (realnum);
                        if (engineArry[realnum] == false)
                        {
                            File.Create(OutputPath + "/" + realnum + ".txt").Close();
                            engineArry[realnum] = true;

                        }
                        TextWriter tw = new StreamWriter(OutputPath + "/" + realnum + ".txt", true);
                        tw.WriteLine(line);
                        tw.Close();

                        break;
                    }
                }

            }

            if (hadHandlerOrEngine == false)
            {
                if (engineArry[cuurentEngine] == true)
                {
                    TextWriter tw = new StreamWriter(OutputPath + "/" + cuurentEngine + ".txt", true);
                    tw.WriteLine(line);
                    tw.Close();
                }

            }

        }

我的问题是有什么方法可以让这个运行更快

【问题讨论】:

标签: c# file text io


【解决方案1】:

您尚未显示您的 Init 方法,但目前看起来您的 每个 线程实际上将检查 所有 行。此外,看起来所有这些都可能试图写入相同的文件 - 并且没有以异常安全的方式(使用using 语句)这样做。

编辑:好的,现在我们可以看到Init,但我们看不到SubArray。大概它只是复制了数组的一部分。

如果您一开始就避免使用线程,这有多慢?是不是太慢了?你的绩效目标是什么?不过,使用 10 个线程似乎不太可能有帮助,因为那时它完全受内存/CPU 限制。 (你还应该尽量避免重复这么多代码来启动所有线程——你为什么不使用一个集合呢?)

【讨论】:

  • 如您所见,我附加了我的初始化方法,并将文件拆分到此处的每个线程:` for (int i = 0; i
  • @MoShe:这有多快,你需要多快?
【解决方案2】:

您可能受 IO 限制,所以我猜多线程不会有太大帮助。 (奇怪的是您的程序大部分时间都花在这里: Lines = File.ReadAllLines(FilePath); 而实际解析的时间并不多。但您应该测量一下。)事实上,您的 SubArray 拆分可能比您刚刚通过整个事情到一个解析器线程。

我会查看 MemoryMappedFile(如果这是 .NET 4),它可以通过不必复制所有源数据来帮助一些 IO。

【讨论】:

  • 也可以有两个线程:一个用于读取,一个用于写入。将 ReadAllLines 更改为小部分循环读取允许开始搜索而无需等待文件被完全读取。
【解决方案3】:

我想推荐一些可能有用的东西。正如有人所说,如果分配多个线程读取文件是没有意义的,因为这更多的是I/O 活动,在这种情况下会在OS FileManager 中排队。但绝对可以向任何可用的I/O completion thread 提出async I/O 请求来照顾。

现在在处理文件时,我建议您使用Memory-mapped files .内存映射文件非常适合需要重复/单独访问相当大文件的任意块文件 (view) 的场景。在您的场景中,如果块无序到达/处理,内存映射文件可以帮助您拆分/组装文件。 目前我没有方便的例子。看看下面的文章Memory Mapped Files

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多