Creating a Byte Array from a Stream

Creating a byte array from a stream

It really depends on whether or not you can trust s.Length. For many streams, you just don't know how much data there will be. In such cases - and before .NET 4 - I'd use code like this:

public static byte[] ReadFully(Stream input)
{
byte[] buffer = new byte[16*1024];
using (MemoryStream ms = new MemoryStream())
{
int read;
while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
{
ms.Write(buffer, 0, read);
}
return ms.ToArray();
}
}

With .NET 4 and above, I'd use Stream.CopyTo, which is basically equivalent to the loop in my code - create the MemoryStream, call stream.CopyTo(ms) and then return ms.ToArray(). Job done.

I should perhaps explain why my answer is longer than the others. Stream.Read doesn't guarantee that it will read everything it's asked for. If you're reading from a network stream, for example, it may read one packet's worth and then return, even if there will be more data soon. BinaryReader.Read will keep going until the end of the stream or your specified size, but you still have to know the size to start with.

The above method will keep reading (and copying into a MemoryStream) until it runs out of data. It then asks the MemoryStream to return a copy of the data in an array. If you know the size to start with - or think you know the size, without being sure - you can construct the MemoryStream to be that size to start with. Likewise you can put a check at the end, and if the length of the stream is the same size as the buffer (returned by MemoryStream.GetBuffer) then you can just return the buffer. So the above code isn't quite optimised, but will at least be correct. It doesn't assume any responsibility for closing the stream - the caller should do that.

See this article for more info (and an alternative implementation).

How do I convert a Stream into a byte[] in C#?

Call next function like

byte[] m_Bytes = StreamHelper.ReadToEnd (mystream);

Function:

public static byte[] ReadToEnd(System.IO.Stream stream)
{
long originalPosition = 0;

if(stream.CanSeek)
{
originalPosition = stream.Position;
stream.Position = 0;
}

try
{
byte[] readBuffer = new byte[4096];

int totalBytesRead = 0;
int bytesRead;

while ((bytesRead = stream.Read(readBuffer, totalBytesRead, readBuffer.Length - totalBytesRead)) > 0)
{
totalBytesRead += bytesRead;

if (totalBytesRead == readBuffer.Length)
{
int nextByte = stream.ReadByte();
if (nextByte != -1)
{
byte[] temp = new byte[readBuffer.Length * 2];
Buffer.BlockCopy(readBuffer, 0, temp, 0, readBuffer.Length);
Buffer.SetByte(temp, totalBytesRead, (byte)nextByte);
readBuffer = temp;
totalBytesRead++;
}
}
}

byte[] buffer = readBuffer;
if (readBuffer.Length != totalBytesRead)
{
buffer = new byte[totalBytesRead];
Buffer.BlockCopy(readBuffer, 0, buffer, 0, totalBytesRead);
}
return buffer;
}
finally
{
if(stream.CanSeek)
{
stream.Position = originalPosition;
}
}
}

Create a Stream from a byte[] to a primitive byte Stream

A Stream<Byte> is about as good as a ByteStream of primitives would be, since Byte#valueOf returns cached instances of the boxed values (and the compiler handles boxing and unboxing for you). So then the only trick is to turn your byte[] into a Stream<Byte>.

One way to do that would be to create an IntStream of indexes, and then map those indexes into lookups into your byte[]:

byte[] byteArray = "hello".getBytes();
Stream<Byte> byteStream = IntStream.range(0, byteArray.length)
.mapToObj(i -> byteArray[i]);

I don't know of any helper method in the JDK that does this for you.

java 8: how to stream an array of int, extract low bytes, and create an array of byte

Unfortunately, steams don't support the byte type directly; i.e,. there is no ByteStream specialization like there are for int and long1.

If you insist on using streams, a reasonably efficient solution is to use a ByteArrayOutputStream to collect the bytes:

ByteArrayOutputStream baos(myintarray.length);
Arrays.stream(myintarray).forEachOrdered(i -> baos.write((byte)i));
byte[] byteArray = baos.toArray();

This only copies the array once. A for loop and explicit array insertion is going to be better still:

byte[] byteArray = new byte[myintarray.length];
for (int i = 0; i < myintarray.length; i++) {
byteArray[i] = (byte)myintarray[i];
}

Probably slightly more concise than the streams version, and about as fast as you'll get in Java.

If you really insist on a 1-liner with Streams, you can get a Byte[] rather than a byte[] like so:

Arrays.stream(myintarray).boxed().map(Integer::byteValue)
.collect(Collectors.toList()).toArray(new Byte[myintarray.length]);

This involves a crapload of boxing and you end up with a much larger and slower Byte[], but hey you used a pure Java 8 solution, right?


1 Combinatorial explosion arguments notwithstanding, this has always seemed like an unfortunate omission to me, given the key nature of byte[] in many input/output oriented operations.

Superimpose a stream on top of a byte array

The MemoryStream constructor you mentioned in the second block actually does what you want. It saves the array you provide and uses that as the backing buffer for the stream. You can modify the array and those changes will be reflected by the stream if those bytes are still yet to be read.

Here's a minimal reproducible example to demonstrate this.

byte[] source = new byte[] { 0, 1, 2, 3 };
MemoryStream stream = new MemoryStream(source);

// If the constructor made a copy, the stream won't be
// affected and it will output 0 below.
source[0] = 10;

byte b = (byte)stream.ReadByte();

Console.WriteLine(b);

Output:

10

Try it out!

Be aware that the stream cannot grow when you use that constructor. According to its documentation:

The length of the stream cannot be set to a value greater than the initial length of the specified byte array; however, the stream can be truncated (see SetLength).

Allowing it to grow would break the expectation that it's using that buffer because growing would require allocating a new array and copying the data to it.

Convert InputStream to byte array in Java

You can use Apache Commons IO to handle this and similar tasks.

The IOUtils type has a static method to read an InputStream and return a byte[].

InputStream is;
byte[] bytes = IOUtils.toByteArray(is);

Internally this creates a ByteArrayOutputStream and copies the bytes to the output, then calls toByteArray(). It handles large files by copying the bytes in blocks of 4KiB.



Related Topics



Leave a reply



Submit