3

在我的程序中,我需要编写大型文本文件(~300 mb),文本文件包含由空格分隔的数字,我正在使用此代码:

TextWriter guessesWriter = TextWriter.Synchronized(new StreamWriter("guesses.txt"));

private void QueueStart()
    {
        while (true)
        {
            if (writeQueue.Count > 0)
            {
                guessesWriter.WriteLine(writeQueue[0]);
                writeQueue.Remove(writeQueue[0]);
            }
        }
    }

private static void Check()
    {
        TextReader tr = new StreamReader("data.txt");

        string guess = tr.ReadLine();
        b = 0;
        List<Thread> threads = new List<Thread>();
        while (guess != null) // Reading each row and analyze it
        {
            string[] guessNumbers = guess.Split(' ');
            List<int> numbers = new List<int>();
            foreach (string s in guessNumbers) // Converting each guess to a list of numbers
                numbers.Add(int.Parse(s));

            threads.Add(new Thread(GuessCheck));
            threads[b].Start(numbers);
            b++;

            guess = tr.ReadLine();
        }
    }

    private static void GuessCheck(object listNums)
    {
        List<int> numbers = (List<int>) listNums;

        if (!CloseNumbersCheck(numbers))
        {
            writeQueue.Add(numbers[0] + " " + numbers[1] + " " + numbers[2] + " " + numbers[3] + " " + numbers[4] + " " + numbers[5] + " " + numbers[6]);
        }
    }

    private static bool CloseNumbersCheck(List<int> numbers)
    {
        int divideResult = numbers[0]/10;
        for (int i = 1; i < 6; i++)
        {
            if (numbers[i]/10 != divideResult)
                return false;
        }
        return true;
    }

文件 data.txt 包含这种格式的数据:(点表示遵循相同逻辑的更多数字)

1 2 3 4 5 6 1
1 2 3 4 5 6 2
1 2 3 4 5 6 3
.
.
.
1 2 3 4 5 6 8
1 2 3 4 5 7 1
.
.
.

我知道这不是很有效,我正在寻找一些关于如何让它更快的建议。如果您知道如何比 .txt 更有效地保存大量数字,我将不胜感激。

4

4 回答 4

4

提高效率的一种方法是在输出流上使用更大的缓冲区。您正在使用默认值,这可能为您提供 1k 缓冲区,但您不会看到小于 64k 缓冲区的最大性能。像这样打开你的文件:

new StreamWriter("guesses.txt", new UTF8Encoding(false, true), 65536)
于 2011-04-19T15:46:22.670 回答
2

与其逐行读写(ReadLine 和 WriteLine),不如读写大块数据(ReadBlock 和 Write)。这样,您访问磁盘的次数就会减少很多,并且性能会得到很大的提升。但是您需要管理每一行的结尾(查看 Environment.NewLine)。

于 2011-04-19T15:42:20.233 回答
1

使用 BinaryWriter 可以提高效率。然后你可以直接写出整数。这将允许您跳过读取时的解析步骤和写入时的 ToString 转换。

看起来您正在那里创建一堆线程。额外的线程会降低你的性能。您应该在单个线程上完成所有工作,因为线程是非常重量级的对象。

这是您的代码或多或少的直接转换,以使用 BinaryWriter。(这并不能解决线程问题。)

    BinaryWriter guessesWriter = new BinaryWriter(new StreamWriter("guesses.dat"));
    private void QueueStart()
    {
        while (true)
        {             
            if (writeQueue.Count > 0)
            {
                lock (guessesWriter)
                {
                    guessesWriter.Write(writeQueue[0]);
                }
                writeQueue.Remove(writeQueue[0]);
            }
        }
    }
    private const int numbersPerThread = 6;
    private static void Check()
    {
        BinaryReader tr = new BinaryReader(new StreamReader("data.txt"));
        b = 0;
        List<Thread> threads = new List<Thread>();
        while (tr.BaseStream.Position < tr.BaseStream.Length)
        {
            List<int> numbers = new List<int>(numbersPerThread);
            for (int index = 0; index < numbersPerThread; index++)
            {
                numbers.Add(tr.ReadInt32());
            }
            threads.Add(new Thread(GuessCheck));
            threads[b].Start(numbers);
            b++;
        }
    }
于 2011-04-19T15:34:11.683 回答
1

尝试在两者之间使用缓冲。有一个 BGufferdSTream。现在您使用非常低效的磁盘访问模式。

于 2011-04-19T15:37:07.020 回答