我正在开发一个模拟器程序,该程序在文件中频繁(> 10 次)写入小数据(<1kB)。我使用队列来存储这些数据,当这个队列有 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 条记录)与模拟暂停有关。