12

以下のコードを使用してファイルを約32GBに分割しようとしましたが、を取得しましたmemory exception

を使用してファイルを分割することを提案してくださいC#

string[] splitFile = File.ReadAllLines(@"E:\\JKS\\ImportGenius\\0.txt");

int cycle = 1;
int splitSize = Convert.ToInt32(txtNoOfLines.Text);
var chunk = splitFile.Take(splitSize);
var rem = splitFile.Skip(splitSize);

while (chunk.Take(1).Count() > 0)
{
    string filename = "file" + cycle.ToString() + ".txt";
    using (StreamWriter sw = new StreamWriter(filename))
    {
        foreach (string line in chunk)
        {
    sw.WriteLine(line);
        }
    }
    chunk = rem.Take(splitSize);
    rem = rem.Skip(splitSize);
    cycle++;
}
4

6 に答える 6

20

まず、File.ReadLines(.NET 4を使用していると仮定して)を使用して、すべてをメモリに読み込もうとしないようにする必要があります。次に、新しいファイルに「次の」行をいくつでも吐き出すメソッドを呼び出し続けます。

int splitSize = Convert.ToInt32(txtNoOfLines.Text);
using (var lineIterator = File.ReadLines(...).GetEnumerator())
{
    bool stillGoing = true;
    for (int chunk = 0; stillGoing; chunk++)
    {
        stillGoing = WriteChunk(lineIterator, splitSize, chunk);
    }
}

...

private static bool WriteChunk(IEnumerator<string> lineIterator,
                               int splitSize, int chunk)
{
    using (var writer = File.CreateText("file " + chunk + ".txt"))
    {
        for (int i = 0; i < splitSize; i++)
        {
            if (!lineIterator.MoveNext())
            {
                return false;
            }
            writer.WriteLine(lineIterator.Current);
        }
    }
    return true;
}
于 2012-07-26T12:06:13.390 に答える
8

すべての行をすぐに配列に読み込むのではなく、次のようにStremReader.ReadLineメソッドを使用します。

using (StreamReader sr = new StreamReader(@"E:\\JKS\\ImportGenius\\0.txt")) 
{
    while (sr.Peek() >= 0) 
    {
       var fileLine = sr.ReadLine();
       //do something with line
    }
}
于 2012-07-26T12:03:13.013 に答える
4
File.ReadAllLines

これにより、ファイル全体がメモリに読み込まれます。

大きなファイルを操作するには、必要なものだけをメモリに読み込んで、使い終わったらすぐに破棄する必要があります。

より良いオプションはFile.ReadLines、遅延列挙子を返すことです。データは、列挙子から次の行を取得するときにのみメモリに読み込まれます。複数の列挙を回避する場合(たとえば、使用しないでくださいCount())、ファイルの一部のみが読み取られます。

于 2012-07-26T12:05:11.180 に答える
3

を使用してすべてのファイルを一度に読み取る代わりに、foreachループFile.ReadAllLinesで使用して、必要に応じて行を読み取ります。File.ReadLines

foreach (var line in File.ReadLines(@"E:\\JKS\\ImportGenius\\0.txt"))
{
    // Do something
}

編集:無関係なメモでは、文字列の前に「@」を付けるときにバックスラッシュをエスケープする必要はありません。したがって、書き込み"E:\\JKS\\ImportGenius\\0.txt"または@"E:\JKS\ImportGenius\0.txt"のいずれかですが、@"E:\\JKS\\ImportGenius\\0.txt"冗長です。

于 2012-07-26T12:03:51.330 に答える
0

ここでの問題は、ファイル全体のコンテンツをで一度にメモリに読み込んでいることですFile.ReadAllLines()。あなたがする必要があるのは、File.OpenRead()小さなチャンクでFileStreamを開き、読み取り/書き込みを行うことです。

編集:実際、あなたの場合、ReadLineの方が明らかに優れています。他の回答を参照してください。:)

于 2012-07-26T12:02:52.330 に答える
0

StreamReade rを使用してファイルを読み取り、StreamWriterで書き込みます。

于 2012-07-26T12:03:06.120 に答える