Java Process InputStream错误?

时间:2010-11-30 12:12:14

标签: java c++ inputstream

嘿伙计们。所以这里是交易。我有一个Java程序运行C ++程序。 C ++进程通过简单地使用一些指针转换调用std :: cout上的write来向Java程序发送一些双精度数。 Java程序使用Process的getInputStream(),读取8个字节,并使用一些字节移位和Double.longBitsToDouble()将它们转换为double。我确保两个应用程序之间的类型大小和字节顺序匹配。现在,虽然这在大多数时间都有效,但每次都会发生错误。

我已将其中一个错误隔离到一个简单的字节序列中,我似乎无法正确传输。请查看以下代码段:

#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()
}

Java应用程序:

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()) + " ");
  }
}

这些是非常简单的示例,但它们用于演示我的问题。当我在Windows 7机器上运行它时。我得到以下Java输出:

b6 e1 d a b9 98 e3 48

预期输出

b6 e1 a b9 98 e3 48 40

不知何故,插入了额外的0x0d字节。然而,真正奇怪的是,如果在java应用程序中我们再读取一个字节(将8更改为9),我们得到

b6 e1 d a b9 98 e3 48 40 

这意味着InputStream实际上包含9个字节的数据,一旦删除了额外的0x0d,它就包含正确的数据。

你们觉得怎么样?正如我之前提到的,这不会经常发生,但是当它发生时,它是灾难性的。

提前致谢, zienkikk

3 个答案:

答案 0 :(得分:6)

默认情况下,

cout在文本模式下打开,我想说的是0xa(换行)字符在输出预处理期间转换为<CRLF>序列。

我认为不可能将二进制数据可靠地写入cout(例如,参见here),因此我将所需的输出转换为文本,然后在输入端反序列化(爪哇)。

答案 1 :(得分:3)

C ++正在将0x0A(即\ n)转换为0x0d0a,即\ r \ n。有一种方法可以阻止它这样做,无法帮助你解决它的问题。我不会自己使用iostreams作为二进制数据,我可能只使用write()或fwrite()。

答案 2 :(得分:2)

在我看来,你的Windows shell将UNIX样式行终止符LF(0xA)转换为Windows行终结者CRLF(0xD OxA)。

通常,出于此特定原因,不建议将二进制数据写入程序输出流。将长数据转换为文本,然后在Java端解析它。