2013-12-07 2 views
1

Я работаю над программой симулятора, которая записывает небольшие данные (< 1kB) часто (> 10 раз в секунду) в файл. Я использовал Очередь для хранения этих данных, и когда в этой очереди было 300 членов или более, она будет записывать данные в файл, хранящийся в zip-файле, и очищать очередь.C# - Использование protobuf для записи непосредственно в zip-файл

Проблемы после паузы или остановки симуляции (в обеих случаях flush будет называться), когда я извлечь почтовый файл и проверить выходные файлы (более специфический: Offsets.sdo) только данные из последнего шага записи (в моем коде, вызов flush) находится внутри файла. Также в ходе моделирования ZipFile, что я создаю (с outFile поле) имеет размер 0.

Мой файл писателя код:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.IO; 
using System.IO.Packaging; 
using System.Net.Mime; 
using ProtoBuf; 

namespace SEWS.History 
{ 
    class HistoryWriterEngine : HistoryEngine ,HistoryWriter 
    { 
     public static readonly string OUTPUT_DATA_FILE_NAME = "SimulationOutdata.sod"; 
     public static readonly string OFFSETS_FILE_NAME = "Offsets.sdo"; 

     #region buffer 
     private static readonly int MAXIMUM_BUFFER_SIZE = 300; // half a minute of simulation with 0.1s steps 
     private Queue<SEWS.SimulationEngine.SimulationOutputData> buffer = new Queue<SEWS.SimulationEngine.SimulationOutputData>(); 
     private Dictionary<string, PackagePart> packageParts = new Dictionary<string, PackagePart>(); 
     #endregion 

     #region IO 
     private ZipPackage outFile; 
     public override void initFile(string address) 
     { 
      if (outFile != null) 
      { 
       flush(); 
       closeFile(); 
      } 
      workingFile = address; 

      outFile = (ZipPackage)ZipPackage.Open(workingFile, FileMode.Create); 

      getNewStream(OUTPUT_DATA_FILE_NAME); 
      getNewStream(OFFSETS_FILE_NAME, MediaTypeNames.Text.Plain); 
     } 

     public override void closeFile() 
     { 
      flush(); 
      outFile.Flush(); 
      outFile.Close(); 
      outFile = null; 
     } 

     public Stream getNewStream(string fileName, string type = MediaTypeNames.Application.Octet) 
     { 
      PackagePart packagePart; 
      packagePart = outFile.CreatePart(
       PackUriHelper.CreatePartUri(new Uri(fileName, UriKind.Relative)), 
       type, 
       CompressionOption.SuperFast); 

      packageParts.Add(fileName, packagePart); 
      return packagePart.GetStream(); 
     } 

     public Stream getStream(string fileName) 
     { 
      if (packageParts.ContainsKey(fileName)) 
      { 
       return (packageParts[fileName] as PackagePart).GetStream(); 
      } 
      else 
      { 
       throw new NullReferenceException("No such file as " + fileName + " found."); 
      } 
     } 
     #endregion 

     #region HistoryWriterImpl 
     public void writeOutputData(SEWS.SimulationEngine.SimulationOutputData data) 
     { 
      buffer.Enqueue(data); 
      if (buffer.Count >= MAXIMUM_BUFFER_SIZE) 
      { 
       flush(); 
      } 
     } 
     System.Diagnostics.Stopwatch s = new System.Diagnostics.Stopwatch(); 
     public void flush() 
     { 
      Stream outStream = getStream(OUTPUT_DATA_FILE_NAME); 
      Stream offsetsStream = getStream(OFFSETS_FILE_NAME); 
      StreamWriter offsetsWriter = new StreamWriter(offsetsStream); 

      SEWS.SimulationEngine.SimulationOutputData currentData; 
      Console.WriteLine("Writing " + buffer.Count + " records"); 
      s.Restart(); 
      while (buffer.Count > 0) 
      { 
       currentData = buffer.Dequeue(); 
       Serializer.SerializeWithLengthPrefix(outStream, currentData, PrefixStyle.Base128, 1); 
       offsetsWriter.Write(
        new StringBuilder() 
        .Append(currentData.CurrentStep.ToString()) 
        .Append(' ') 
        .Append(currentData.CurrentTime.TimeSinceStart.ToString()) 
        .Append(' ') 
        .Append(outStream.Position) 
        .Append("\r\n") 
        .ToString() 
       ); 
      } 
      s.Stop(); 
      Console.WriteLine("Took " + s.ElapsedMilliseconds + " ms."); 

      outStream.Flush(); 
      offsetsWriter.Flush(); 
      offsetsStream.Flush(); 
      outStream.Close(); 
      offsetsWriter.Close(); 
      offsetsStream.Close(); 

      outFile.Flush(); 
     } 
     #endregion 
    } 
} 

Выход:

Writing 300 records 
Took 138 ms. 
Writing 300 records 
Took 18 ms. 
Writing 300 records 
Took 14 ms. 
Writing 300 records 
Took 14 ms. 
Writing 300 records 
Took 14 ms. 
Writing 41 records 
Took 5 ms. 

Первые 5 пишет автоматические и последний (41 запись) относится к паузе в симуляции.

+0

Выглядит слишком сложно, TL; DR. Но какая часть, по вашему мнению, означает «Открыть в режиме добавления»? Я вижу только созданные новые файлы, перезаписывая предыдущие. –

+0

@HenkHolterman я называю 'getNewStream' только один раз. эта функция создает файлы в архиве. –

+0

Один раз за 'flush()', поэтому каждый раз каждый раз 'buffer.Count> = MAXIMUM_BUFFER_SIZE' –

ответ

2

Ваш код повторно вызывает flush(), а намерение внутри flush() похоже на повторное использование файла через getStream().

Но у хвоста flush() есть звонок outStream.Close();, и из этого следует, что getStream() должен всегда создавать новый файл. В режиме Overwrite, по-видимому.

Смежные вопросы