c#从流中读取特定类型数组的有效方法

时间:2022-12-06 21:27:06

I'm looking for an efficient way of reading multiple arrays of a specific type from a stream.

我正在寻找一种从流中读取特定类型的多个数组的有效方法。

So far I'm using a class like this below to read single values like: int, byte, sbyte, uint, short, ushort, ... but also for arrays like: ushort[], short[], uint[], int[], byte[], sbyte[], ...

到目前为止,我正在使用下面这样的类来读取单个值,如:int,byte,sbyte,uint,short,ushort,...还可以用于以下数组:ushort [],short [],uint [], int [],byte [],sbyte [],...

    public byte[] ReadBytes(int count)
    {
      byte[] buffer = new byte[count];
      int retValue = _Stream.Read(buffer, 0, count);
      return buffer;
    }

    public ushort ReadUshort()
    {
      byte[] b = ReadBytes(2);
      if (BitConverter.IsLittleEndian) // for motorola (big endian)
        Array.Reverse(b);
      return BitConverter.ToUInt16(b, 0);
    }

    public ushort[] ReadUshorts(int count) 
    {
       ushort[] data = new ushorts[count];
       for (int i = 0; i < count; i++)
       {
          data[i] = ReadUshort();
       }
       return data;
    }

   public uint ReadUint() 
   {
       byte[] b = ReadBytes(4);
      if (BitConverter.IsLittleEndian) // for motorola (big endian)
        Array.Reverse(b);
      return BitConverter.ToUInt32(b, 0);
   }

   public uint[] ReadUints(int count)
   {
      // ...
   }

Is there a more efficient way compared to code snippet I've shared here to read the arrays?

与我在这里分享读取数组的代码片段相比,是否有更有效的方法?

I have a feeling that a combination of for-loop and each time a single read call is not so efficient. But the problem is that I need to check for IsLittleEndian each time and reverse if needed, so I can read many bytes at ones. Not sure if this could be rewritten more efficiently.

我觉得for循环和每次单个读取调用的组合效率都不高。但问题是我需要每次检查IsLittleEndian并在需要时反转,所以我可以读取多个字节。不确定这是否可以更有效地重写。

1 个解决方案

#1


2  

You could write a generic method, and use Buffer.BlockCopy to copy the data into the target array:

您可以编写泛型方法,并使用Buffer.BlockCopy将数据复制到目标数组中:

    public static T[] ReadElements<T>(Stream input, int count)
    {
        int bytesPerElement = Marshal.SizeOf(typeof(T));
        byte[] buffer = new byte[bytesPerElement * count];

        int remaining = buffer.Length;
        int offset = 0;
        while (remaining > 0)
        {
            int read = input.Read(buffer, offset, remaining);
            if (read == 0) throw new EndOfStreamException();
            offset += read;
            remaining -= read;
        }

        if (BitConverter.IsLittleEndian)
        {
            for (int i = 0; i < buffer.Length; i += bytesPerElement)
            {
                Array.Reverse(buffer, i, bytesPerElement);
            }
        }

        T[] result = new T[count];
        Buffer.BlockCopy(buffer, 0, result, 0, buffer.Length);
        return result;
    }

#1


2  

You could write a generic method, and use Buffer.BlockCopy to copy the data into the target array:

您可以编写泛型方法,并使用Buffer.BlockCopy将数据复制到目标数组中:

    public static T[] ReadElements<T>(Stream input, int count)
    {
        int bytesPerElement = Marshal.SizeOf(typeof(T));
        byte[] buffer = new byte[bytesPerElement * count];

        int remaining = buffer.Length;
        int offset = 0;
        while (remaining > 0)
        {
            int read = input.Read(buffer, offset, remaining);
            if (read == 0) throw new EndOfStreamException();
            offset += read;
            remaining -= read;
        }

        if (BitConverter.IsLittleEndian)
        {
            for (int i = 0; i < buffer.Length; i += bytesPerElement)
            {
                Array.Reverse(buffer, i, bytesPerElement);
            }
        }

        T[] result = new T[count];
        Buffer.BlockCopy(buffer, 0, result, 0, buffer.Length);
        return result;
    }