Reputation: 2414
Hey guys. So here is the deal. I have a Java program run a C++ program. The C++ process sends some doubles to the Java program by simply calling write on std::cout with some pointer casting. The Java program uses Process's getInputStream(), reads in 8 bytes and converts them into a double using some byte shifting and Double.longBitsToDouble(). I have made sure that the type sizes as well as byte orders match up between the 2 applications. Now, while this works most of the time, every so often an error occurs.
I have isolated one of the errors to a simple sequence of bytes that I seem to be unable to transfer correctly. Check out the following snippets:
#include <iostream>
int main(int argc, char** argv) {
long long l = 0x4048e398b90ae1b6;
char* ptr = (char*) &l;
std::cout.write(ptr, 8);
std::cout.flush();
// for (int i = 0; i < 8; ++i)
// std::cout.put(ptr[i]);
// std::cout.flush()
}
And the Java app:
public static void main(String[] argv) throws IOException {
Process p = Runtime.getRuntime().exec("prog.exe");
InputStream is = p.getInputStream();
for (int i = 0 ; i < 8; ++i) {
System.err.print(Long.toHexString(is.read()) + " ");
}
}
These are pretty simple examples but they server to demonstrate my problem. When I run this on my Windows 7 machine. I get the following Java output:
b6 e1 d a b9 98 e3 48
The expected output is
b6 e1 a b9 98 e3 48 40
Somehow, an extra 0x0d byte is inserted. However, what is really weird is that if inside the java app we read one more byte (change the 8 to a 9), we get
b6 e1 d a b9 98 e3 48 40
This means that the InputStream actually contained 9 bytes of data and once that extra 0x0d is removed it contains the correct data.
What do you guys think? As I mentioned before, this doesn't happen often but when it does, it is disastrous.
Thanks in advance, zienkikk
Upvotes: 2
Views: 800
Reputation: 310893
C++ is translating 0x0A, which is \n, to 0x0d0a, which is \r\n. There's a method to stop it doing that, can't help you with what it is. I wouldn't use iostreams for binary data myself, I would probably just use write() or fwrite().
Upvotes: 3
Reputation: 45576
Looks to me like your Windows shell converts UNIX style line terminator LF ( 0xA ) to Windows Line Terminator CRLF( 0xD OxA ).
Generally it is not advisable to write binary data to the program output stream for this particular reason. Convert your long data to text and then parse it on a Java side.
Upvotes: 2
Reputation: 54148
cout
is by default opened in text mode, what I would say is happening is that the 0xa (linefeed) character is getting converted to a <CRLF>
sequence during output preprocessing.
I don't think it's possible to reliably write binary data to cout
(see here for example), so I would convert your desired output into text, and then deserialize on the input side (Java).
Upvotes: 6