小さなデータ (<1kB) をファイルに頻繁に (> 1 秒間に 10 回) 書き込むシミュレーター プログラムに取り組んでいます。これらのデータを格納するために Queue を使用しました。このキューに 300 人以上のメンバーがいる場合、zip ファイルに格納されたファイルにデータを書き込み、キューをクリアします。
問題は、シミュレーションを一時停止または停止した後 (どちらの場合flush
も呼び出されます)、zip ファイルを抽出して出力ファイルをチェックするときです (より具体的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 レコード) はシミュレーションの一時停止に関するものです。