ищу способ читать и быстро искать файл в c # - PullRequest
2 голосов
/ 23 октября 2011

У меня есть текстовый файл размером 100 МБ, и мне нужно проверять каждую строку на наличие специального слова. Я ищу быстрый способ сделать это.

поэтому я делю файл на 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();

это метод Init:

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();
                }

            }

        }

мой вопрос, есть ли способ сделать это быстрее

Ответы [ 3 ]

7 голосов
/ 23 октября 2011

Вы не показали свой метод Init, но на данный момент похоже, что каждый ваших потоков будет фактически проверять все строк.Кроме того, похоже, что все они могут пытаться записывать в одни и те же файлы - и не делать это безопасным способом (используя операторы using) либо.может видеть Init, но мы не можем видеть SubArray.Предположительно, он просто копирует часть массива.

Насколько это медленно, если вы избегаете использовать потоки для запуска?Это определенно слишком медленно?Какова ваша цель производительности?Кажется маловероятным, что использование 10 потоков поможет, тем не менее, учитывая, что в этот момент оно полностью связано с памятью / ЦП.(Вам также следует избегать повторения такого большого количества кода для запуска всех потоков - почему вы не используете коллекцию для этого?)

6 голосов
/ 23 октября 2011

Вы, вероятно, связаны с IO, поэтому я предполагаю, что несколько потоков не сильно помогут. (Скорее всего, ваша программа проводит большую часть своего времени здесь: Lines = File.ReadAllLines (FilePath); и не так уж много времени на самом деле разбирает. Вы должны измерять, хотя.) На самом деле, ваше разбиение SubArray возможно медленнее, чем если бы вы только что передали все это в один поток синтаксического анализатора.

Я бы посмотрел на MemoryMappedFile (если это .NET 4), который должен помочь некоторым с вводом-выводом, не делая копий всех исходных данных.

1 голос
/ 23 октября 2011

Я бы хотел порекомендовать что-нибудь полезное.Как кто-то сказал, нет смысла назначать многопоточное чтение файла, так как это больше активности I/O, которая в этом случае помещается в очередь в OS FileManager.Но, безусловно, вы можете разместить запрос async I/O для любого доступного I/O completion thread для просмотра.

Теперь, когда дело доходит до обработки файла, я бы порекомендовал вам использовать Memory-mapped files.Файлы с отображением в памяти идеально подходят для сценариев, когда к произвольному фрагментному файлу (view) значительно большего файла необходимо обращаться неоднократно / по отдельности.В вашем сценарии файлы с отображением в памяти могут помочь вам разбить / собрать файл, если куски поступают / обрабатываются не по порядку.У меня нет удобных примеров на данный момент.Взгляните на следующую статью Файлы с отображением в памяти .

...