0

Let me give a simplified version of what I've tried. I have a file asset that contains a raw array of numbers (total of N number each is 4 bytes wide). I make an InputStream using AssetManager and try to push all the data into a direct ByteBuffer:

try (InputStream inputStream = assetsManager.open(assetFileName)) {
     int size = inputStream.available();
     assert size % 4 == 0;
     ByteBuffer bytes = ByteBuffer.allocateDirect(size).order(ByteOrder.nativeOrder());
     inputStream.read(bytes.array());
}

I thought that should work just fine, but I've met some strange behavior of my program that made me think that data loading was not correct after all, and indeed, after doing some debug logging of first content inside bytes and comparing it to the file content in a HEX viewer I found that this approach doesn't read the first 4 bytes, i.e. bytes content starts from my second 4 byte-wide number. I confess that I didn't check what's contained in the end of bytes, but let's assume it's just zeros.

I then resorted to another approach and it reads all the bytes fully and correctly (yet it's kind of ugly and I'd like to avoid it):

 try (InputStream inputStream = assetsManager.open(assetFileName) {
      int size = inputStream.available();
      byte[] bytesArray = new byte[size];
      inputStream.read(bytesArray, 0, size);
      ByteBuffer bytes = ByteBuffer.allocateDirect(size).order(ByteOrder.nativeOrder());
      bytes.put(bytesArray);
      bytes.rewind();
 }

I'm really a rookie of both Java and Android development, so I ask is this a platform-side bug, or is there something about InputStream / AssetManager.open(...) that I need to handle more carefully to achieve correct reading of data?

I've examined this question which sounds similar, but it's about C#: NetworkStream cuts off first 4 bytes when reading

It made me think that I should also read data in chunks and put them in ByteStream one by one, yet my files are not big (less than 16MB) and there's obviously no data race when reading, so I think inputStream.read(bytes.array()); shouldn't fail that strangely...

Alexey S. Larionov
  • 6,555
  • 1
  • 18
  • 37
  • `ByteOrder.nativeOrder())` What kind of order can a byte buffer have? A byte is a byte i would say. – blackapps Jun 23 '21 at 09:29
  • `inputStream.read(bytes.array());` Would one call read 16MB ? I wonder. `int nread = inputStream.read(bytes.array());` Same problem with `inputStream.read(bytes, 0, size);` – blackapps Jun 23 '21 at 09:32
  • 16MB is an edgy case, typically it's about 2MB. I see that it might cause problems, so chunking is it? – Alexey S. Larionov Jun 23 '21 at 09:35
  • @blackapps `ByteOrder.nativeOrder()` is something I found in OpenGL example for Android, didn't put much thought in it, but works just fine when this binary data is used to be transferred on GPU for OpenGL – Alexey S. Larionov Jun 23 '21 at 09:36
  • `byte[] bytesArray` First four bytes in hex? – blackapps Jun 23 '21 at 09:36
  • `(yet it's kind of ugly and I'd like to avoid it):` There is nothing ugly. But you should check the return value of .read(). – blackapps Jun 23 '21 at 09:38
  • @blackapps yes, `3E 79 0C 3F 49 BB 61 3E ...` is how my file starts, `49 BB 61 3E ...` is what I get – Alexey S. Larionov Jun 23 '21 at 09:38
  • @blackapps it's ugly in a sense that I allocate byte array twice, first as `byte[]`, next as `ByteBuffer` – Alexey S. Larionov Jun 23 '21 at 09:39
  • Yes, that is true. But why do you need a ByteBuffer if you have already a byte array? How would you use a ByteBuffer for numbers each four bytes long? – blackapps Jun 23 '21 at 09:42
  • @blackapps I pass it to raw OpenGL functions, and they require a direct storage – Alexey S. Larionov Jun 23 '21 at 09:43
  • `49 BB 61 3E ... is what I get –` ??? Dont understand. You said that all went ok if you used this array. – blackapps Jun 23 '21 at 09:44
  • I dont know what you mean with direct storage but if they need a ByteBuffer then i can understand what you do. – blackapps Jun 23 '21 at 09:46
  • ... sorry for misunderstanding, with `byte[]` it's OK, but with straight read into `ByteBuffer` I lose first 4 bytes – Alexey S. Larionov Jun 23 '21 at 09:46
  • Isnt it possible to declare a small byte array of say 8192 and then in a loop read into array and use bytes.put(bytesArray); repeatedly? In that way you only have the file once in memory. – blackapps Jun 23 '21 at 09:54
  • I believe it's totally possible, but I would be just as happy if straight read into a `ByteBuffer` wouldn't lose 4 bytes, and that's why I've asked this question – Alexey S. Larionov Jun 23 '21 at 09:57
  • Quote: Thus, not all ByteBuffer implementations are backed by a bytes array, and when they are, the beginning of the array returned by .array() may not necessarily correspond to the beginning of the ByteBuffer. http://errorprone.info/bugpattern/ByteBufferBackingArray Further i saw no examples where they try to write in .array(). It looks as if you invented that yourself. – blackapps Jun 23 '21 at 10:33
  • I've literally taken it from [there](https://github.com/google-ar/arcore-android-sdk/blob/master/samples/hello_ar_java/app/src/main/java/com/google/ar/core/examples/java/helloar/HelloArActivity.java#L364), but anyway... Thanks for your investigation nontheless, very enlightening – Alexey S. Larionov Jun 23 '21 at 10:49

0 Answers0