Java write(str.getBytes()) vs writeBytes(str) [duplicate] - java

This question already has answers here:
writeBytes(str) vs write(str) in DataOutputStream
(2 answers)
Closed 3 years ago.
When using DataOutputStream to push Strings, I normally do the following:
DataOutputStream dout;
String str;
dout.write(str.getBytes());
I just came across the writeBytes() method of DataOutputStream, and my question is whether the above is equivalent to:
dout.writeBytes(str);
If not, what is difference and when should it be used?

No, it is not equivalent.
The Javadocs for writeBytes say
Writes out the string to the underlying output stream as a sequence of bytes. Each character in the string is written out, in sequence, by discarding its high eight bits.
So this will not work well except for ASCII Strings.
You should be doing
dout.write(str.getBytes(characterSet));
// remember to specify the character set, otherwise it become
// platform-dependent and the result non-portable
or
dout.writeChars(str);
or
dout.writeUTF(str);
Note that only the last method also writes the length of the String, so for the others, you probably need to know exactly what you are doing if you intend to later read it back.
The bigger question is why you need to use such a low-level protocol as DataOutputStream directly.

Related

Unable to write data(class) properly on socket in java(client) and read it on c++(server) [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
I am trying to develop a client server model here. Server is written in c++ and client is in java.
Now I have changed few things here to get the desired output.
I have tried two methods.
FIRST METHOD is as below:
I am writing two integer values in ByteBuffer and sending it on socket using write call. Code is as below:
Socket socket = new Socket(ip,port);
socket.setReuseAddress(true);
ObjectOutputStream ostream = new ObjectOutputStream(socket.getOutputStream());
ByteBuffer buffer = ByteBuffer.allocate(8);
buffer.putInt((int)11);
buffer.putInt((int)22);
ostream.write(buffer.array());
And i have written a c++ socket code to receive packets on socket but i am not getting desired data. This is the structure below on which i am mapping incoming data:
struct Test
{
int a;
int b;
};
When i run my application, i get some garbage value of 4 bytes.Output is as below:
Packet Size : 4
t.a : 83946924
t.b : 1836667692
I have also checked using linux command tcpdump and i am getting 4 bytes.
SECOND METHOD which i have tried is as below:
class Test implements Serializable
{
int a;
int b;
}
Socket socket = new Socket(ip,port);
socket.setReuseAddress(true);
ObjectOutputStream ostream = new
ObjectOutputStream(socket.getOutputStream());
Test t = new Test();
t.a = 11;
t.b = 12;
ostream.writeObject(t);
But using this method i am recieving 3 packets instead of 1.Server side output is as below:
================================================
Packet Size : 4
t.a : 83946924
t.b : 1836667692
================================================
Packet Size : 28
t.a : 83915379
t.b : 1953719636
================================================
Packet Size : 10
t.a : 28792
t.b : 2816
And on tcpdump also i can see there are 3 packets flowing of sizes 4, 28, 10 bytes respectively.
Can Anyone please guide me here that how can i send data and receive it on a c++ application and map it on a structure.
Ok, you have a few problems here. The most pressing one is that you don't know what you are actually writing to your socket (according to your comments above), so lets look into that.
Your Test class does not have a toString() method, so it defaults to the toString() in Object which outputs:
Returns a string representation of the object. In general, the
toString method returns a string that "textually represents" this
object. The result should be a concise but informative representation
that is easy for a person to read. It is recommended that all
subclasses override this method.
The toString method for class Object returns a string consisting of
the name of the class of which the object is an instance, the at-sign
character `#', and the unsigned hexadecimal representation of the hash
code of the object. In other words, this method returns a string equal
to the value of:
getClass().getName() + '#' + Integer.toHexString(hashCode())
In other words: Not the two integers that you want (btw, a simple sanity check would have been just throwing this string through a println() and checking the console).
You then hand this off to writeUTF() which does the following:
Writes a string to the underlying output stream using modified UTF-8
encoding in a machine-independent manner.
First, two bytes are written to the output stream as if by the
writeShort method giving the number of bytes to follow. This value is
the number of bytes actually written out, not the length of the
string. Following the length, each character of the string is output,
in sequence, using the modified UTF-8 encoding for the character. If
no exception is thrown, the counter written is incremented by the
total number of bytes written to the output stream. This will be at
least two plus the length of str, and at most two plus thrice the
length of str.
Which could explain why you get two packets (length + string), though I can't see if this is what you actually get, as I don't know what "t.a : 83946924" means. Perhaps it would be a better idea to put the raw data bytes from the packet into your question in hex format.
Anyway, that is what you do now. As a simple test to see if there is more wrong, or if this is it, you could try to use writeInt() instead:
out.writeInt(t.a);
out.writeInt(t.b);
Writes an int to the underlying output stream as four bytes, high byte
first. If no exception is thrown, the counter written is incremented
by 4.
It should be possible to verify with tcpdump if that gets through fine.
Though I would echo the advice from #sklott to go read about "marshaling" and "serialization", because you probably don't want to just write only the raw ints to your stream. Adding some header information or other "start of transfer" information would be a good idea - you could also add some CRC or something to the end, but since you are using TCP that should not be that necessary.

When should we use BufferedInputStream,FileInputStream or DataInputStream? [duplicate]

This question already has answers here:
Should I use DataInputStream or BufferedInputStream
(7 answers)
Closed 5 years ago.
I'm confused the above mentioned classes. When to use what? From my perspective every thing that comes in, is in the form of stream in java right? so which one is to use in what case to make the input more efficient? Also answer please can I use DataInputStream or BufferedInputStream in case of reading content from files?
FileInputStream
Is used for reading from files.
See the JavaDoc:
A FileInputStream obtains input bytes from a file in a file system. What files are available depends on the host environment. [...]
DataInputStream
Is used for reading in primitive Java types (that you might have written using a DataOutputStream) and provides convenience methods for that purpose, e.g. writeInt().
See the JavaDoc:
A data input stream lets an application read primitive Java data types
from an underlying input stream in a machine-independent way. [...]
BufferedInputStream
Is used to do buffered block reads from an InputStream (instead of single bytes) and increases performance if reading small chunks of data. Most of the time you want to use it for text processing.
See the JavaDoc:
A BufferedInputStream adds functionality to another input stream-namely, the ability to buffer the input[...].
Of course you can combine those as they are following the Decorator Pattern.
Example of writing primitive Java types to a file:
FileOutputStream write = new FileOutputStream
DataOutputStream out = new DataOutputStream(write);
out.writeInt(10);
write.close();

Write to an offset using DataOutputStream [duplicate]

This question already has answers here:
Inserting text into an existing file via Java
(8 answers)
Closed 6 years ago.
In my project, we are writing a file using DataOutputStream. We are writing different data types like short, byte, int and long and we are using respective methods in DataOutputStream like writeShort(), writeByte() etc.
Now, I want to edit one record in this file at a particular offset. I know the offset from which that record starts but I am not sure what is the right approach of writing to the file because only method in DataOutputStream supporting offset is the one which takes byte[].
I want to write the whole record which is a combination of different data types as mentioned above.
Can someone please tell me what is the correct approach for this?
In your case, you should use RandomAccessFile in order to read and/or write some content in a file at a given location thanks to its method seek(long pos).
For example:
try (RandomAccessFile raf = new RandomAccessFile(filePath, "rw")) {
raf.seek(offset);
// do something here
}
NB: The methods writeShort(), writeByte() etc. and their read counterparts are directly available from the class RandomAccessFile so using it alone is enough.

Java file handling classes [duplicate]

This question already has answers here:
What's the difference between InputStream and ByteArrayInputStream?
(4 answers)
Closed 6 years ago.
What is the difference between FileInputStream and ByteArrayInputStream?
When we should use them?
What is the benefits of using one over other
Streams
byte oriented stream (8 bit)
good for binary data such as a Java .class file, images etc.
good for "machine-oriented"
Readers/Writers
char (utf-16) oriented stream (16 bit)
one character at a time
good for text such as a Java source
good for "human-oriented" data
Buffered
many bytes/characters at a time
always useful unless proven otherwise
Both ByteArrayInputStream and FileInputStream serve the same purpose i.e. reading binary data and both implement a common abstract superclass InputStream.So it is really tough find out a sharp contrast among the two.But common logic dictates that arrays are already present in the memory hence they can be accessed much faster as compared to files which are present in the file system. Also if you go through the documentation of the two classes you will find out that read function of ByteArrayInputStream cannot block whereas the read function in FileInputStream blocks if no input is yet available.
So if you are confused about what to use when then think about these :
In what form my data is present, file or array?
Is speed really a requirement? If it is, then go for ByteArray. But remember you cannot store too much information in ByteArray as they are present in the memory.

Reading different encoding from the same InputStream [duplicate]

I'm working through the problems in Programming Pearls, 2nd edition, Column 1. One of the problems involves writing a program that uses only around 1 megabyte of memory to store the contents of a file as a bit array with each bit representing whether or not a 7 digit number is present in the file. Since Java is the language I'm the most familiar with, I've decided to use it even though the author seems to have had C and C++ in mind.
Since I'm pretending memory is limited for the purpose of the problem I'm working on, I'd like to make sure the process of reading the file has no buffering at all.
I thought InputStreamReader would be a good solution, until I read this in the Java documentation:
To enable the efficient conversion of bytes to characters, more bytes may be read ahead from the underlying stream than are necessary to satisfy the current read operation.
Ideally, only the bytes that are necessary would be read from the stream -- in other words, I don't want any buffering.
One of the problems involves writing a program that uses only around 1 megabyte of memory to store the contents of a file as a bit array with each bit representing whether or not a 7 digit number is present in the file.
This implies that you need to read the file as bytes (not characters).
Assuming that you do have a genuine requirement to read from a file without buffering, then you should use the FileInputStream class. It does no buffering. It reads (or attempts to read) precisely the number of bytes that you asked for.
If you then need to convert those bytes to characters, you could do this by applying the appropriate String constructor to a byte or byte[]. Note that for multibyte character encodings such as UTF-8, you would need to read sufficient bytes to complete each character. Doing that without the possibility of read-ahead is a bit tricky ... and entails "knowledge* of the character encoding you are reading.
(You could avoid that knowledge by using a CharsetDecoder directly. But then you'd need to use the decode method that operates on Buffer objects, and that is a bit complicated too.)
For what it is worth, Java makes a clear distinction between stream-of-byte and stream-of-character I/O. The former is supported by InputStream and OutputStream, and the latter by Reader and Write. The InputStreamReader class is a Reader, that adapts an InputStream. You should not be considering using it for an application that wants to read stuff byte-wise.

Categories