在C语言中使用结构解析二进制文件头/数据结构的java等价物是什么?

在C语言中使用结构解析二进制文件头/数据结构的java等价物是什么?,java,struct,Java,Struct,因此,在文件i/o中主要使用了C语言,下面是我在读取文件时的思维方式: 创建反映文件头的结构 读取足够的文件以填充标头 根据标题内容进行验证和决策,并根据需要读取文件的其余部分 在java中,使用头信息读取二进制文件的标准方法是什么?请不要说一次遍历一个变量的文件流 请不要说一次遍历一个变量的文件流 很抱歉,这就是在Java中必须做的事情,因为Java没有结构 例如,使用ByteBuffer读取a,如下所示: try (InputStream inputStream = /*code here*

因此,在文件i/o中主要使用了C语言,下面是我在读取文件时的思维方式:

  • 创建反映文件头的结构
  • 读取足够的文件以填充标头
  • 根据标题内容进行验证和决策,并根据需要读取文件的其余部分 在java中,使用头信息读取二进制文件的标准方法是什么?请不要说一次遍历一个变量的文件流

    请不要说一次遍历一个变量的文件流

    很抱歉,这就是在Java中必须做的事情,因为Java没有结构

    例如,使用
    ByteBuffer
    读取a,如下所示:

    try (InputStream inputStream = /*code here*/) {
        // code here
    
        // Read TCP Header
        ByteBuffer buf = ByteBuffer.allocate(20);
        if (inputStream.read(buf.array(), 0, buf.capacity()) != buf.capacity())
            throw new EOFException();
        short sourcePort           = buf.getShort();
        short destinationPort      = buf.getShort();
        int   sequenceNumber       = buf.getInt();
        int   acknowledgmentNumber = buf.getInt();
        short flags                = buf.getShort();
        byte  dataOffset = (byte)((flags >> 12) & 0xF);
        flags &= 0xFFF;
        short windowSize           = buf.getShort();
        short checksum             = buf.getShort();
        short urgentPointer        = buf.getShort();
        byte[] options = new byte[(dataOffset - 5) * 4];
        if (inputStream.read(options, 0, options.length) != options.length)
            throw new EOFException();
    
        // code here
    }
    
    您还可以按如下方式提取标志:

    boolean ns  = (flags & 0x100) != 0;
    boolean cwr = (flags & 0x080) != 0;
    boolean ece = (flags & 0x040) != 0;
    boolean urg = (flags & 0x020) != 0;
    boolean ack = (flags & 0x010) != 0;
    boolean psh = (flags & 0x008) != 0;
    boolean rst = (flags & 0x004) != 0;
    boolean syn = (flags & 0x002) != 0;
    boolean fin = (flags & 0x001) != 0;
    
    如果您在
    TcpHeader
    类中实现了这一点,那么您可能只需要将
    标志
    值作为一个字段,并在getter方法中实现它,例如

    public boolean isAck() {
        return (flags & 0x010) != 0;
    }
    
    记住,Java没有无符号原语,所以所有的值都是有符号的

    请不要说一次遍历一个变量的文件流

    很抱歉,这就是在Java中必须做的事情,因为Java没有结构

    例如,使用
    ByteBuffer
    读取a,如下所示:

    try (InputStream inputStream = /*code here*/) {
        // code here
    
        // Read TCP Header
        ByteBuffer buf = ByteBuffer.allocate(20);
        if (inputStream.read(buf.array(), 0, buf.capacity()) != buf.capacity())
            throw new EOFException();
        short sourcePort           = buf.getShort();
        short destinationPort      = buf.getShort();
        int   sequenceNumber       = buf.getInt();
        int   acknowledgmentNumber = buf.getInt();
        short flags                = buf.getShort();
        byte  dataOffset = (byte)((flags >> 12) & 0xF);
        flags &= 0xFFF;
        short windowSize           = buf.getShort();
        short checksum             = buf.getShort();
        short urgentPointer        = buf.getShort();
        byte[] options = new byte[(dataOffset - 5) * 4];
        if (inputStream.read(options, 0, options.length) != options.length)
            throw new EOFException();
    
        // code here
    }
    
    您还可以按如下方式提取标志:

    boolean ns  = (flags & 0x100) != 0;
    boolean cwr = (flags & 0x080) != 0;
    boolean ece = (flags & 0x040) != 0;
    boolean urg = (flags & 0x020) != 0;
    boolean ack = (flags & 0x010) != 0;
    boolean psh = (flags & 0x008) != 0;
    boolean rst = (flags & 0x004) != 0;
    boolean syn = (flags & 0x002) != 0;
    boolean fin = (flags & 0x001) != 0;
    
    如果您在
    TcpHeader
    类中实现了这一点,那么您可能只需要将
    标志
    值作为一个字段,并在getter方法中实现它,例如

    public boolean isAck() {
        return (flags & 0x010) != 0;
    }
    
    请记住,Java没有无符号的原语,所以所有的值都是有符号的。

    对不起,在找到合适的值时花了很长时间

    终于找到了一个可用的库:

    我没有意识到要找到一本书有那么难——我只是在需要的时候写了自己的

    以下是他们文档中的一个示例:

    import java.nio.ByteBuffer;
    class Clock extends Struct { // Hardware clock mapped to memory.
     Unsigned16 seconds  = new Unsigned16(5); // unsigned short seconds:5
     Unsigned16 minutes  = new Unsigned16(5); // unsigned short minutes:5
     Unsigned16 hours    = new Unsigned16(4); // unsigned short hours:4
     Clock() {
         setByteBuffer(Clock.nativeBuffer(), 0);
     }
     private static native ByteBuffer nativeBuffer();
    }
    
    对不起,找合适的东西花了很长时间

    终于找到了一个可用的库:

    我没有意识到要找到一本书有那么难——我只是在需要的时候写了自己的

    以下是他们文档中的一个示例:

    import java.nio.ByteBuffer;
    class Clock extends Struct { // Hardware clock mapped to memory.
     Unsigned16 seconds  = new Unsigned16(5); // unsigned short seconds:5
     Unsigned16 minutes  = new Unsigned16(5); // unsigned short minutes:5
     Unsigned16 hours    = new Unsigned16(4); // unsigned short hours:4
     Clock() {
         setByteBuffer(Clock.nativeBuffer(), 0);
     }
     private static native ByteBuffer nativeBuffer();
    }
    


    可能最好使用专门的框架来解析提供某种结构的二进制数据,看一看和

    可能最好使用专门的框架来解析提供某种结构的二进制数据,看一看和

    使用a,它基本上是(这就是我在C中读取结构化二进制文件的方式)。这是一篇关于ByteBuffer(s)的文章。@Krythic这完全是无用的建议。使用结构读取文件在C中是一种糟糕的做法。我不知道你为什么要在Java中复制它。@Krythic这可能会让人震惊,但Notch不是权威或大师。“Java并不是最快的语言,但我怀疑如果我用一种我不太喜欢的语言来完成Minecraft,所以我很高兴能做出这样的选择。”-我们不应该再提这个人了。使用a,它基本上是的Java版本(这是我在C中读取结构化二进制文件的方式).是一篇关于ByteBuffer的文章。@Krythic这完全是无用的建议。使用结构读取文件在C语言中是不好的做法。我不知道你为什么要在Java中复制它。@Krythic这可能会让人震惊,但Notch不是权威或大师。”Java并不是最快的语言,但我怀疑如果我用一种我不太喜欢的语言来完成Minecraft,那么我会完成它,所以我对这个选择感到高兴。“-我们不应该再提某人的名字。我意识到这是离题的,但是…即使是这样一个很小的读数也可能无法在第一次尝试时完成;这并不一定意味着已经达到EOF。在(buf.haslaining()){channel.read(buf);}。这是如何解析一个4位无符号后跟一个24位无符号的?移位和掩蔽。有点不像要求的那样。@VGR是的,你是对的。主要的问题是如何使用
    字节缓冲
    ,所以我把
    输入流
    逻辑保持得有点太简单了。不过,我不知道把它变成一个通道有什么帮助,因为它也会遇到同样的问题m、 @BillK不知道从何处获得4+24位,但这只有28位,数据是以完整字节读取的,即使是C。虽然问题没有提到子字节头字段,但我选择TCP头作为示例来展示如何处理这些字段,以及多字节大端字段。它确实显示了如何获得4位无符号值,即
    dataOffset
    字段,剩余的12位在
    标志
    字段中,总共16位,即2个字节。@Andreas当您分析压缩头时,它们不是。它们是分散的2-3-4位整数以及标志和16/20/24+位字段,通常没有一个在您喜欢的边界上对齐。这就是问题的全部要点。例如:我意识到这是离题的,但是……即使是这样一个很小的阅读,第一次尝试也可能无法完成;这并不一定意味着已经达到EOF。使用
    while(buf.haslaining()){channel.read(buf);}
    。这是如何解析一个4位无符号后跟一个24位无符号的?移位和掩蔽。有点不像要求的那样。@VGR是的,你是对的。主要的问题是如何使用
    字节缓冲
    ,所以我把
    输入流
    逻辑保持得有点太简单了。不过,我不知道把它变成一个通道有什么帮助,因为它也会遇到同样的问题m、 @BillK不知道从何处获得4+24位,但这只有28位,数据是以完整字节读取的,即使是C。虽然问题没有提到子字节头字段,但我选择TCP头作为示例来展示如何处理这些字段,以及多字节大端字段。它确实显示了如何获得4位无符号值,即
    dataOffset
    字段,