Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java-优化将值作为位写入bytebuffer_Java_Networking_Byte_Bit_Bytebuffer - Fatal编程技术网

Java-优化将值作为位写入bytebuffer

Java-优化将值作为位写入bytebuffer,java,networking,byte,bit,bytebuffer,Java,Networking,Byte,Bit,Bytebuffer,我目前正在编写一些网络代码(这是我的第一台服务器),并有一个关于优化特定函数的快速问题,该函数将值写入位,然后将它们打包成字节。优化此函数的原因是,在将数据打包发送到多个客户端时,每个服务器都会使用它数千次 为了更好地解释函数试图实现的功能,可以使用一个示例: 值3可由两位表示。 在二进制中,它看起来像00000011。该函数将此二进制值转换为11000000。再次调用该函数时,它将知道从第三个最高有效位(从右/十进制32开始的第三个)开始,最多向当前字节写入6位。如果还有剩余的位要写,它将从一

我目前正在编写一些网络代码(这是我的第一台服务器),并有一个关于优化特定函数的快速问题,该函数将值写入位,然后将它们打包成字节。优化此函数的原因是,在将数据打包发送到多个客户端时,每个服务器都会使用它数千次

为了更好地解释函数试图实现的功能,可以使用一个示例: 值3可由两位表示。 在二进制中,它看起来像
00000011
。该函数将此二进制值转换为
11000000
。再次调用该函数时,它将知道从第三个最高有效位(从右/十进制32开始的第三个)开始,最多向当前字节写入6位。如果还有剩余的位要写,它将从一个新字节开始

如果有多个小于字节的值,则这样做的目的是节省空间

我当前的函数如下所示:

 private ByteBuffer out = ByteBuffer.allocate(1024);
 private int bitIndex = 0;
 /*
  * Value: The value to write
  * Amount: The number of bits to represent the value in.
  */
     public OutputBuffer writeBits(long value, int amount) {
    if (bitIndex != 0) {
        int remainingBits = 8 - bitIndex;
        int bytePos = out.position() - 1;
        byte current = out.get(bytePos);
        int shiftAmount = amount - remainingBits;
        int bitsWritten = amount < remainingBits ? amount : remainingBits;
        int clearShiftAmount = 8 - bitsWritten + 56;

        byte b;
        if (shiftAmount < 0) {
            b = (byte) (current | (value << remainingBits - amount));
        } else {
            //deal with negative values
            long temp = (value >> shiftAmount);
            temp =  (temp << clearShiftAmount);
            temp = (byte) (temp >>> clearShiftAmount);
            b = (byte) (current | temp);
        }
        out.put(bytePos,b);
        bitIndex = (bitIndex + bitsWritten) % 8;
        amount -= bitsWritten;
    }
    if (amount <= 0) {
        return this;
    }
    bitIndex = amount & 7;
    int newAmount = amount - bitIndex;
    //newValue should not equal 2047
    for (int i = 0; i != newAmount; i += 8) {
        writeByte((byte) ((value >> i)), false);
    }
    if (bitIndex > 0)
        writeByte((byte) (value << (8 - bitIndex)), false);
    return this;
}
private ByteBuffer out=ByteBuffer.allocate(1024);
私有int-bitIndex=0;
/*
*Value:要写入的值
*Amount:表示中的值的位数。
*/
公共输出缓冲区写入息税前利润(长值,整数金额){
如果(bitIndex!=0){
整数剩余位数=8-比特索引;
int bytePos=out.position()-1;
字节电流=out.get(bytePos);
int shiftAmount=金额-剩余位;
int BITSWRITED=金额移位计数);
温度=(温度>>清除量);
b=(字节)(当前温度);
}
输出(bytePos,b);
bitIndex=(bitIndex+位写入)%8;
金额-=写入的位;
}
如果(金额>i)),则为假);
}
如果(bitIndex>0)

writeByte((byte)(value这样的东西怎么样

private ByteBuffer out = ByteBuffer.allocate(1024);
private int position = 0;
private int dataBits = 0;
private long data = 0;

/**
 * value: The value to write
 * amount: The number of bits to represent the value in.
 */
public void writeBits(long value, int amount) {
    if (amount <= 0) {
        // need to flush what's left
        if (dataBits > 0) {
            dataBits = Byte.SIZE;
        }
    } else {
        int totalBits = dataBits + amount;

        // need to handle overflow?
        if (totalBits > Long.SIZE) {
            // the new data is to big for the room that remains;  by how much?
            int excess = totalBits - Long.SIZE;

            // drop off the excess and write what's left
            writeBits(value >> excess, amount - excess);

            // now we can continue processing just the rightmost excess bits
            amount = excess;
        }

        // push the bits we're interested in all the way to the left of the long
        long temp = value << (Long.SIZE - amount);

        // make room for any existing (leftover) data bits, filling with zeros to the left (important)
        temp = temp >> dataBits;

        // append the new data to the existing
        data |= temp;

        // account for new bits of data
        dataBits += amount;
    }

    while (dataBits >= Byte.SIZE) {
        // shift one byte left, rotating the byte that falls off into the rightmost byte
        data = Long.rotateLeft(data, Byte.SIZE);

        // add the rightmost byte to the buffer
        out.put(position++, (byte)(data & 0xff));

        // drop off the rightmost byte
        data &= 0xffffffffffffff00L;

        // setup for next byte
        dataBits -= Byte.SIZE;
    }
}
private ByteBuffer out=ByteBuffer.allocate(1024);
私有int位置=0;
私有int-dataBits=0;
私有长数据=0;
/**
*value:要写入的值
*amount:表示中的值的位数。
*/
公共无效可写息税前利润(长期价值,整数金额){
如果(金额>超额,金额-超额);
//现在我们可以继续处理最右边的多余位
金额=超额;
}
//把我们感兴趣的部分一直推到长条的左边
长温度=值>数据位;
//将新数据附加到现有数据
数据|=温度;
//说明新的数据位
数据位+=金额;
}
while(数据位>=字节大小){
//向左移动一个字节,旋转掉到最右边的字节
数据=Long.rotateLeft(数据,字节大小);
//将最右边的字节添加到缓冲区
输出(位置++,(字节)(数据和0xff));
//删除最右边的字节
数据&=0xFFFFFFFFFF00L;
//下一个字节的设置
数据位-=字节大小;
}
}
这里有一个更好的解决方案(比我以前的解决方案)使用递归,它非常适合这个问题

private static final long[] mask = { 0, 0x1, 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f, 0xff };

private ByteBuffer out = ByteBuffer.allocate(1024);
private int position = 0;
private int dataBits = 0;
private byte remainder = 0;

/**
 * value: The value to write
 * amount: The number of bits to represent the value in.
 */
public void writeBits(long value, int amount) {
    if (amount <= Long.SIZE) {
        if (amount > 0) {
            // left align the bits in value
            writeBitsLeft(value << (Long.SIZE - amount), amount);
        } else {
            // flush what's left
            out.put(position++, remainder);
        }
    } else {
        // the data provided is invalid
        throw new IllegalArgumentException("the amount of bits to write is out of range");
    }
}

/**
 * write amount bits from the given value
 * 
 * @param value represents bits aligned to the left of a long
 * @param amount bits left to be written from value
 */
private void writeBitsLeft(long value, int amount) {
    if (amount > 0) {
        // how many bits are left to be filled in the current byte?
        int room = Byte.SIZE - dataBits;

        // how many bits are we going to add to the current byte?
        int taken = Math.min(amount, room);

        // rotate those number of bits into the rightmost position
        long temp = Long.rotateLeft(value, taken);

        // add count taken to the count of bits in the current byte
        dataBits += taken;

        // add in that number of data bits
        remainder &= temp & mask[taken];

        // have we filled the byte yet?
        if (Byte.SIZE == dataBits) {
            out.put(position++, remainder);

            // reset the current byte
            remainder = 0;
            dataBits = 0;

            // process any bits left over
            writeBitsLeft(temp, amount - taken);
        }
    } 
} // writeBitsLeft()
private static final long[]mask={0,0x1,0x3,0x7,0xf,0x1f,0x3f,0x7f,0xff};
private ByteBuffer out=ByteBuffer.allocate(1024);
私有int位置=0;
私有int-dataBits=0;
专用字节余数=0;
/**
*value:要写入的值
*amount:表示中的值的位数。
*/
公共无效可写息税前利润(长期价值,整数金额){
如果(金额0){
//左对齐值中的位

writeBitsLeft(值好的,我调整了您的原始算法以删除一些多余的数学运算,并减少了约10%(在我的机器上从0.016毫秒减少到约0.014毫秒)。我还更改了测试,使每个算法运行1000次

在最后一个for循环中似乎也有一些节省,因为相同的位被反复移位。如果您能以某种方式保留上一次移位的结果,这可能会有所帮助。但这会改变字节的输出顺序,因此需要更多的考虑

public void writeBits3(long value, int amount) {
    if (bitIndex != 0) {
        int remainingBits = 8 - bitIndex;
        int bytePos = out.position() - 1;
        byte current = out.get(bytePos);
        int shiftAmount = amount - remainingBits;

        int bitsWritten = 0;
        if (shiftAmount < 0) {
            bitsWritten = amount;
            out.put(bytePos, (byte) (current | (value << -shiftAmount)));
        } else {
            bitsWritten = remainingBits;
            out.put(bytePos, (byte) (current | (value >> shiftAmount)));
        }

        bitIndex += bitsWritten;
        amount -= bitsWritten;
        if (bitIndex >= 8) {
            bitIndex = 0;
        }
    }
    if (amount <= 0) {
        return;
    }
    bitIndex = amount & 7;
    int newAmount = amount - bitIndex;
    long newValue = (value >> bitIndex);
    for (; newAmount >= 8; newAmount -= 8) {
        out.put((byte) (newValue >> newAmount));
    }
    out.put((byte) (value << (8 - bitIndex)));
}
public void writeBits3(长值,整数金额){
如果(bitIndex!=0){
整数剩余位数=8-比特索引;
int bytePos=out.position()-1;
字节电流=out.get(bytePos);
int shiftAmount=金额-剩余位;
int bitswrited=0;
如果(移位量<0){
比特数=金额;
输出(字节)(当前|(值>移位数));
}
bitIndex+=位写入;
金额-=写入的位;
如果(bitIndex>=8){
bitIndex=0;
}
}
如果(金额>指数);
对于(;newAmount>=8;newAmount-=8){
out.put((字节)(newValue>>newAmount));
}

out.put((字节)(在接收端的值为“你看到比特串<代码> 11111 0011”/代码>,你怎么知道前两个比特是“<代码> 3”/代码>,它不是真正的前3位被发送为<代码> 7 < /C>?因为接收端知道数据是如何被打包的,所以它会读2位,然后4,等等。你考虑过使用<代码> java?UTIL BitSet < /C>?它可以做任何你想做的事情,不需要复杂的编码,也不需要自己管理缓冲区。请阅读Javadoc。@JimGarrison位集上没有设置特定值的方法(例如,值5需要biset.set(0)、biset.set(2))除此之外,它还必须被颠倒。我想它会更复杂?哦,这是一个想法。我回到Javadoc,现在意识到这个类的功能是多么的不足。它可以使用相当多的功能,比如原语和集合的任意子字符串之间的逻辑运算。没关系。好的l、 我编写了一个单元测试来度量您的解决方案