【问题标题】:Java Process InputStream bug?Java 处理 InputStream 错误?
【发布时间】:2011-05-17 20:21:52
【问题描述】:

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

我已将其中一个错误隔离为一个我似乎无法正确传输的简单字节序列。查看以下 sn-ps:

#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,它就包含正确的数据。

你们怎么看?正如我之前提到的,这种情况并不经常发生,但一旦发生,那就是灾难性的。

提前致谢, 曾基克

【问题讨论】:

    标签: java c++ inputstream


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

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

      出于这个特殊原因,通常不建议将二进制数据写入程序输出流。将您的长数据转换为文本,然后在 Java 端对其进行解析。

      【讨论】:

      • 这里不涉及shell。
      • @EJP。同意。我的 C++ 越来越生锈了。
      【解决方案3】:

      cout 默认情况下以文本模式打开,我想说的是,在输出预处理期间,0xa(换行符)字符正在转换为&lt;CRLF&gt; 序列。

      我认为不可能可靠地将二进制数据写入cout(例如参见here),所以我会将您想要的输出转换为文本,然后在输入端(Java)反序列化。

      【讨论】:

      • 您也可以使用以二进制模式打开的显式文件来传递数据。
      • @Karl - 是的,我不知道如果这样做的话,我不知道如何建议 OP 连接流,但这是一个肯定的选择。
      • 感谢您的快速回复。这正是错误所在。使用文件会减慢我传入的数据量,但由于这段代码是为了在 Unix 机器上运行,我认为它就足够了(我只是懒得启动虚拟机并对其进行测试)。我知道将二进制数据写入标准输出有点难,但这似乎是实现预期结果的最简单方法。
      猜你喜欢
      • 1970-01-01
      • 2017-02-25
      • 1970-01-01
      • 1970-01-01
      • 2014-08-29
      • 1970-01-01
      • 2019-11-05
      • 2013-08-16
      • 2014-03-28
      相关资源
      最近更新 更多