【问题标题】:c# string array out of memoryc#字符串数组内存不足
【发布时间】:2014-12-18 10:09:43
【问题描述】:

我尝试获取 2 个 txt 文件并将 file1 中的每一行与 file2 中的每一行连接起来的行

示例: 文件1:

a
b

文件2:

c
d

结果:

a c

a d

b c

b d

这是代码:

{
        //int counter = 0;


        string[] lines1 = File.ReadLines("e:\\1.txt").ToArray();
        string[] lines2 = File.ReadLines("e:\\2.txt").ToArray();

        int len1 = lines1.Length;
        int len2 = lines2.Length;

        string[] names = new string[len1 * len2];
        int i = 0;
        int finish = 0;
        //Console.WriteLine("Check this");
        for (i = 0; i < lines2.Length; i++)
        {
            for (int j = 0; j < lines1.Length; j++)
            {
                names[finish] = lines2[i] + ' ' + lines1[j];
                finish++;
            }
        }

        using (System.IO.StreamWriter file = new System.IO.StreamWriter(@"E:\text.txt"))
        {
            foreach (string line in names)
            {
                // If the line doesn't contain the word 'Second', write the line to the file. 
                    file.WriteLine(line);
            }
        }
    }

我得到了这个例外:

“发生了“System.OutOfMemoryException”类型的未处理异常 在 ConsoleApplication2.exe 中”这一行:

字符串[] 名称 = 新字符串[len1 * len2];

有没有其他方法可以组合这两个文件而不会出现 OutOfMemoryException?

【问题讨论】:

  • 文件有多大?
  • 把你的for循环放在“Using”里面,而不是“names[finish] =”,直接把它写到文件中:“file.WriteLine(lines2[i] + ' ' + lines1[j]);", 这样您就不必创建字符串[] 名称
  • 合并后文件均为400,000,000行

标签: c# arrays string out-of-memory


【解决方案1】:

类似

using (var output = new StreamWriter(@"E:\text.txt"))
{
    foreach(var line1 in File.ReadLines("e:\\1.txt"))
    {
        foreach(var line2 in File.ReadLines("e:\\2.txt"))
        {
            output.WriteLine("{0} {1}", line1, line2);
        }
    }
}

除非行很长,否则应该避免OutOfMemoryException

【讨论】:

    【解决方案2】:

    看起来您想要一个笛卡尔积而不是串联。不要将所有行加载到内存中,而是使用ReadLinesSelectMany,这可能不会很快但会避免异常:

    var file1 = File.ReadLines("e:\\1.txt");
    var file2 = File.ReadLines("e:\\2.txt");
    
    var lines = file1.SelectMany(x => file2.Select(y => string.Join(" ", x, y));
    File.WriteAllLines("output.txt", lines);
    

    【讨论】:

      【解决方案3】:

      使用 StringBuilder 实例而不是连接字符串。字符串在 .Net 中是不可变的,因此对任何实例的每次更改都会创建一个新实例,从而消耗可用内存。 使名称成为 StringBuilder[] 名称并使用 Append 方法构造您的结果。

      【讨论】:

      • 但它会抛出string[] names = new string[len1 * len2];;它甚至没有到达for 循环。
      • 另一种解决方案是从文件中顺序读取行而不是同时读取它们,避免同时分配内存中的所有字符串。请参阅 StreamReader.ReadLine() 方法。
      【解决方案4】:

      如果您的文件很大(这是内存不足的原因),您不应该(永远)将完整的文件加载到内存中。尤其是结果文件(size = size1 * size2)会变得非常大。 我建议使用 StreamReader 逐行读取输入文件并 使用 StreamWriter 逐行写入结果文件。

      使用这种技术,您可以处理任意大的文件(只要结果适合您的硬盘)

      【讨论】:

        【解决方案5】:

        使用 stringbuilder 而不是通过“+”追加

        【讨论】:

          【解决方案6】:

          使用“列表名称”并将合并的行“添加”到列表中。 所以你不需要分配内存。

          【讨论】:

            猜你喜欢
            • 2012-02-03
            • 1970-01-01
            • 2020-09-30
            • 1970-01-01
            • 1970-01-01
            • 2013-02-13
            • 2017-06-19
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多