1

I recently started to learn Java and as I'm really the type of a person that learns much quicker with a task in hands I decided to take a small application written in C# and create an equivalent in Java.

Perhaps I should have start with smaller tasks, but since I already started to design it (the C# app is not written very well, hence creating an equivalent application in terms of features, not design and structure), I don't feel like dropping my idea.

Well, as you may probably realized by now, reading this, I am stuck. The application is kind of an editor that acts on data stored in a binary file. What I can't figure out at this time is how to read this file (one thing is reading) and parse (extract) data I need. I know the structure of this file. So here are the things I'm looking for:

  1. How should I access binary data stored in the file (in C# I would use BinaryReader)
  2. How to deal with primitives that are not available in Java (uint8_t, uint16_t, since the file is created in C++)

EDIT

I should have probably also mention that I probably need to load whole file into memory before processing! The file is 2MB.

I usually get lost when dealing with binary files and streams :x

EDIT 2

I think I figured it out in the meantime. I need to verify 4 byte signature at first. So I do this:

byte[] identifier = {'A', 'B', 'C', 'D'};
fs = new FileInputStream(filename);
byte[] extractedIdentifier = new byte[4];
if(4 != fs.read(extractedIdentifier)) {
    throw new Exception();
}

if(!Arrays.equals(identifier, extractedIdentifier)) {
    throw new Exception();
}

and after this I need whole file anyway, so I found MappedByteBuffer https://docs.oracle.com/javase/7/docs/api/java/nio/MappedByteBuffer.html which I think I will look into, because it seems like the perfect solution at first glance.

FileChannel fc = fs.getChannel();
MappedByteBuffer buf = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());

Since I just started reading about this, are there any side effects of using this method? Is there a better way to do this?

Community
  • 1
  • 1
pzaj
  • 1,062
  • 1
  • 17
  • 37
  • 1
    "How to deal with primitives that are not available in Java": Go up one size and mask accordingly is one option, but beware! Java expects Big Endian, so you may be better off [doing something like this](https://stackoverflow.com/questions/3438415/convert-little-endian-file-into-big-endian). – user4581301 Jun 20 '17 at 23:17
  • 1
    You'll probably want to look into byte streams (`FileInputStream` specifically) for reading. – Kevin Anderson Jun 20 '17 at 23:19
  • @user4581301 this looks about right as far as I managed to do my own research while waiting for some advice. So would you say I should use FileInputStream along with FileChannel and ByteBuffer? Or perhaps reading file of that size with `Files.readAllBytes` would be better here? Or even combination of these two (I first need to check signature to make sure I use correct file). – pzaj Jun 20 '17 at 23:26
  • 1
    I am wary when giving out specific Java advice. Last time I wrote production Java was about ten years ago and probably tainted by years of C programming. I wouldn't have clicked this question if not for the C++ tag and a bit of experience in dealing with unsigned data types writing a C code generator in Java. – user4581301 Jun 21 '17 at 00:10
  • 1
    On the other hand, Java buffered very well back then and probably still does now. You may not see much of an improvement bulk loading the file all at once. – user4581301 Jun 21 '17 at 00:11
  • @user4581301 sorry about the C++ tag, but at least you probably saved me hours of wondering what is wrong! So I assume using DataInputStream methods like getUnsignedShort and getUnsignedByte are not going to solve endianess issue here? Well, I will try to figure it out myself now and probably also refer to the link from your first comment if that does not work. – pzaj Jun 21 '17 at 00:34
  • 1
    No worries. Note the trick the first answer pulls with `ByteBuffer.order`. If I read [the documentation](https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html#order-java.nio.ByteOrder-) correctly this should make your job a lot easier. Then use the appropriately sized `get...` function, store the number into one integer type bigger, and mask off any sign extension. – user4581301 Jun 21 '17 at 00:46
  • Thanks a lot @user4581301. I did some more reading and I eventually decided to drop my idea (of creating this and probably learning Java too). It just seems to become way too complicated compared to .NET implementation and even C++ implementation I have. – pzaj Jun 21 '17 at 11:57

0 Answers0