Reputation: 18567
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[], ...
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.
Upvotes: 0
Views: 258
Reputation: 26436
You could write a generic method, and use Buffer.BlockCopy
to copy the data into the target array:
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;
}
Upvotes: 2