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