MemoryStream из байтового массива с различными типами данных - PullRequest
3 голосов
/ 11 февраля 2011

Я хочу создать поток памяти, который содержит int32, int16, отдельные значения.Использование бинарной записи бесполезно, поэтому я попытался создать массив байтов.Поскольку значения имеют разные типы, я не знаю, как это сделать правильно.Поэтому я пытаюсь сделать так:

byte[] tab = new byte[]{2,0,0,0,3,0,3,0} - 2 - это int32 (четыре байта), еще два - это int16 (два байта)

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

byte[] tab = new byte[]{2,0,0,0,3,0,3,0,4.4f,5.6f}

У меня должен быть поток в правильном формате, потому что этот поток будет прочитан в этом методе:

short[] rawData;
 float[] modulusData;
   public void rawData(Stream s)
        {

            BinaryReader br = new BinaryReader(s);

            int dataCount = br.ReadInt32();

            if (dataCount > 0)
            {
                rawData = new short[dataCount];
                for (int i = 0; i < dataCount; i++)
                    rawData[i] = br.ReadInt16();
            }
            else
                rawData = new short[0];

            dataCount = br.ReadInt32();

            if (dataCount > 0)
            {
                modulusData = new float[dataCount];
                for (int i = 0; i < dataCount; i++)
                    modulusData[i] = br.ReadSingle();
            }
            else
                modulusData = new float[0];
        }

У любогоидея как это сделать ??

Ответы [ 3 ]

5 голосов
/ 11 февраля 2011

Вопреки вашему первоначальному утверждению, BinaryWriter - это точно , что вы хотите.Вот для чего он предназначен.В частности, это совершенно уместно, если вы собираетесь использовать BinaryReader позже.

Вы не указали, почему вы не хотите его использовать, но это действительно то, что вы должны использовать:

using (MemoryStream stream = new MemoryStream())
{
    using (BinaryWriter writer = new BinaryWriter(stream))
    {
        writer.Write(2);
        writer.Write((short) 3);
        writer.Write((short) 3);
        writer.Write(4.4f);
        writer.Write(5.6f);
    }
    byte[] bytes = stream.ToArray();
}

Создает байтовый массив со следующими данными:

[Int32    ] [Int16] [Int16] [Single   ] [Single   ]
02 00 00 00 03 00   03 00   CD CC 8C 40 33 33 B3 40

Обратите внимание: ваше описание записывает эти значения:

- Int32
- Int16
- Int16
- Single
- Single

... но ваш код чтения будет читать:

- Int32 (value 2)
- Int16
- Int16
- Int32 (this wasn't written - so you're reading data from the first Single!)
- ???

Другими словами, если ваши предыдущие попытки с BinaryWriter не увенчались успехом, потому что они выглядели как мой исходный код,это потому, что вы забыли

writer.Write(2);

после записи значений Int16, чтобы сказать, сколько значений Single присутствовало.

Обратите внимание, что если вам не нужны значения в виде байтового массива,Вам не нужно звонить ToArray - просто верните поток (без его утилизации).Тем не менее, вы захотите «перемотать» его перед прочтением.Например:

public Stream GetData()
{
    MemoryStream stream = new MemoryStream();
    BinaryWriter writer = new BinaryWriter(stream); // Don't close at the end!
    writer.Write(2);
    writer.Write((short) 3);
    writer.Write((short) 3);
    writer.Write(2); // Extra count for the Single values
    writer.Write(4.4f);
    writer.Write(5.6f);
    writer.Flush(); // May not be required...

    stream.Position = 0; // Rewind so stream can be read again
    return stream;
}
3 голосов
/ 11 февраля 2011

BinaryWriter вовсе не бесполезен.Просто создайте поток памяти и напишите в него:

MemoryStream m = new MemoryStream();
using (BinaryWriter writer = new BinaryWriter(m)) {
  writer.Write(2); // count
  writer.Write((short)3);
  writer.Write((short)3);
  writer.Write(2); // count
  writer.Write(4.4f);
  writer.Write(5.6f);
}
byte[] tab = m.ToArray();

Обратите внимание, что я также добавил счетчик для значений с плавающей точкой.Это не в вашем примере данных, но метод, который читает данные, нуждается в этом.

Я проверил, что данные могут быть прочитаны правильно.Я использовал ваш код читателя и выписал результат:

Console.WriteLine(rawData.Length);
foreach (short x in rawData) Console.WriteLine(x);
Console.WriteLine(modulusData.Length);
foreach (float f in modulusData) Console.WriteLine(f);

Вывод:

2
3
3
2
4,4
5,6
0 голосов
/ 11 февраля 2011

Построение байтового массива, подобного этому, не работает, потому что Int32 и Int16 будут неявно преобразованы в byte, чего не происходит для чисел с плавающей запятой, следовательно, ваша ошибка компилятора.

Лучший способ - записать в поток так же, как вы читаете из него, используя BinaryWriter (см. Другие ответы)

...