5

オブジェクトのカスタムのシリアル化/逆シリアル化を行い、シリアル化されたデータを DeflateStreams で圧縮/解凍しようとしています。私は元々、より複雑なオブジェクトに対してこれを行っていましたが、問題を解決するために削減しましたが、まだそこにあるため、より不可解になりました。シリアライズ/デシリアライズするクラスは次のとおりです。

[Serializable]
    public class RandomObject : ISerializable
    {
        public String Name { get; set; }
        public String SavePath { get; set; }

        public RandomObject()
        {
        }

        public RandomObject(String name, String savepath)
        {
            Name = name;
            SavePath = savepath;
        }

        public RandomObject(SerializationInfo info, StreamingContext context)
            : this(info.GetString("name"), info.GetString("savepath"))
        {
        }
        [SecurityPermissionAttribute(SecurityAction.Demand, SerializationFormatter = true)]
        public void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            info.AddValue("name", Name);
            info.AddValue("savepath", SavePath);
        }
    }

そして、これをシリアル化することになっているコードがあります(動作しているようです):

BinaryFormatter bf = new BinaryFormatter();
            using (MemoryStream ms = new MemoryStream())
            {
                bf.Serialize(ms, profile);
                using (DeflateStream ds = new DeflateStream(ms, CompressionMode.Compress))
                {
                    try
                    {
                        using (FileStream fs = File.Create(path))
                        {
                            ds.Flush();
                            Miscellaneous.CopyStream(ds.BaseStream, fs);
                            fs.Flush();
                            fs.Close();
                        }
                    }
                    catch (IOException e)
                    {
                        MessageBox.Show(e.Message);
                        success = false;
                    }
                    ds.Close();
                }
                ms.Close();
            }

そして、ここに逆シリアル化があります:

RandomObject profile = null;
                using (FileStream fs = File.OpenRead(path))
                {
                    using (DeflateStream ds = new DeflateStream(fs, CompressionMode.Decompress))
                    {
                        BinaryFormatter bf = new BinaryFormatter();
                        ds.Flush();

                        using (MemoryStream ms = new MemoryStream())
                        {
                            Miscellaneous.CopyStream(ds.BaseStream, ms);
                            profile = bf.Deserialize(ms) as RandomObject;
                            profile.SavePath = path;
                            ms.Close();
                        }
                        ds.Close();
                    }
                    fs.Close();
                }

さて、問題に。デシリアライゼーションは、{"オブジェクト '201326592' のマップがありません。"} というメッセージとともに SerializationException をスローします。トラブルシューティングの方法や、問題の原因を正確に突き止める方法がわかりません。BinaryFormatter の Serialize メソッドと Deserialize メソッドを同じ MemoryStream で実行すると、非常に基本的なシリアル化が機能します。

両方のメソッドから DeflateStream のものを削除しようとしましたが、それでも同じ問題です。MSDN や他の場所の例を見ると、私はそれを正しく行っているように見え、例外メッセージをグーグルで調べても意味のある結果が得られません (または、検索が下手なだけかもしれません)。

PS。ご覧のとおり、 src.CopyTo(dest) をまったく機能させることができないため、基本的なストリームコピーである Miscellaneous.CopyStream(src, dest) を使用しているため、そのヒントも歓迎します。

以下は、VS2010 プロジェクト全体へのリンクです。詳しく調べたい場合は、 http ://www.diredumplings.com/SerializationTesting.zip を参照してください。

アップデート:

The_Smallest : シリアライゼーションに投稿した Compress メソッドを使用してみました:

BinaryFormatter bf = new BinaryFormatter();
            using (MemoryStream stream = new MemoryStream())
            {
                bf.Serialize(stream, profile);

                byte[] array = Compress(stream);

                using (MemoryStream ms = new MemoryStream(array))
                {
                    using (FileStream fs = File.Create(path))
                    {
                        ms.WriteTo(fs);
                        fs.Flush();
                    }
                }
            }

ただし、以前に srcStream.CopyTo(destStream) で発生したのと同じ問題が発生するようです。つまり、ストリームに書き込まれないようです。ディスクに保存しようとすると、結果は 0 kb のファイルになります。何か案は?

Pieter : デシリアライズ メソッドから MemoryStream を削除しましたが、以前と同じ機能を持っているようです。ただし、あなたが提案した方法でシリアル化を実装する方法がわかりません。これはあなたが考えていたことですか?

BinaryFormatter bf = new BinaryFormatter();

            using (FileStream fs = File.Create(path))
            {
                using (DeflateStream ds = new DeflateStream(fs, CompressionMode.Compress))
                {
                    bf.Serialize(ds, profile);
                    fs.Flush();
                    ds.Close();
                }
                fs.Close();
            }

お二人ともありがとう!

4

3 に答える 3

1

私はあなたの例をダウンロードし、そこに少し掘り下げました。以下のプロジェクトの変更を参照してください。

  1. LoadFromFileLoader.csで置き換えます
private static RandomObject LoadFromFile(string path)
{
  try
  {
    var bf = new BinaryFormatter();
    using (var fileStream = File.OpenRead(path))
    using (var decompressed = new MemoryStream())
    {
      using (var deflateStream = new DeflateStream(fileStream, CompressionMode.Decompress))
        deflateStream.CopyTo(decompressed);

      decompressed.Seek(0, SeekOrigin.Begin);
      var profile = (RandomObject)bf.Deserialize(decompressed);
      profile.SavePath = path;
      return profile;
    }
  }
  catch (IOException e)
  {
    MessageBox.Show(e.Message);
    return null;
  }
}

  1. SaveSaver.csで次のように置き換えます。
public static bool Save(RandomObject profile, String path)
{
   try
   {
      var bf = new BinaryFormatter();
      using (var uncompressed = new MemoryStream())
      using (var fileStream = File.Create(path))
      {
         bf.Serialize(uncompressed, profile);
         uncompressed.Seek(0, SeekOrigin.Begin);

         using (var deflateStream = new DeflateStream(fileStream, CompressionMode.Compress))
           uncompressed.CopyTo(deflateStream);
      }
      return true;
    }
    catch (IOException e)
    {
       MessageBox.Show(e.Message);
       return false;
    }
}
于 2010-11-28T18:38:05.500 に答える
1

DeflateStreamベース ( MemoryStream) ストリームではなく、 にシリアル化する必要があります。

シリアル化の場合: から始めますFile.Create。次に、そのストリームの周りにDeflateStream. 次にDefaulteStream、オブジェクトをシリアル化します。

逆シリアル化の場合: を作成せず、MemoryStreamから直接逆シリアル化しDeflateStreamます。

を追加する必要はないと思いますMemoryStream。ただし、ファイル ストリームへの直接書き込み/ファイル ストリームからの直接読み取りに問題がある場合は、シリアライズ ルーチンを変更してDeflateStreamMemoryStream.

それはあなたの問題を解決するはずです。

于 2010-11-28T17:01:41.333 に答える
1

ストリーム ロジックにエラーがあります。圧縮中に CompressStream に書き込む必要があります。CompressStream は MemoryStream に書き込みます。この後、(CompressStream ではなく) MemoryStream になります。バイトを圧縮および解凍する方法の例を次に示します。

    private static byte[] Compress(Stream stream)
    {
        using (var resultStream = new MemoryStream())
        {
            using (var gzipStream = new DeflateStream(resultStream, CompressionMode.Compress))
                stream.CopyTo(gzipStream);
            return resultStream.ToArray();
        }
    }

    private static byte[] Decompress(byte[] bytes)
    {
        using (var readStream = new MemoryStream(bytes))
        using (var resultStream = new MemoryStream())
        {
            using (var gzipStream = new DeflateStream(readStream, CompressionMode.Decompress))
                gzipStream.CopyTo(resultStream);
            return resultStream.ToArray();
        }
    }
于 2010-11-28T17:10:50.223 に答える