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;
}