How do I work with binary data in Java? [duplicate] - java

This question already has answers here:
Reading/writing a BINARY File with Strings?
(2 answers)
Closed 8 years ago.
I'm working on a simple VM/interpreter kind of program for a simple toy language I implemented. Currently the compiler emits textual assembly instructions such as push and add to be executed by the VM.
Recently I figured it would be a better idea to actually compile to binary opcodes instead of textual ones, for performance and space. (It doesn't actually matter in this toy project, but this is for learning).
Soon I realized, even though generally I consider myself a decent Java programmer, that I have no idea how to work with binary data in Java. No clue.
Regarding this, I have two questions:
How can I save binary data to a file? For example say I want to save the byte 00000001 and then the byte 00100000 to a file (each byte will be an opcode for the VM) - how can I do that?
How can I read binary data from a file on disk, save it in variables, parse it and manipulate it? Do I use the usual I/0 and parsing techniques I use with regular Strings, or is this something different?
Thanks for your help

You should be able to use any OutputStream to do this, because they all have a write method that takes a byte. For example, you could use a FileOutputStream.
Similarly, you can use an InputStream's read method for reading bytes.

OutputStream and its subtypes have methods to write bytes to files. DataOutputStream has additional methods to write int, long, float, double, etc. if you need those, although it writes them in big endian byte order. The corresponding input streams have equivalent methods for reading.

You may want to try to use ByteArrayInputStream and DataOutputStream
Refer to the Oracle documentation for details.
Also, checkout this similar question: How to output binary data to a file in Java?

Use a FileOutputStream. It has a write(byte[] b) method to write an array of bytes to a file and a write(int b) method to write a single byte to the file.
So, to save 00000001 followed by 00100001, you can do :
FileOutputStream file = new FileOutputStream(new File(path));
file.write(1);
file.write(33);
Similarly you can read FileInputStream for reading from a binary file.

Related

How to store primitives using BufferedOutputStream [duplicate]

This question already has answers here:
Creating an efficient way of sending integers over a network. TCP
(2 answers)
Closed 4 years ago.
Hello everyone I'm in my second semester of CS and we are on the subject of file IO using InputStreams and OutputStreams, everything was relatively simple until this subject for me. I am a little confused with the BufferedOutputStream class. I understand that it stores data in a buffer of the specified size, then writes it all at once to be more efficient than a byte by byte stream. What I do not understand is that, unlike DataInputStream, which has methods to write specific primitives, I can only write byte arrays. How would I store primitives like int, long, double, etc.. using the BufferedOutputStream. Thank you guys in advance!
You could use guava library for converting primitves to byteArray. It has pretty sweet syntax:
byte[] bytearray = Ints.toByteArray(201);
where 201 is the primitive integer you wish to use. Since now you have byteArray you can easily use it in BufferedOutputStream.
Wrap a DataOutputStream around it.

ByteArrayInputStream, SequenceInputStream, StringReader where to use

There are too many java.io classes, for some of them i really dont understand when we need them, for example:
ByteArrayInputStream, ByteArrayOutputStream
SequenceInputStream,
PushbackInputStream, PushbackReader
StringReader...
I mean some real-life usages
Can someone please explain...
I would say that your question is too wide.
However it is possible to give a very basic overview of java.io package. It contains interfaces and classes for data input and output operations, such as reading bytes from file. There are only few basic interfaces / classes:
DataInput / ObjectInput - readig Java primitives and objects
DataOutput / ObjectOutput - writing Java primitives and objects
InputStream - reading individual bytes
OutputStream - writing individial bytes
Reader - reading character data
Writer - writing character data
There are other useful interfaces (like Closeable), but these are less significant.
It is best if you read the JavaDoc of these classes. Some examples:
It is pretty obvious that you would use FileOutputStream to write something into a file.
Character data is represented by bytes (defined by character encoding), so you can wrap any output stream using OutputStreamWriter.
You have byte[] and want to read from it just like from InputStream? Use ByteArrayInputStream.
You want to be able to return read bytes back to the reader (usually only a single pass-through is supported)? Wrap your reader with PushbackReader.
You have some String and want to read from it just like from Reader? Use StringReader.
...
So if you need some specific stream/reader/writer, check java.io package, search the internet and ask a question on SO if needed.
Of course then there is java.nio package, which you should know about. But that is for a different topic.

Mapping java variables data to C Structures and write a c compatible file

I have a java class file with three arrayLists, one with type String, one with type Integer and other is ArrayList with type (ArrayList(String)). I have to write these these arraylists to a structure in C with character arrays, integers and short and output a file in a specefic format extension. The file has to be readable again by the same application. What is the best way to trasnfer the data from java to c structure and then output the c structure in a file. Thank you
There is no "C compatible file" format. If you have C structs written to disk file directly, then those are in an ad-hoc binary format. Exact format depends on things like packing and padding of the struct, byte order, word size of the CPU (like, 32 or 64 bit), etc.
So, start by defining the format, then forget it is produced by C.
Once you have the format defined, you can write a program to parse it in Java. If it is short with fixed length records, I'd probably create a class, which internally has just a private byte[] array, and then methods to manipulate it, save it and load it.
I suggest you write/read the data to a ByteBuffer using native byte ordering. The rest is up to you are to how you do it.
A library which might help is Javolution's Struct library which helps you map C structs onto ByteBuffers. This can help with C's various padding rules i.e.the exact layout might not be obvious.

Magic number file checking

I'm attempting to read magic numbers/bytes to check the format of a file. Will reading a file byte by byte work in the same way on a Linux machine?
Edit: The following shows to get the magic bytes from a class file using an int. I'm trying to do the same for a variable number of bytes.
http://www.rgagnon.com/javadetails/java-0544.html
I'm not sure that I understand what you are trying to do, but it sounds like what you are trying to do isn't the same thing as what the code that you are linking to is doing.
The java class format is specified to start with a magic number, so that code can only be used to verify if a file might be a java class or not. You can't use the same logic and apply it to arbritraty file formats.
Edit: .. or do you only want to check for wav files?
Edit2: Everything in Java is in big endian, that means that you can use DataInputStream.readInt to read the first four bytes from the file, and then compare the returned int with 0x52494646 (RIFF as a big endian integer)

problem when Java and C++ talk with each other

I have a program in C++ and it writes a binary file on disk. Then I use a Java program to read the number. The problem is the number read is different from the number written.
Say, I write an integer 4 using c++ and get back 67108864 when use JAVA to read it (using readint()). I suspect its due to big or small endian. Do you have any simple solutions to solve this?
Java's java.nio buffers let you specify the endianness.
See http://download.oracle.com/javase/6/docs/api/java/nio/ByteBuffer.html especially the order method which lets you specify endianness and the getInt method which lets you read an int.
To read a file using a ByteBuffer do something like:
ByteBuffer buffer = new RandomAccessFile(myFile, "r")
.getChannel.map(MapMode.READ, offset, length);
Remember to close it when you're done.

Categories

Resources