在 Java 中填充字节数组

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2614446/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 22:01:29  来源:igfitidea点击:

Filling a byte array in Java

javabytearrayvoiprtp

提问by Corleone

For part of a project I'm working on I am implementing a RTPpacket where I have to fill the header array of byte with RTP header fields.

对于我正在处理的项目的一部分,我正在实现一个 RTPpacket,我必须用 RTP 标头字段填充字节的标头数组。

  //size of the RTP header:
  static int HEADER_SIZE = 12; // bytes

  //Fields that compose the RTP header
  public int Version; // 2 bits
  public int Padding; // 1 bit
  public int Extension; // 1 bit
  public int CC; // 4 bits
  public int Marker; // 1 bit
  public int PayloadType; // 7 bits
  public int SequenceNumber; // 16 bits
  public int TimeStamp; // 32 bits
  public int Ssrc; // 32 bits

  //Bitstream of the RTP header
  public byte[] header = new byte[ HEADER_SIZE ];

This was my approach:

这是我的方法:

/*      
 * bits 0-1: Version
 * bit    2: Padding 
 * bit    3: Extension
 * bits 4-7: CC
 */
header[0] = new Integer( (Version << 6)|(Padding << 5)|(Extension << 6)|CC ).byteValue();

/* 
 * bit    0: Marker
 * bits 1-7: PayloadType
 */
header[1] = new Integer( (Marker << 7)|PayloadType ).byteValue();

/* SequenceNumber takes 2 bytes = 16 bits */
header[2] = new Integer( SequenceNumber >> 8 ).byteValue();
header[3] = new Integer( SequenceNumber ).byteValue();

/* TimeStamp takes 4 bytes = 32 bits */
for ( int i = 0; i < 4; i++ )
    header[7-i] = new Integer( TimeStamp >> (8*i) ).byteValue();

/* Ssrc takes 4 bytes = 32 bits */
for ( int i = 0; i < 4; i++ )
    header[11-i] = new Integer( Ssrc >> (8*i) ).byteValue();

Any other, maybe 'better' ways to do this?

任何其他,也许是“更好”的方法来做到这一点?

回答by Maurice Perry

I think I would use a ByteBuffer

我想我会使用ByteBuffer

ByteBuffer buf = ByteBuffer.wrap(header);
buf.setOrder(ByteOrder.BIG_ENDIAN);
buf.put((byte)((Version << 6)|(Padding << 5)|(Extension << 6)|CC));
buf.put((byte)((Marker << 7)|PayloadType));
buf.put((short)SequenceNumber);
buf.put(TimeStamp);
buf.put(Ssrc);

回答by Syntactic

You can convert an intdirectly to a bytein Java, without having to create an Integerobject. An explicit cast is required, because a bytehas a narrower range of possible values than an int. For instance:

您可以在 Java 中将anint直接转换为 a byte,而无需创建Integer对象。需要显式转换,因为 abyte的可能值范围比 an 窄int。例如:

header[1] = (byte) (Marker << 7 | PayloadType);

回答by bealex

There is one problem with such data. Usually protocols use unsigned bytes there and Java has signed bytes. So, for correct byte array fill I usually use such construct:

这样的数据存在一个问题。通常协议在那里使用无符号字节,Java 有有符号字节。因此,对于正确的字节数组填充,我通常使用这样的构造:

bytearray[index] = (byte) ((some integer-result calculation) & 0xff);

Simple casting to byte type won't work correctly.

简单地转换为字节类型将无法正常工作。

Update. "& 0xff" is not needed here. Simple cast will work.

更新。此处不需要“& 0xff”。简单的演员表会起作用。

回答by dfa

in addition to the presented answers give a try to Preon

除了给出的答案之外,还可以尝试一下Preon

回答by Wilfred Springer

With Preon, the RtpHeader could be represented like this:

使用Preon, RtpHeader 可以这样表示:

public class RtpHeader {

    @BoundNumber(size = "2")
    public int version;

    @Bound
    public boolean padding;

    @Bound
    public boolean extension;

    @BoundNumber(size="4")
    public int csrcCount;

    @Bound
    public boolean marker;

    @BoundNumber(size="7")
    public int payloadType;

    @BoundNumber(size="16", byteOrder = ByteOrder.BigEndian)
    public int sequenceNumber;

    @BoundNumber(size="32", byteOrder = ByteOrder.BigEndian)
    public int timestamp;

    @BoundNumber(size="32", byteOrder = ByteOrder.BigEndian)
    public int synchronizationSource;

    @BoundList(size="csrcCount")
    public int[] csrcs; 

}

Encoding this to bytes could be as simple as this:

将其编码为字节可能就像这样简单:

    Codec<RtpHeader> codec = Codecs.create(RtpHeader.class);
    RtpHeader header = new RtpHeader();
    ... // Setting header values
    OutputStream out = ...;
    Codecs.encode(header, codec, out);

However, bear in mind that encoding in Preon is still in early stages. It seems to work, for this particular case, but I am not going to make any guarantees.

但是,请记住,Preon 中的编码仍处于早期阶段。对于这种特殊情况,它似乎有效,但我不打算做出任何保证。

The benefit of using Preon is obviously the fact that you don't have to bother writing all of the encoding and decoding logic yourself.

使用 Preon 的好处显然是您不必费心编写所有的编码和解码逻辑。