I'm trying to slice a byte array to prune the first part of the array. I'm using ByteBuffer but it does not behave like I would expect.
byte[] myArray = new byte[10];
ByteBuffer buf = ByteBuffer.wrap(myArray);
buf.position(5);
ByteBuffer slicedBuf = buf.slice();
byte[] newArray = slicedBuf.array();
I would expect the size of newArray to be 5, containing only the last portion of my ByteBuffer. Instead, the full byte array is returned. I understand that this is because the "backing buffer" is the same all along.
How can I slice to have only the desired part of the array?
EDIT: Added context
The bytes are received from network. The buffer is formed like this :
[ SHA1 hash ] [ data... lots of it ]
I already have a function that takes a byte array as a parameter and calculate the SHA1 hash. What I want is to slice the full buffer to pass only the data without the expected hash.
You can use the Arrays.copyOfRange method. For example:
// slice from index 5 to index 9
byte[] slice = Arrays.copyOfRange(myArray, 5, 10);
The ByteBuffer you created is being backed by that array. When you call slice() you effectively receive a specific view of that data:
Creates a new byte buffer whose content is a shared subsequence of this buffer's content.
So calling array() on that returned ByteBuffer returns the backing array in its entirety.
To extract all the bytes from that view, you could do:
byte[] bytes = new byte[slicedBuf.remaining()];
slicedBuf.read(bytes);
The bytes from that view would be copied to the new array.
Edit to add from comments below: It's worth noting that if all you're interested in doing is copying bytes from one byte[] to another byte[], there's no reason to use a ByteBuffer; simply copy the bytes.
Related
As everyone already knows, Java allocates the size of array upon declaration. meaning that if I define array like this:
byte[] buffer = new byte[10];
the buffer.length will return 10. However, my question is, how can I find out how many elements are populated. I am populating elements from an InputStream so I never know how many elements will be there.
I know that allocated array positions which are empty will be 0 but what if I am getting zero values from the InputStream as well, mixed together with normal values?
You can't. Just store the amount of bytes you have read in a variable. InputStream.read() returns the number of bytes read:
Returns:
the total number of bytes read into the buffer, or -1 if there is no more data because the end of the stream has been reached.
You could pre-populate the array with some invalid value that is not expected to be produced by the InputStream. However, this depends on the InputStreams content, so picking a generic default value is not really easy.
Another option for you is to use some collection, like List<Byte> or Set<Byte> (if you need uniqueness) - in this case the number of populated elements will simply be the size of the collection and if you really need an array at the end, you could easily produce one from the content of the collection.
Lets look at this piece of code:
InputStream inputStream = new FileInputStream(new File("fileName"));
int cntReadBytes = 0;
byte[] bytes = new byte[10];
while((i = inputStream.read()) != -1) {
bytes[cntReadBytes] = i;
cntReadBytes++;
}
System.out.println("You have read total: " + cntReadBytes + " bytes" );
as you can see in the while loop condition I make comparison of inputstream return and -1, when the return value is different it means I have more data to read, when it reaches the end of file it will return -1. So the value of cntReadBytes will be the number of iterations, i.e. successfully read bytes.
Or if you are free to use List, you don't have to worry about this.
You could count the number of bytes passed through the InputStream, e.g. by using Apache Commons CountingInputStream. Or you could extend FilterInputStream yourself, if you don't have Apache Commons.
I have a byte array. But I want array length mod 4=0. So I want to add 00 after array until pass condition.
I find many solutions to append array
byte[] arr_combined = new byte[arr_1.length + arr_2.length];
System.arraycopy(arr_1, 0, arr_combined, 0, arr_1.length);
System.arraycopy(arr_2, 0, arr_combined, arr_1.length, arr_2.length);
But I do not want to create new byte array. I only want append byte after a byte array. Thanks
As it was already mentioned, Java arrays have fixed size which cannot be changed after array is created. In your case it's probably ok to use ByteArrayOutputStream:
ByteArrayOutputStream out = new ByteArrayOutputStream();
out.write(arr_1);
out.write(arr_2);
byte[] arr_combined = out.toByteArray();
This way you work with primitive byte type (unlike List<Byte>) which will be more efficient. The drawback is that ByteArrayOutputStream is synchronized, so there's some overhead for synchronization (though I guess it's much lower than boxing/unboxing overhead when using List<Byte>). Another drawback is that ByteArrayOutputStream.write is declared to throw IOException. In practice it's never thrown, but you have to catch/rethrow it.
If you don't mind using third-party libraries, there are plenty ways to create convenient wrappers over the primitive types which don't have these drawbacks. For example, TByteArrayList from Trove library.
If you have an array you can't modify the length of it. You should use an ArrayList:
List<Byte> bytes = new ArrayList<Byte>();
Here you can add a new element wherever you want just using add method so, supposing that b it's a byte variable:
bytes.add(b);
So, in this way, you can add the number of 00 that you want regardless of the length of the ArrayList.
EDIT: I saw now on this question that you can convert the ArrayList when you have complete it to an array, like this:
Byte[] arrayBytes = bytes.toArray(new Byte[bytes.size()]);
I expect it helps to you!
What´s the difference between
"hello world".getBytes("UTF-8");
and
Charset.forName("UTF-8").encode("hello world").array();
?
The second code produces a byte array with 0-bytes at the end in most cases.
Your second snippet uses ByteBuffer.array(), which just returns the array backing the ByteBuffer. That may well be longer than the content written to the ByteBuffer.
Basically, I would use the first approach if you want a byte[] from a String :) You could use other ways of dealing with the ByteBuffer to convert it to a byte[], but given that String.getBytes(Charset) is available and convenient, I'd just use that...
Sample code to retrieve the bytes from a ByteBuffer:
ByteBuffer buffer = Charset.forName("UTF-8").encode("hello world");
byte[] array = new byte[buffer.limit()];
buffer.get(array);
System.out.println(array.length); // 11
System.out.println(array[0]); // 104 (encoded 'h')
Is there a good way to combine ByteBuffer & FloatBuffer ?
For example I get byte[] data and I need to convert it to float[] data and vice versa :
byte[] to float[] (java.lang.UnsupportedOperationException) :
byte[] bytes = new bytes[N];
ByteBuffer.wrap(bytes).asFloatBuffer().array();
float[] to byte[] (works) :
float[] floats = new float[N];
FloatBuffer floatBuffer = FloatBuffer.wrap(floats);
ByteBuffer byteBuffer = ByteBuffer.allocate(floatBuffer.capacity() * 4);
byteBuffer.asFloatBuffer().put(floats);
byte[] bytes = byteBuffer.array();
array() is an optional operation for ByteBuffer and FloatBuffer, to be supported only when the backing Buffer is actually implemented on top of an array with the appropriate type.
Instead, use get to read the contents of the buffer into an array, when you don't know how the buffer is actually implemented.
To add to Louis's answer, arrays in Java are limited in that they must be an independent region of memory. It is not possible to have an array that is a view of another array, whether to point at some offset in another array or to reinterpret the bytes of another array as a different type.
Buffers (ByteBuffer, FloatBuffer, etc) were created to overcome this limitation. They are equivalent to arrays in that they compile into machine instructions that are as fast as array accesses, despite requiring the programmer to use what appear to be function calls.
For top performance and minimum memory usage, you should use ByteBuffer.wrap(bytes).asFloatBuffer() and then call get() and put().
To get a float array, you must allocate a new array and copy the data into it with ByteBuffer.wrap(bytes).asFloatBuffer().get(myFloatArray).
The array method of a ByteBuffer is not something that anyone should normally use. It will fail unless the Buffer is wrapping an array (instead of pointing to some memory-mapped region like a file or raw non-GC memory) and the array is of the same type as the buffer.
I would like to convert an integer array in java, to an Inputstream, after that I would like to use the stream of bytes to be decompressed using LZMA library.
int [] header = new int[copy.length];
edu.coeia.Compression.LZMA.Decoder decoder = new edu.coeia.Compression.LZMA.Decoder();
ByteArrayInputStream bStream = new ByteArrayInputStream(bheader);
bStream.coder(// InputSream of bytes);
What you need to do is convert the array of integers into an equivalent array of bytes, and then use the ByteArrayInputStream(byte[]) constructor to create the input stream. Finally, decode the stream using the code that you already have.
The first step (conversion) is probably the one that you are having difficulty with, but the code depends on how the bytes are represented in the integer array.