Difference in read/write between Windows Vs Linux
Hi,
Can you please write, whether it is a bug or my ignorance. I thought, if a java program runs in Windows then it will run in other platform too, without editing any code. It proved me wrong. So is it a bug?
Ref: Fedora linux version 5
Kernel ver. 2.6.17
jdk version - build 1.5.0_06-b05
I was working on a web service. The server side program connects to an application using socket program and sends back data to client.
While it was working very fine with Windows XP. When I moved the service to Linux (above said linux). The program stopped working. When I explored it, I found 3 things.
1. I was using PrintWriter
PrintWriter outputStream = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()), true);
to write into the socket. It works fine in Windows but not in Linux. ie. it sends different bytes in linux. Thus fails. When I changed it to BufferedOutputStream it works fine.
BufferedOutputStream outputStream = new BufferedOutputStream (socket.getOutputStream());
2. I was using BufferedReader to read
BufferedReader inputStream = new BufferedReader(new InputStreamReader(socket.getInputStream()));
data from socket. It reads. But byte varies from expectation. The same program works very well with windows.
I used DataInputStream now. that works. but..
DataInputStream inputStream = new DataInputStream(socket.getInputStream());
3. While reading it was suppossed to read 2098 bytes, instead it reads 1448 bytes. It reads correctly in Windows, but not in the above said linux.
Is it a bug or there is a difference in reading and writing from socket between Windows and Linux ( even though it is same JVM).
Thanks
Sasi.
[1765 byte] By [
Sasia] at [2007-10-3 3:04:11]

In Windows the new line string is "\r\n"In Linux its "\n"Maybe you have some logic dependent on the new line string.
The default character coding is different for Windows and Linux and the line
PrintWriter outputStream = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()), true);
uses the default character encoding.
This is very easy to fix - one replaces
OutputStreamWriter(socket.getOutputStream())
with
OutputStreamWriter(socket.getOutputStream(),"your choice of character encoding")
where I normally use "utf-8" as the encoding since it covers just about everything.
Of course one has to do a similar thing for the Reader!
P.S. I hope you are not trying to use this to send non-text data (i.e. binary data) between client and server because if you are you then have a further problem.
Message was edited by:
sabre150
Thanks a lot for both of you.
I believe, \r\n Vs \n could not be the reason. Because, I was sending binary data.
With regard to "utf-8", I thought of that but I did not try to issue it in the function. Because, I was trying to send and receive raw binary data.
Now, You may ask that why did you use PrintWriter. Because, the data had unsigned byte values. So I converted everything in to char array and send it. especially, whereever unsigned byte was required, I used (byte & Oxff). It worked very well with Windows. So I just go ahead doing other things.
Here my question is, I assumed that if a program is written in java and complied on jvm x, then irrespective of the underlying OS, if the jvm is the same x, then the program should run without error. Is it wrong. If it is not wrong, then is it a jre bug?
Did you see my third point of my original problem statement. How to solve that.
Thanks.
Sasi.
Sasia at 2007-7-14 20:54:10 >

Problem is even when you are sending binary row data you are sending them as character data. So the rules that govern the carracter encoding governes the data transfer.
>Here my question is, I assumed that if a program is written in java and
>complied on jvm x, then irrespective of the underlying OS, if the jvm is
>the same x, then the program should run without error. Is it wrong. If it is
>not wrong, then is it a jre bug?
Not always correct! becouse some of the settings like which character encoding to use. Java take them from underlaying platform. So whenyou are doing a coss platform transfer they might give problems.
LRMKa at 2007-7-14 20:54:10 >

> I assumed that if a program is written in java and complied on jvm x, then
> irrespective of the underlying OS, if the jvm is the same x, then the program
> should run without error.
What do you mean by "error"?
PrintWriter's methods do whatever the API docs say they do, reagardless of OS.
But if you are using Readers/Writers for binary data and your program makes
assumptions about the particular bytes that are written - assumptions that are
not guaranteed by the API docs - then that's an error of logic.
Depending on precisely what the wrong assumption is, it may only give rise
unwanted program behaviour with one OS but not with another. But it's wrong in
either case.
> Thanks a lot for both of you.
>
> I believe, \r\n Vs \n could not be the reason.
> Because, I was sending binary data.
Then you should not be using Writer at all!
>
> With regard to "utf-8", I thought of that but I did
> not try to issue it in the function. Because, I was
> trying to send and receive raw binary data.
Then you should not be using Writer at all!
>
> Now, You may ask that why did you use PrintWriter.
> Because, the data had unsigned byte values.
Makes no difference - you should not be using Writer at all!
> So I
> converted everything in to char array and send it.
Will cause you problems at some point on some platform unless you use Base64 or HEX encoding.
> especially, whereever unsigned byte was required, I
> used (byte & Oxff). It worked very well with
> Windows. So I just go ahead doing other things.
I use byte & 0xff for dealing with unsigned valued but your use sounds dangerous.
>
> Here my question is, I assumed that if a program is
> written in java and complied on jvm x, then
> irrespective of the underlying OS, if the jvm is the
> same x, then the program should run without error. Is
> it wrong. If it is not wrong, then is it a jre bug?
Your program will work if you have not used any implicit or explicit platform dependencies. For example, if in your program then you have hard codes a path as "C:\Program Files" then it will work on Windows (but then only if it has a C drive) but not on Unix.
Any program has to deal with a number of platform specific features and Java protects you from them as much as possible BUT you must deal with things like Locale, EOL and default character encoding.
No! Of course it is not a jre bug. You have coded to a specific platform and are then are suprised when it fails on other platforms.
>
> Did you see my third point of my original problem
> statement. How to solve that.
Since I don't have a view of your code I can't make an informed comment. I think I can guess what the problem is but I won't speculate.
I love it. "I didn't bother to read the specs, I didn't care about the documentations, I didn't keep a constant environment, but if it doesn't do what I want: it must be a Java bug."
(a) If you are sending binary you should not use Writers and Readers at all, you should use Input/OutputStreams. Readers and Writers are for character data only.
(b) There is no guarantee anywhere that read() will read the maximum number of bytes, on any platform and from any kind of an input, whether Socket, URL, file, ... As its documentation clearly says, it can return up to 'len' bytes. You just have to read in a loop until you get what you want, or use DataInputStream.readFully().
ejpa at 2007-7-14 20:54:10 >

Thank you very much. It has educated me a lot. Now, I am reading the header first, identifing the packet length and then reading corect number of bytes. It works fine with both Windows and Linux. Thank you once again for your help.Sasi.
Sasia at 2007-7-14 20:54:10 >
