1

コンソールアプリケーションで大きなタブ区切りのテキストファイルを読み取った後、テキストファイルを書き込もうとしています。問題は、サーバー上でこのexeの多くのインスタンスを同時に実行すると、TextWriter.WriteLineでランタイムエラーが発生し、未処理の例外が原因でアプリケーションがクラッシュすることです。これはすべてのインスタンスで発生します。この動作の理由がわかりません。メモリを動的に使用するStringBuilderを使用していないためですか?

私のコードは次のとおりです:

 StreamReader sr = new StreamReader(@FilePath, System.Text.Encoding.Default);
 string mainLine = sr.ReadLine();
 string[] fileHeaders = mainLine.Split(new string[] { "\t" }, StringSplitOptions.None);
 string newLine = "";

 System.IO.StreamWriter outFileSw = new System.IO.StreamWriter(@outFile);

 while (!sr.EndOfStream)
 {
    mainLine = sr.ReadLine();
    string[] originalLine = mainLine.Split(new string[] { "\t" }, StringSplitOptions.None);

   newLine = "";
   for (int i = 0; i < fileHeaders.Length; i++)
   {
      if(fileHeaders[i].Trim() != "")
       newLine = newLine + fileHeaders[i].Trim() + "=" + originalLine[i].Trim() + "&";
   }

outFileSw.WriteLine(newLine.Remove(newLine.Length - 1));
FileInfo fileInfo = new FileInfo(@outFile);

  if (fileInfo.Length > (1.3 * 1024.0 * 1024.0 * 1024.0)) // greater than 1.3 GB  
  {
          outFileSw.Close();
          outFileNumber = outFileNumber + 1;
          outFileSw = new System.IO.StreamWriter(@outFile + outFileNumber.ToString() + ".txt");
  }

}
outFileSw.Dispose();
sr.Close();
sr.Dispose();

エラーの詳細は次のとおりです。

Exception Message: The specified network name is no longer available.

Stack Trace:    at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
 at System.IO.FileStream.WriteCore(Byte[] buffer, Int32 offset, Int32 count)
 at System.IO.FileStream.Write(Byte[] array, Int32 offset, Int32 count)
 at System.IO.StreamWriter.Flush(Boolean flushStream, Boolean flushEncoder)
 at System.IO.StreamWriter.Write(Char[] buffer, Int32 index, Int32 count)
 at System.IO.TextWriter.WriteLine(String value)
 at ExampleExe.ExampleProcess.FnFiles()


 Unhandled Exception: System.IO.IOException: The specified network name is no longer available.

 at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
 at System.IO.FileStream.WriteCore(Byte[] buffer, Int32 offset, Int32 count)
 at System.IO.FileStream.FlushWrite(Boolean calledFromFinalizer)
 at System.IO.FileStream.Dispose(Boolean disposing)
 at System.IO.FileStream.Finalize()

ありがとう、カヌ

4

1 に答える 1

1

これは、StringBuilder バッファーを使用した FileWriter です。メインスレッドがデータを蓄積し続ける間、別のスレッドを使用して書き込みます。一度に 10MB のバッファを書き込みます。バッファリングされたデータは Queue オブジェクトに保持されます。書き込みスレッドは、このキューから項目を削除し、File.AppendAllText メソッドを使用して完全に書き込みます。

private Queue<StringBuilder> writeQueue;
private bool isComplete;

public void FileWriter()
{
    this.isComplete = false;
    this.writeQueue = new Queue<StringBuilder>();

    var writer = new Action<string>(this.StartWriting);
    var writerAsync = writer.BeginInvoke(@"outputfile.txt", null, null);

    using (StreamReader sr = new StreamReader(@"inputfile.txt"))
    {
        var fileHeaders = sr.ReadLine()
            .Split('\t')
            .Where(i => !string.IsNullOrEmpty(i))
            .Select(j => j.Trim())
            .ToList();

        var buffer = new StringBuilder();
        while (!sr.EndOfStream)
        {
            var originalLine = sr.ReadLine()
                .Split('\t')
                .Where(i => !string.IsNullOrEmpty(i))
                .Select(j => j.Trim())
                .ToList();

            var line = new StringBuilder();
            //Must have same number of items
            if (originalLine.Count == fileHeaders.Count)
            {
                for (int i = 0; i < fileHeaders.Count(); i++)
                {
                    line.AppendFormat("{0}={1}&", fileHeaders[i], originalLine[i]);
                }
                line.AppendLine();
            }

            buffer.AppendLine(line.ToString());
            if (buffer.Length > 1024 * 1024 * 10)//approx 10MB 
            {
                lock (this.writeQueue)
                {
                    this.writeQueue.Enqueue(buffer);
                }
                buffer = new StringBuilder();
            }
        }
        //Queue any final remaining data
        if (buffer.Length>0) lock (this.writeQueue)
        {
            this.writeQueue.Enqueue(buffer);
        }
    }
    this.isComplete = true;
    writer.EndInvoke(writerAsync);
}

private void StartWriting(string outFilePath)
{
    while (!this.isComplete || this.writeQueue.Count > 0)
    {
        StringBuilder queuedItem;
        if (this.writeQueue.Count > 0)
        {
            lock (this.writeQueue)
            {
                queuedItem = this.writeQueue.Dequeue();
            }
            File.AppendAllText(outFilePath, queuedItem.ToString());
        }
        System.Threading.Thread.Sleep(5000); //Sleep 5sec
    }
}
于 2012-09-18T20:42:43.533 に答える