我需要将一对长度为16位的二进制序列存储到一个字节数组(长度为2)中。一个或两个二进制数不会更改,因此执行转换的函数可能过度。例如,16位二进制序列是1111000011110001.如何将其存储在长度为2的字节数组中?
答案 0 :(得分:10)
String val = "1111000011110001";
byte[] bval = new BigInteger(val, 2).toByteArray();
还有其他选项,但我发现最好使用BigInteger
类来转换为字节数组,以解决这类问题。我更喜欢,因为我可以实例化来自String
的类,它可以代表各种基础,如8,16等,并且也可以输出它。
public static byte[] getRoger(String val) throws NumberFormatException,
NullPointerException {
byte[] result = new byte[2];
byte[] holder = new BigInteger(val, 2).toByteArray();
if (holder.length == 1) result[0] = holder[0];
else if (holder.length > 1) {
result[1] = holder[holder.length - 2];
result[0] = holder[holder.length - 1];
}
return result;
}
示例:
int bitarray = 12321;
String val = Integer.toString(bitarray, 2);
System.out.println(new StringBuilder().append(bitarray).append(':').append(val)
.append(':').append(Arrays.toString(getRoger(val))).append('\n'));
答案 1 :(得分:6)
我对将字符串转换为字节数组的所有解决方案感到失望,反之亦然 - 所有这些都是错误的(即使是上面的BigInteger解决方案),并且很少有效率应该如此高
我意识到OP只涉及到两个字节数组的位串,BitInteger方法似乎可以正常工作。但是,由于这篇文章是目前在Google中搜索“bit string to byte array java”时的第一个搜索结果,我将在这里发布我的一般解决方案,用于处理大字符串和/或大字节数组的人。
请注意,我的解决方案是我运行的唯一通过所有测试用例的解决方案 - 许多针对此相对简单问题的在线解决方案根本无效。
/**
* Zips (compresses) bit strings to byte arrays and unzips (decompresses)
* byte arrays to bit strings.
*
* @author ryan
*
*/
public class BitZip {
private static final byte[] BIT_MASKS = new byte[] {1, 2, 4, 8, 16, 32, 64, -128};
private static final int BITS_PER_BYTE = 8;
private static final int MAX_BIT_INDEX_IN_BYTE = BITS_PER_BYTE - 1;
/**
* Decompress the specified byte array to a string.
* <p>
* This function does not pad with zeros for any bit-string result
* with a length indivisible by 8.
*
* @param bytes The bytes to convert into a string of bits, with byte[0]
* consisting of the least significant bits in the byte array.
* @return The string of bits representing the byte array.
*/
public static final String unzip(final byte[] bytes) {
int byteCount = bytes.length;
int bitCount = byteCount * BITS_PER_BYTE;
char[] bits = new char[bitCount];
{
int bytesIndex = 0;
int iLeft = Math.max(bitCount - BITS_PER_BYTE, 0);
while (bytesIndex < byteCount) {
byte value = bytes[bytesIndex];
for (int b = MAX_BIT_INDEX_IN_BYTE; b >= 0; --b) {
bits[iLeft + b] = ((value % 2) == 0 ? '0' : '1');
value >>= 1;
}
iLeft = Math.max(iLeft - BITS_PER_BYTE, 0);
++bytesIndex;
}
}
return new String(bits).replaceFirst("^0+(?!$)", "");
}
/**
* Compresses the specified bit string to a byte array, ignoring trailing
* zeros past the most significant set bit.
*
* @param bits The string of bits (composed strictly of '0' and '1' characters)
* to convert into an array of bytes.
* @return The bits, as a byte array with byte[0] containing the least
* significant bits.
*/
public static final byte[] zip(final String bits) {
if ((bits == null) || bits.isEmpty()) {
// No observations -- return nothing.
return new byte[0];
}
char[] bitChars = bits.toCharArray();
int bitCount = bitChars.length;
int left;
for (left = 0; left < bitCount; ++left) {
// Ignore leading zeros.
if (bitChars[left] == '1') {
break;
}
}
if (bitCount == left) {
// Only '0's in the string.
return new byte[] {0};
}
int cBits = bitCount - left;
byte[] bytes = new byte[((cBits) / BITS_PER_BYTE) + (((cBits % BITS_PER_BYTE) > 0) ? 1 : 0)];
{
int iRight = bitCount - 1;
int iLeft = Math.max(bitCount - BITS_PER_BYTE, left);
int bytesIndex = 0;
byte _byte = 0;
while (bytesIndex < bytes.length) {
while (iLeft <= iRight) {
if (bitChars[iLeft] == '1') {
_byte |= BIT_MASKS[iRight - iLeft];
}
++iLeft;
}
bytes[bytesIndex++] = _byte;
iRight = Math.max(iRight - BITS_PER_BYTE, left);
iLeft = Math.max((1 + iRight) - BITS_PER_BYTE, left);
_byte = 0;
}
}
return bytes;
}
}
我在工作时感到无聊,所以我做了一些性能测试,比较了当N很大时接受的答案。 (假装忽略上面发布的BigInteger方法甚至不能作为一般方法正常工作的事实。)
这是使用大小为5M的随机位字符串和大小为1M的随机字节数组运行的:
String -> byte[] -- BigInteger result: 39098ms
String -> byte[] -- BitZip result: 29ms
byte[] -> String -- Integer result: 138ms
byte[] -> String -- BitZip result: 71ms
代码:
public static void main(String[] argv) {
int testByteLength = 1000000;
int testStringLength = 5000000;
// Independently random.
final byte[] randomBytes = new byte[testByteLength];
final String randomBitString;
{
StringBuilder sb = new StringBuilder();
Random rand = new Random();
for (int i = 0; i < testStringLength; ++i) {
int value = rand.nextInt(1 + i);
sb.append((value % 2) == 0 ? '0' : '1');
randomBytes[i % testByteLength] = (byte) value;
}
randomBitString = sb.toString();
}
byte[] resultCompress;
String resultDecompress;
{
Stopwatch s = new Stopwatch();
TimeUnit ms = TimeUnit.MILLISECONDS;
{
s.start();
{
resultCompress = compressFromBigIntegerToByteArray(randomBitString);
}
s.stop();
{
System.out.println("String -> byte[] -- BigInteger result: " + s.elapsed(ms) + "ms");
}
s.reset();
}
{
s.start();
{
resultCompress = zip(randomBitString);
}
s.stop();
{
System.out.println("String -> byte[] -- BitZip result: " + s.elapsed(ms) + "ms");
}
s.reset();
}
{
s.start();
{
resultDecompress = decompressFromIntegerParseInt(randomBytes);
}
s.stop();
{
System.out.println("byte[] -> String -- Integer result: " + s.elapsed(ms) + "ms");
}
s.reset();
}
{
s.start();
{
resultDecompress = unzip(randomBytes);
}
s.stop();
{
System.out.println("byte[] -> String -- BitZip result: " + s.elapsed(ms) + "ms");
}
s.reset();
}
}
}