سؤال

أحاول القيام بالتسلسل المخصص/إزالة التسلسل للكائن بالإضافة إلى ضغط/إلغاء ضغط البيانات المسلسل باستخدام 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();
                }

الآن ، للمشكلة. يلقي Deserialization a SerializationException مع الرسالة {"لا توجد خريطة للكائن" 201326592 "."} ليس لدي أي فكرة عن كيفية استكشاف أو اكتشاف ما يسبب بالضبط المشكلة. يعمل التسلسل الأساسي للغاية عندما أقوم فقط بتشغيل أساليب BinaryFormatter وتسفر الأساليب على نفس الذاكرة.

حاولت إزالة أشياء deflatestream من كلتا الطريقتين ، لكنها لا تزال نفس المشكلة. عندما أنظر إلى الأمثلة في MSDN والأماكن الأخرى ، يبدو أنني أفعل ذلك تمامًا ، ولا يعطي Googling لرسالة الاستثناء أي نتائج ذات معنى (أو ربما أكون سيئًا في البحث).

ملاحظة. كما ترون ، فأنا أستخدم miscellaneor.copysstream (SRC ، DEST) وهو نسخة أساسية للتيار ، حيث لا يمكنني الحصول على src.copyto (القدر) للعمل على الإطلاق ، لذلك أي تلميحات على هذا الترحيب أيضًا.

فيما يلي رابط لمشروع VS2010 بالكامل إذا كنت ترغب في النظر إليه عن كثب:http://www.diredumplings.com/SerializationTesting.zip

تحديث:

الأصغر: حاولت استخدام طريقة الضغط التي نشرتها على التسلسل الخاص بي:

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 كيلو بايت عندما أحاول حفظه على القرص. أيه أفكار؟

بيتر: لقد أزلت 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();
            }

بفضل كل واحد منكما!

هل كانت مفيدة؟

المحلول

لقد قمت بتحميل مثالك وحفرت قليلاً هناك. انظر التغييرات لمشروعك أدناه:

  1. يحل محل LoadFromFile في loader.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. يحل محل Save في Saver.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;
    }
}

نصائح أخرى

يجب عليك التسلسل في DeflateStream, وليس القاعدة (MemoryStream) مجرى.

للتسلسل: ابدأ مع File.Create. ثم حول هذا الدفق ، قم بإنشاء ملف DeflateStream. ثم إلى DefaulteStream, ، تسلسل الأشياء الخاصة بك.

للتخلص من ذلك: لا تنشئ MemoryStream وفرس مباشرة من DeflateStream.

أعتقد أنه لا توجد حاجة للإضافات MemoryStream. إذا كانت لديك مشاكل في الكتابة مباشرة إلى/القراءة مباشرة من تدفقات الملفات ، فما عليك سوى تغيير الروتين التسلسلي للكتابة إلى DeflateStream بدلا من ال MemoryStream.

يجب أن يحل مشاكلك.

هناك خطأ في منطقات التدفقات ، في حين يجب أن تكتب إلى CompressStream ، والذي يكتب إلى MemoryStream ، بعد ذلك ، ستؤدي إلى ذاكرة (وليس في CompressStream) ، فيما يلي مثال على كيفية ضغط البايتات وإزالة الضغط عليها

    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();
        }
    }
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top