Случайный доступ и BinaryWriter? - PullRequest
2 голосов
/ 23 января 2010

Я работаю над проектом, в котором я создаю байтовый массив, который похож на сериализацию графа объектов. Каждый класс отвечает за запись своих собственных данных, поэтому я думаю об использовании BinaryWriter и передаю этот экземпляр моим дочерним объектам, позволяя им сериализоваться в них, вместо того, чтобы создавать временные буферы (байтовые массивы) и объединять их.

Однако мне нужно добавить к каждому дочернему элементу байт, в котором указан размер следующего блока, но он неизвестен до тех пор, пока дочерний элемент не записывает все данные, и к этому времени средство записи позиционируется в конце childdata. Конечно, я мог бы создать временный буфер и передать временный BinaryWriter потомку, а затем записать данные в «основной» BinaryWriter, но это похоже на хакерское решение.

Есть ли альтернативные решения? Может быть, это плохая идея подделать позицию BinaryWriter? Я хотел бы избежать создания временных буферов / писателей, если это возможно, и просто позволить каждому дочернему элементу писать в мой «основной» писатель / буфер

Решение, приведенное ниже, может работать, но немного хакерское. Есть ли более приятные решения? (Я не проверял его, поэтому, возможно, он не совсем выровнен)

public abstract class BaseObject 
{
      public abstract void Serialize(BinaryWriter writer);
}



public class Program() 
{

  public static void Main() 
  {
       List<BaseObject> myChildren = new List<BaseObject>();

       // ... Initialize children here..

       MemoryStream memoryStream = new MemoryStream();
       BinaryWriter writer = new BinaryWriter(memoryStream);

       foreach (BaseObject child in myChildren) {
           writer.Write((byte)0); // Dummy placeholder. Length is a byte
           long sizePosition = writer.BaseStream.Position;
           child.Serialize(writer);
           long currentPosition = writer.BaseStream.Position;
           writer.Seek(sizePosition, SeekOrigin.Begin);
           writer.Write((byte)currentPosition-sizePosition);
           writer.Seek(currentPosition , SeekOrigin.Begin);
       }
   }
}

1 Ответ

2 голосов
/ 23 января 2010

Недавно я тоже был озадачен очень похожим вопросом и также понял, что кажется, что вы можете / должны иметь практически только один двоичный модуль записи, связанный также с конкретным потоком, потому что, как только вы закроете один двоичный модуль записи (согласно документации) поток тоже закрыт. Я не нашел лучшего решения, чем те, которые вы описываете:

  1. Записать данные в MemoryStream, затем записать размер и содержимое потока памяти в основной поток. Это может быть удобно, если вы хотите разрешить некоторым объектам использовать другой тип записи, кроме BinaryWriter.
  2. Запомните текущую позицию, введите значение 0, затем блок данных. Затем вернитесь к значению 0 и замените его записанным размером, затем вернитесь к концу.

Я выбрал вариант № 1. Хотя я еще не закончил свою реализацию, мне лучше узнать размер того, что будет написано, прежде чем что-либо записывать в поток. Чувствует себя более изобретательным, чтобы писать фиктивные значения и прыгать по течению. И это, вероятно, больше похоже на то, как BinaryWriter пишет строки внутри. Вы наследуете или решили рассмотреть возможность наследования от BinaryWriter для добавления собственных функций записи?

...