【问题标题】:C struct written in file, open with Java用文件编写的 C 结构,用 Java 打开
【发布时间】:2012-04-15 14:30:05
【问题描述】:

例如在 C 中我有结构:

typedef struct {
    int number;
    double x1;
    double y1;
    double x2;
    double y2;
    double x3;
    double y3;
} CTRstruct;`

然后我将它写入文件fwrite(&tr, 1, sizeof(tr), fp);(tr - 它的 CTRstruct var,fp - 文件指针);

那我需要用Java来阅读它!我真的不知道如何从文件中读取结构...我尝试用ObjectInputStream() 读取它,最后一个想法是用RandomAccessFile() 读取但我也不知道如何...(readLong(), readDouble()也不起作用,它可以正常工作,但不能读取正确的数据)。那么,知道如何使用 Java 从二进制文件中读取 C 结构吗?


如果有趣的话,我的读整数版本(但它很难看,我不知道如何处理double):

公共类 MyDataInputStream 扩展 DataInputStream{

public MyDataInputStream(InputStream AIs) {
    super(AIs);
}

public int readInt1() throws IOException{
    int ch1 = in.read();
    int ch2 = in.read();
    int ch3 = in.read();
    int ch4 = in.read();
    if ((ch1 | ch2 | ch3 | ch4) < 0)
        throw new EOFException();
    return ((ch4 << 24) + (ch3 << 16) + (ch2 << 8) + (ch1 << 0));
}

使用 double 我们可以以相同的方式处理(例如使用 int 或使用 long (8bytes),然后使用本机 func 转换为 double)。

【问题讨论】:

  • 你写struct到file的方式不对,看看这个:stackoverflow.com/questions/10153155/…
  • 真正正确的答案是不要将结构的内存表示转储到这样的文件中。
  • 是的,mb这样做很愚蠢,但我需要这样做..(我的意思是在文件中写入孔结构)
  • 您确实将文件打开为二进制文件? IE。 fp = fopen("some/file", "wb");?然后你必须注意诸如填充和Java如何处理endianess的整数,以及double是否是相同的格式。
  • @Daunn 好吧,因为在所有情况下都没有答案能够提供“正确”的答案,所以最简单的解决方案就是读取全零。当然,这几乎总是错误的——但这至少比每 100 次错误要好。使调试大大更简单

标签: java c++ c


【解决方案1】:

您不应该使用整个struct 中的fwrite,因为您将不可避免地遇到paddingendian-ness 的问题。 C 端会将整个struct 转储到内存中的方式,以及编译器为性能等而放入的所有差距。这就是“不可移植性之母”!

相反,您应该使用协议缓冲区、JSON 或其他可移植序列化方式来完成您的任务。

【讨论】:

    【解决方案2】:

    使用library that serializes your data to disk。这将使将其读回 Java 变得容易得多。确保库使用有据可查的存储格式。

    【讨论】:

      【解决方案3】:

      您必须找出在您执行程序的架构中使用了这些 C 类型(int、double)和字节序(感谢 andrew cooke)的大小,并在 Java 中使用相同大小的类型。

      【讨论】:

      【解决方案4】:

      DataInputStream 是在 Java 中读取原始输入的典型方式——我认为你应该能够做到

      int number = dataInputStream.readInt();
      double x1 = dataInputStream.readDouble();
      ...
      double y3 = dataInputStream.readDouble();
      

      但我不能 100% 确定字节顺序和其他问题是否兼容。

      【讨论】:

      • 我希望int 和第一个double 之间的填充需要处理。
      • 这完全取决于 C 决定如何在内存中表示它;最好一次真正地做一个字段,而不是仅仅转储内存中的表示。
      • 那么第一个问题是:int 是 4 字节还是 8 字节?如果它是 4 字节,我们可能必须使用填充,如果不合适,但突然我们不能再使用 java int 而是需要一个 long。等等等等。这只是一个非常糟糕的主意。
      • int 4 byte,在我看来,导致这些方法工作不正确
      【解决方案5】:

      好吧,万一您可以选择 JNI,您可以在 C 中读回它。使用swig,您可以轻松地公开您的结构,以及它从文件中读取的函数。当然,JNI 带来的所有麻烦都不值得单独解决这个问题,但您可能已经在使用它了。

      【讨论】:

        【解决方案6】:

        我使用http://javolution.org/(或https://github.com/javolution/javolution)。 即使该项目看起来“死”了,我也没有发现任何比“Struct”更简单高效的东西。

        看看这里了解如何创建一个映射缓冲区的类: Struct Javadoc

        【讨论】:

          猜你喜欢
          • 2011-03-28
          • 1970-01-01
          • 1970-01-01
          • 2022-06-15
          • 1970-01-01
          • 2021-02-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多