1

小さなデータ (<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 レコード) はシミュレーションの一時停止に関するものです。

4

1 に答える 1

2

あなたのコードは繰り返し呼び出しますがflush()、内部の意図flush()は を介し​​てファイルを再利用することですgetStream()

しかし、最後にflush()呼び出しがoutStream.Close();あり、 getStream()常に新しいファイルを作成する必要があります。どうやら上書きモードで。

于 2013-12-07T12:36:56.867 に答える