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.
Related
I have a 2D dynamic array containing integers and strings that I need to send to the server. The array comprises of 100,000 columns. One possibility is to copy the array into a file and send it to the server and the server can parse it. Whereas, the other possibility is to do serialisation. I am doing socket programming for the first time and the solution that I am looking for should be optimal. Considering the size of the array, I dont think converting each element into bytes would be good. Please could you give me a slight hint or guide me on how I should proceed.
Serializing the data to bytes for streaming over a socket, or serializing the data to a file, and sending the file is essentially the same thing. If you serialize to a file you can fall back on an established protocol like FTP, which will be easier for a developer new to sockets.
Again however, realize they're essentially the same problem. Breaking down a programmatic object into bytes for writing to an output stream.
Edit:
Depending on the content of your strings, using the zip compression algorithm is a good bet. The more repeated content in your strings, the better compression ratio you'll get. Here's just an example file format:
Number of ints to follow. (As you've not given the max ROWS in your 2D array I can't say how many bytes this will take. We'll assume its 8 bytes.)
All ints. This will take 3*NUM_INTS bytes.
Zip compressed strings, separated by a space.
I'm making a lot of assumptions here because you've not been specific enough in your question, or any replies you've given.
I would convert it to json or xml and send that. Is not the most efficient solutions in terms of speed, but is the most portable.
A simple approach would be to use a DataOutputStream and wrap it around the socket you are using: DataOutputStream dOut = new DataOutputStream(socket.getOuputStream()).
You then could just establish your own simple binary protocol like this (it's for an 1D array, but it can be easily extended to work for 2D arrays as well):
//first write the amount of elements in the array
dOut.write(array.length());
//now write every element
for (Object obj : array) {
if (obj instanceof Integer) {
dOut.writeByte(0); //0 = Integer
dOut.writeInt((Integer) obj);
} else
if (obj instanceof String) {
dOut.writeByte(1); //1 = String
dOut.writeUTF((String) obj); //UTF-8 encoded String
}
// ...
}
If you want to optimize for data size then you could also use a GZIPOutputStream in between the socket's OutputStream and your DataOutputStream like this: new DataOutputStream(new GZIPOutputStream(socket.getOutputStream())). Of course you have to decompress it on server side for this to work.
I'm writing an Android app, trying to parse some binary data received via Bluetooth, containing various signed and unsigned 1-4 byte integers. I'm given to understand that the best (or possibly only) way to interpret bytes as unsigned numbers is via an input stream. My code is:
ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
ObjectInput in = new ObjectInputStream(bis);
The second line, for some reason, throws a StreamCorruptedException with no data in it. What am I doing wrong? Also how is it conceptually possible to "corrupt" a bunch of bytes?
Unless the data has been written by ObjectOutputStream, you shouldn't use ObjectInputStream - that's very specific to Java's binary serialization. If this is just binary data, 4 bytes for a 32-bit integer etc, then you probably want DataInputStream instead - but you should validate that your data is big-endian, which is what DataInputStream will handle it.
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.
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.
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.