5

配列モデル オブジェクトをバイナリ ストリームにシリアル化したいと考えています。モデル クラスには、主に文字列と整数のプロパティがあります。

クラスを [Serializable] としてマークし、バイナリ フォーマッタを使用できると思いますが、転送用のファイルをできるだけ小さくすることが優先事項であることを念頭に置いて、これが最善の方法であると思われるかどうかを知りたいと思います。低帯域幅接続を介して(ファイルも圧縮/解凍できます)。

ファイルには数千のレコードが含まれる可能性があるため、理想的には、ファイル全体を一度にメモリに保持することなく、ディスクに追加してレコードごとにディスクから読み取ることができるようにしたいと考えています。

したがって、私の優先事項は次のとおりです。小さなファイルサイズと効率的なメモリ使用。

おそらく、これには事前に作成されたフレームワークがありますか?XMLやCSVファイルで簡単にできそう!うまくいけば、それもカスタムバイナリ形式です。

ありがとう

4

6 に答える 6

6

非常に効率的なprotobuf.netをお勧めします。

そうは言っても、これはコレクション内の個々のオブジェクトのシリアル化/逆シリアル化を処理できません。その部分は自分で実装する必要があります。

  • オブジェクトを個別のファイルとしてフォルダに格納します。ファイル名には参照が含まれるため、名前に基づいて必要なオブジェクトを見つけることができます。

  • もう 1 つは、ファイルは 1 つですが、ファイル内のすべてのオブジェクトとそれらの位置のリストを保持するインデックス ファイルを保持する方法です。ファイルの途中にあるオブジェクトを保存する場合、他のすべてのアドレスを移動する必要があり、おそらく b ツリーの方が効果的であるため、これははるかに複雑です。

于 2011-03-18T15:36:34.470 に答える
2

もう 1 つのオプションは、固定幅のテキスト ファイル形式にシリアル化し、ZIP に圧縮を処理させることです。固定幅とは、 MemoryMappedFileを使用して、ファイル全体をメモリにロードすることなく各レコードを簡単に処理できることを意味します。

于 2011-03-18T15:43:06.480 に答える
1

BinaryFormatterを使用できます。これは小さなファイルが必要な場合に適したソリューションですが、それがドメインにとって最適なソリューションであるかどうかは、あなただけが知っています。ただし、一度に 1 つのレコードを読み取ることはできないと思います。

現時点で私が持っている唯一のサンプル コードはDataSetです。これらの拡張メソッドは、カスタム DataSet を (逆) シリアル化します。私の記憶が正しければ、BinaryFormatter を使用できる型を持つ最も簡単な方法でした。

public static TDataSet LoadBinary<TDataSet>(Stream stream) where TDataSet : DataSet
{
    var formatter = new BinaryFormatter();
    return (TDataSet)formatter.Deserialize(stream);
}

public static void WriteBinary<TDataSet>(this TDataSet dataSet, Stream stream) where TDataSet : DataSet
{
    dataSet.RemotingFormat = SerializationFormat.Binary;
    var formatter = new BinaryFormatter();
    formatter.Serialize(stream, dataSet);
}

また、シリアライゼーションを処理する .NET の新しい「標準」方法であるDataContractSerializerを確認することもできます(C# 4.0 In A Nutshell、Albahari & Albahari によると)。その場合は、ベスト プラクティス: データ コントラクトのバージョン管理もお読みください。以下は、XML および JSON で (デ) シリアル化する方法の例ですが、(小さなファイルが必要なため) 状況に直接適用することはできません。ただし、ファイルを圧縮することはできます。

/// <summary>
/// Converts this instance to XML using the <see cref="DataContractSerializer"/>.
/// </summary>
/// <typeparam name="TSerializable">
/// A type that is serializable using the <see cref="DataContractSerializer"/>.
/// </typeparam>
/// <param name="value">
/// The object to be serialized to XML.
/// </param>
/// <returns>
/// Formatted XML representing this instance. Does not include the XML declaration.
/// </returns>
public static string ToXml<TSerializable>(this TSerializable value)
{
    var serializer = new DataContractSerializer(typeof(TSerializable));
    var output = new StringWriter();
    using (var writer = new XmlTextWriter(output) { Formatting = Formatting.Indented })
    {
        serializer.WriteObject(writer, value);
    }
    return output.GetStringBuilder().ToString();
}

/// <summary>
/// Converts this instance to XML using the <see cref="DataContractSerializer"/> and writes it to the specified file.
/// </summary>
/// <typeparam name="TSerializable">
/// A type that is serializable using the <see cref="DataContractSerializer"/>.
/// </typeparam>
/// <param name="value">
/// The object to be serialized to XML.
/// </param>
/// <param name="filePath">Path of the file to write to.</param>
public static void WriteXml<TSerializable>(this TSerializable value, string filePath)
{
    var serializer = new DataContractSerializer(typeof(TSerializable));
    using (var writer = XmlWriter.Create(filePath, new XmlWriterSettings { Indent = true }))
    {
        serializer.WriteObject(writer, value);
    }
}

/// <summary>
/// Creates from an instance of the specified class from XML.
/// </summary>
/// <typeparam name="TSerializable">The type of the serializable object.</typeparam>
/// <param name="xml">The XML representation of the instance.</param>
/// <returns>An instance created from the XML input.</returns>
public static TSerializable CreateFromXml<TSerializable>(string xml)
{
    var serializer = new DataContractSerializer(typeof(TSerializable));

    using (var stringReader = new StringReader(xml))
    using (var reader = XmlReader.Create(stringReader))
    {
        return (TSerializable)serializer.ReadObject(reader);
    }
}

/// <summary>
/// Creates from an instance of the specified class from the specified XML file.
/// </summary>
/// <param name="filePath">
/// Path to the XML file.
/// </param>
/// <typeparam name="TSerializable">
/// The type of the serializable object.
/// </typeparam>
/// <returns>
/// An instance created from the XML input.
/// </returns>
public static TSerializable CreateFromXmlFile<TSerializable>(string filePath)
{
    var serializer = new DataContractSerializer(typeof(TSerializable));

    using (var reader = XmlReader.Create(filePath))
    {
        return (TSerializable)serializer.ReadObject(reader);
    }
}

public static T LoadJson<T>(Stream stream) where T : class
{
    var serializer = new DataContractJsonSerializer(typeof(T));
    object readObject = serializer.ReadObject(stream);
    return (T)readObject;
}

public static void WriteJson<T>(this T value, Stream stream) where T : class
{
    var serializer = new DataContractJsonSerializer(typeof(T));
    serializer.WriteObject(stream, value);
}
于 2011-03-18T15:34:34.647 に答える
1

Sql Server Compact を使用してオブジェクトをシリアル化せずにオブジェクトとして格納することをお勧めします。これは非常に軽量で非常に高速です。サーバーで多くの要求を処理する際に高いペイロードで使用しました。

また、データをバイナリ形式 (シリアル化) で保存することはお勧めしません。保存しようとしているオブジェクトを変更する場合、非常に面倒だからです。コレクション全体を逆シリアル化する必要があるため、保存しているものを確認する必要がある場合も苦痛です。

送信に関しては、必要に応じて zip 圧縮による XML シリアル化を使用することを好みます。XML 形式を使用すると、送信内容を調べたり、テストを行う必要がある場合に、デバッグがはるかに簡単になります。

于 2011-03-18T15:38:00.460 に答える
0

小さくしたい場合は自分で作ってください。必要なデータのみを保存するようにしてください。たとえば、255 個の異なる値しかない場合は、1 バイトを使用します。

http://msdn.microsoft.com/en-us/library/system.bitconverter.aspx

ほとんどの場合、このような単純な構造を使用してデータを保存します

id (ushort)

data_size (単位)

サイズ data_size のデータ

必要な情報だけを保存し、それがどのように使用されるかを考えないでください。ロードするときは、データをどのように使用するかを検討します。

于 2011-03-18T15:39:00.470 に答える
0

オブジェクト自体には BinaryFormatter 、または他の場所で提案されているようにおそらく protobuf.net に固執したくなるでしょう。

これのランダム アクセスの側面が非常に重要な場合 (レコードごとの読み取りと追加)、インデックス ファイルと、zip 内の独自のファイルにシリアル化された各オブジェクト (またはおそらく小さなコレクションで)。

このようにして、効果的に圧縮されたミニ ファイル システムを作成し、レコードに個別にアクセスできます。

于 2011-03-18T15:39:19.237 に答える