วิธีการแปลงไบต์เป็นการแสดงสตริงไบนารี


95

ยกตัวอย่างเช่นบิตในไบต์ที่Bมี10000010วิธีการที่ฉันสามารถกำหนดบิตสตริงตัวอักษรที่เป็นstrstr = "10000010"

แก้ไข

Bผมอ่านไบต์จากไฟล์ไบนารีและเก็บไว้ในอาร์เรย์ไบต์ ฉันใช้System.out.println(Integer.toBinaryString(B[i])). ปัญหาคือ

(a) เมื่อบิตเริ่มต้นด้วย (ซ้ายสุด) 1 เอาต์พุตไม่ถูกต้องเนื่องจากแปลงB[i]เป็นค่า int เชิงลบ

(b) ถ้าบิตเริ่มต้นด้วย0เอาต์พุตจะละเว้น0เช่นสมมติว่าB[0]มี 00000001 เอาต์พุตจะถูก1แทนที่ด้วย00000001


2
ฉันสับสน; นี่คือเคล็ดลับหรือไม่?
Dave Newton

1
คุณกำลังถามว่าจะแปลง a byteเป็นสตริงในฐาน 2 ได้อย่างไร?
SLaks

ฉันเพิ่งเพิ่มคำตอบหัวข้ออื่นทำเช่นนี้ (แปลงค่าให้กับสตริงของตัวเลขไบนารี) ซึ่งทำงานสำหรับBoolean, Byte, Short, Char, และInt stackoverflow.com/a/54950845/501113Long
disorderly3quilibrium

String # Format () อาจจัดการสิ่งนี้ได้ถ้าคุณบอกให้ใช้ความกว้าง 8 ในทำนองเดียวกัน System.out.printf ()
NomadMaker

คำตอบ:


172

ใช้Integer#toBinaryString():

byte b1 = (byte) 129;
String s1 = String.format("%8s", Integer.toBinaryString(b1 & 0xFF)).replace(' ', '0');
System.out.println(s1); // 10000001

byte b2 = (byte) 2;
String s2 = String.format("%8s", Integer.toBinaryString(b2 & 0xFF)).replace(' ', '0');
System.out.println(s2); // 00000010

DEMO


ฉันลองวิธีนี้แล้ว Bในกรณีของฉันฉันอ่านไบต์จากไฟล์ไบนารีและเก็บไว้ในอาร์เรย์ไบต์ ฉันใช้System.out.println(Integer.toBinaryString(B[i])). เมื่อฉันใช้วิธีนี้ปัญหาคือ (a) เมื่อบิตขึ้นต้นด้วย (ซ้ายสุด) 1 ผลลัพธ์ไม่ถูกต้องเพราะแปลงB[i]เป็นค่า int เชิงลบ (b) ถ้าบิตเริ่มต้นด้วย 0 เอาต์พุตจะละเว้น0เช่นสมมติว่าB[0]มี00000001เอาต์พุตจะ1แทน00000001
ฌอน

1
@Sean: a) เกิดขึ้นเนื่องจาก a byteใน Java เป็นจำนวนเต็มเสริมของ 8 บิตที่เซ็นชื่อสอง ค่าต่ำสุดของมันคือ -128 (2 ^ 8) และค่าสูงสุดคือ127; b) คุณสามารถแก้ไขได้อย่างง่ายดายโดยใช้สิ่งนี้String.format("%8s", Integer.toBinaryString(b)).replace(' ', '0')เพื่อกดซ้ายของสตริงผลลัพธ์ด้วยศูนย์
João Silva

1
@ João: ขอบคุณสำหรับคำแนะนำของคุณ คุณมีความคิดเกี่ยวกับวิธีการระบุ (a) วิธีจัดเก็บรูปแบบบิตดั้งเดิม (เริ่มต้นด้วย 1) ลงในสตริง
Sean

1
@ ฌอน: ใช่แค่&กับ0xFF.
João Silva

14
@Sean: & 0xFFพื้นแปลงไปยังsigned byte unsigned integerยกตัวอย่างเช่นเช่นคุณกล่าวว่าเป็นตัวแทนจาก-129 11111111111111111111111110000001ในกรณีนี้คุณโดยทั่วไปต้องการแรก (อย่างน้อยอย่างมีนัยสำคัญ) 8 บิตเพื่อให้คุณและ ( &) กับ0xFF( 00000000000000000000000011111111) ได้อย่างมีประสิทธิภาพการทำความสะอาด 1 10000001ไปทางซ้ายที่เราไม่ได้ดูแลเกี่ยวกับการทิ้งออกเพียง
João Silva

37

ฉันใช้สิ่งนี้ ความคิดที่คล้ายกันกับคำตอบอื่น ๆ แต่ไม่เห็นแนวทางที่แน่นอนเลย :)

System.out.println(Integer.toBinaryString((b & 0xFF) + 0x100).substring(1));

0xFFคือ 255 หรือ11111111(ค่าสูงสุดสำหรับไบต์ที่ไม่ได้ลงชื่อ) 0x100คือ 256 หรือ100000000

&upcasts ไบต์เป็นจำนวนเต็ม ณ จุดนั้นอาจเป็นอะไรก็ได้ตั้งแต่0- 255( 00000000ถึง11111111ฉันไม่รวม 24 บิตนำหน้า) + 0x100และ.substring(1)มั่นใจว่าจะมีศูนย์นำหน้า

ฉันจับเวลาเทียบกับคำตอบของJoão Silvaและเร็วกว่า 10 เท่า http://ideone.com/22DDK1ฉันไม่ได้ใส่คำตอบของ Pshemo เนื่องจากไม่ได้ใส่แผ่นอย่างถูกต้อง


เฮ้! มีคำถามเกี่ยวกับเรื่องนี้ ฉันมีสตริงการแสดง Base64 ของ PDF ฉันต้องแปลงเป็น Binary โดยทั่วไป Base64-> byte-> binary รหัสนี้จะใช้ได้หรือไม่
Sid

+ 0x100 ทำอะไรได้บ้าง? คุณกำลังเพิ่ม 256 ในจำนวนเต็มผลลัพธ์ แต่ทำไมล่ะ?
Conner Dassen

1
@ConnerDassen ช่วยให้แน่ใจว่าสตริงไบนารีเป็น 0 เบาะ ตัวอย่างเช่นถ้าbเป็นหาก1ไม่มี+ 0x100คุณก็จะได้"1"เป็นสตริงของคุณ โดยการเพิ่ม1คุณจะได้รับและถ้าคุณใช้เวลาย่อยละเลยตัวอักษรตัวแรกที่คุณจะได้รับที่เหมาะสม100000001 หากคุณไม่ต้องการให้สายของคุณจะเป็นเบาะที่คุณสามารถเพียงแค่การใช้งาน"00000001" Integer.toBinaryString(b & 0xff)การ& 0xffแก้ไขปัญหาส่วนเสริมเชิงลบ / สอง
Raekye

8

นี่คือสิ่งที่คุณกำลังมองหา?

การแปลงจาก String เป็น byte

byte b = (byte)(int)Integer.valueOf("10000010", 2);
System.out.println(b);// output -> -126

การแปลงจาก byte เป็น String

System.out.println(Integer.toBinaryString((b+256)%256));// output -> "10000010"

หรือตามที่João Silva กล่าวในความคิดเห็นของเขาเพื่อเพิ่มชั้นนำ0เราสามารถจัดรูปแบบสตริงเป็นความยาว 8 และแทนที่ช่องว่างนำหน้าด้วยศูนย์ดังนั้นในกรณีของสตริงที่" 1010"เราจะได้รับ"00001010"

System.out.println(String.format("%8s", Integer.toBinaryString((b + 256) % 256))
                         .replace(' ', '0'));

6

คุณสามารถตรวจสอบแต่ละบิตในไบต์จากนั้นต่อท้าย 0 หรือ 1 เข้ากับสตริง นี่คือวิธีการช่วยเหลือเล็กน้อยที่ฉันเขียนเพื่อทดสอบ:

public static String byteToString(byte b) {
    byte[] masks = { -128, 64, 32, 16, 8, 4, 2, 1 };
    StringBuilder builder = new StringBuilder();
    for (byte m : masks) {
        if ((b & m) == m) {
            builder.append('1');
        } else {
            builder.append('0');
        }
    }
    return builder.toString();
}

3

รับแต่ละไบต์และแปลงเป็นสตริง บอกว่าไบต์มี 8 บิตและเราสามารถรับได้ทีละบิตผ่านการย้ายบิต ตัวอย่างเช่นเราย้ายบิตที่สองของไบต์ 6 บิตไปทางขวาบิตที่สองที่สุดท้ายของบิต 8 บิตจากนั้นและ (&) ด้วย 0x0001 เพื่อทำความสะอาดบิตด้านหน้า

public static String getByteBinaryString(byte b) {
    StringBuilder sb = new StringBuilder();
    for (int i = 7; i >= 0; --i) {
        sb.append(b >>> i & 1);
    }
    return sb.toString();
}

โปรดแก้ไขคำตอบของคุณเพื่อให้คำอธิบายว่าเหตุใดรหัสนี้จึงตอบคำถามได้ คำตอบที่ใช้รหัสเท่านั้นเป็นสิ่งที่ท้อแท้เพราะไม่ได้สอนวิธีแก้ปัญหา
DavidPostill

2

โค้ดนี้จะแสดงให้เห็นว่า java int สามารถแบ่งออกเป็น 4 ไบต์ติดต่อกันได้อย่างไร จากนั้นเราสามารถตรวจสอบแต่ละไบต์โดยใช้วิธีการของ Java เทียบกับการสอบสวนแบบไบต์ / บิตระดับต่ำ

นี่คือผลลัพธ์ที่คาดหวังเมื่อคุณเรียกใช้โค้ดด้านล่าง:

[Input] Integer value: 8549658

Integer.toBinaryString: 100000100111010100011010
Integer.toHexString: 82751a
Integer.bitCount: 10

Byte 4th Hex Str: 0
Byte 3rd Hex Str: 820000
Byte 2nd Hex Str: 7500
Byte 1st Hex Str: 1a

(1st + 2nd + 3rd + 4th (int(s)) as Integer.toHexString: 82751a
(1st + 2nd + 3rd + 4th (int(s)) ==  Integer.toHexString): true

Individual bits for each byte in a 4 byte int:
00000000 10000010 01110101 00011010

นี่คือรหัสที่จะเรียกใช้:

public class BitsSetCount
{
    public static void main(String[] args) 
    {
        int send = 8549658;

        System.out.println( "[Input] Integer value: " + send + "\n" );
        BitsSetCount.countBits(  send );
    }

    private static void countBits(int i) 
    {
        System.out.println( "Integer.toBinaryString: " + Integer.toBinaryString(i) );
        System.out.println( "Integer.toHexString: " + Integer.toHexString(i) );
        System.out.println( "Integer.bitCount: "+ Integer.bitCount(i) );

        int d = i & 0xff000000;
        int c = i & 0xff0000;
        int b = i & 0xff00;
        int a = i & 0xff;

        System.out.println( "\nByte 4th Hex Str: " + Integer.toHexString(d) );
        System.out.println( "Byte 3rd Hex Str: " + Integer.toHexString(c) );
        System.out.println( "Byte 2nd Hex Str: " + Integer.toHexString(b) );
        System.out.println( "Byte 1st Hex Str: " + Integer.toHexString(a) );

        int all = a+b+c+d;
        System.out.println( "\n(1st + 2nd + 3rd + 4th (int(s)) as Integer.toHexString: " + Integer.toHexString(all) );

        System.out.println("(1st + 2nd + 3rd + 4th (int(s)) ==  Integer.toHexString): " + 
                Integer.toHexString(all).equals(Integer.toHexString(i) ) );

        System.out.println( "\nIndividual bits for each byte in a 4 byte int:");

        /*
         * Because we are sending the MSF bytes to a method
         * which will work on a single byte and print some
         * bits we are generalising the MSF bytes
         * by making them all the same in terms of their position
         * purely for the purpose of printing or analysis
         */
        System.out.print( 
                    getBits( (byte) (d >> 24) ) + " " + 
                    getBits( (byte) (c >> 16) ) + " " + 
                    getBits( (byte) (b >> 8) ) + " " + 
                    getBits( (byte) (a >> 0) ) 
        );


    }

    private static String getBits( byte inByte )
    {
        // Go through each bit with a mask
        StringBuilder builder = new StringBuilder();
        for ( int j = 0; j < 8; j++ )
        {
            // Shift each bit by 1 starting at zero shift
            byte tmp =  (byte) ( inByte >> j );

            // Check byte with mask 00000001 for LSB
            int expect1 = tmp & 0x01; 

            builder.append(expect1);
        }
        return ( builder.reverse().toString() );
    }

}


2

ขอโทษฉันรู้ว่ามันช้าไปหน่อย ... แต่ฉันมีวิธีที่ง่ายกว่ามาก ... ในการสตริงไบนารี:

//Add 128 to get a value from 0 - 255
String bs = Integer.toBinaryString(data[i]+128);
bs = getCorrectBits(bs, 8);

เมธอด getCorrectBits:

private static String getCorrectBits(String bitStr, int max){
    //Create a temp string to add all the zeros
    StringBuilder sb = new StringBuilder();
    for(int i = 0; i < (max - bitStr.length()); i ++){
        sb.append("0");
    }

    return sb.toString()+ bitStr;
}

1
String byteToBinaryString(byte b){
    StringBuilder binaryStringBuilder = new StringBuilder();
    for(int i = 0; i < 8; i++)
        binaryStringBuilder.append(((0x80 >>> i) & b) == 0? '0':'1');
    return binaryStringBuilder.toString();
}

1

คุณสามารถทำงานกับBigIntegerดังตัวอย่างด้านล่างโดยเฉพาะอย่างยิ่งถ้าคุณมี256 บิตขึ้นไป:

String string = "10000010";
BigInteger biStr = new BigInteger(string, 2);

System.out.println("binary: " + biStr.toString(2));
System.out.println("hex: " + biStr.toString(16));
System.out.println("dec: " + biStr.toString(10));

อีกตัวอย่างหนึ่งที่ยอมรับไบต์:

String string = "The girl on the red dress.";

byte[] byteString = string.getBytes(Charset.forName("UTF-8"));
System.out.println("[Input String]: " + string);
System.out.println("[Encoded String UTF-8]: " + byteString);

BigInteger biStr = new BigInteger(byteString);
System.out.println("binary: " + biStr.toString(2)); // binary
System.out.println("hex: " + biStr.toString(16));   // hex or base 16
System.out.println("dec: " + biStr.toString(10));  // this is base 10

ผลลัพธ์:

[Input String]: The girl on the red dress.
[Encoded String UTF-8]: [B@70dea4e

binary: 101010001101000011001010010000001100111011010010111001001101100001000000110111101101110001000000111010001101000011001010010000001110010011001010110010000100000011001000111001001100101011100110111001100101110
hex: 546865206769726c206f6e20746865207265642064726573732e

คุณยังสามารถแปลงไบนารีเป็นรูปแบบไบต์ได้

try {
   System.out.println("binary to byte: " + biStr.toString(2).getBytes("UTF-8"));
} catch (UnsupportedEncodingException e) {e.printStackTrace();}

หมายเหตุ: สำหรับการจัดรูปแบบสตริงสำหรับรูปแบบไบนารีของคุณคุณสามารถใช้ตัวอย่างด้านล่าง

String.format("%256s", biStr.toString(2).replace(' ', '0'));  // this is for the 256 bit formatting

1

คำตอบง่ายๆอาจเป็น:

System.out.println(new BigInteger(new byte[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})); // 0
System.out.println(new BigInteger(new byte[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1})); // 1
System.out.println(new BigInteger(new byte[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0})); // 256
System.out.println(new BigInteger(new byte[]{0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0})); // 65536
System.out.println(new BigInteger(new byte[]{0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0})); // 16777216
System.out.println(new BigInteger(new byte[]{0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0})); // 4294967296
System.out.println(new BigInteger(new byte[]{0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0})); // 1099511627776
System.out.println(new BigInteger(new byte[]{0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0})); // 281474976710656
System.out.println(new BigInteger(new byte[]{0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0})); // 72057594037927936
System.out.println(new BigInteger(new byte[]{0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0})); // 18446744073709551616
System.out.println(new BigInteger(new byte[]{0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0})); // 4722366482869645213696
System.out.println(new BigInteger(new byte[]{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})); // 1208925819614629174706176
System.out.println(Long.MAX_VALUE);                                              // 9223372036854775807

0

เราทุกคนรู้ดีว่า Java ไม่ได้ให้คำหลักที่ไม่ได้ลงนาม นอกจากนี้byteตามดั้งเดิมข้อมูลจำเพาะของ Java หมายถึงค่าระหว่างและ−128 127ยกตัวอย่างเช่นถ้าbyteเป็นcastไปยังintJava จะแปลความหมายแรกbitเป็นsignและการใช้ขยายสัญญาณ

จากนั้นวิธีการแปลงไบต์ที่มากกว่า 127เป็นตัวแทนสตริงไบนารีได้อย่างไร ??

ไม่มีอะไรป้องกันคุณจากการดูbyteเพียงเป็น 8 บิตและตีความบิตเหล่านั้นเป็นค่าระหว่างและ0 255นอกจากนี้คุณต้องจำไว้ว่าไม่มีอะไรที่คุณสามารถทำได้เพื่อบังคับให้ตีความตามวิธีการของคนอื่น หากเมธอดยอมรับ a byteวิธีนั้นจะยอมรับค่าระหว่าง−128และ127เว้นแต่จะระบุไว้อย่างชัดเจนเป็นอย่างอื่น

ดังนั้นวิธีที่ดีที่สุดในการแก้ปัญหานี้คือแปลงbyteค่าเป็นไฟล์intค่าโดยการเรียกByte.toUnsignedInt()วิธีการหรือหล่อเป็นแบบดั้งเดิมint (int) signedByte & 0xFFคุณมีตัวอย่างที่นี่:

public class BinaryOperations
{
    public static void main(String[] args)
    {
        byte forbiddenZeroBit = (byte) 0x80;

        buffer[0] = (byte) (forbiddenZeroBit & 0xFF);
        buffer[1] = (byte) ((forbiddenZeroBit | (49 << 1)) & 0xFF);
        buffer[2] = (byte) 96;
        buffer[3] = (byte) 234;

        System.out.println("8-bit header:");
        printBynary(buffer);
    }

    public static void printBuffer(byte[] buffer)
    {
        for (byte num : buffer) {
            printBynary(num);
        }
    }

    public static void printBynary(byte num)
    {
        int aux = Byte.toUnsignedInt(num);
        // int aux = (int) num & 0xFF; 
        String binary = String.format("%8s', Integer.toBinaryString(aux)).replace(' ', '0');
        System.out.println(binary);
    }
}

เอาต์พุต

8-bit header:
10000000
11100010
01100000
11101010

0

คำแนะนำอีกอย่างสำหรับผู้ที่ต้องการแปลงไบต์เป็นสตริงไบนารีอย่างหนาแน่น: ใช้ตารางค้นหาแทนการใช้การดำเนินการสตริงเหล่านั้นตลอดเวลา ซึ่งเร็วกว่าการเรียกใช้ฟังก์ชัน convert ซ้ำแล้วซ้ำเล่า

public class ByteConverterUtil {

  private static final String[] LOOKUP_TABLE = IntStream.range(0, Byte.MAX_VALUE - Byte.MIN_VALUE + 1)
                                                        .mapToObj(intValue -> Integer.toBinaryString(intValue + 0x100).substring(1))
                                                        .toArray(String[]::new);

  public static String convertByte(final byte byteValue) {
    return LOOKUP_TABLE[Byte.toUnsignedInt(byteValue)];
  }

  public static void main(String[] args){
    System.out.println(convertByte((byte)0)); //00000000
    System.out.println(convertByte((byte)2)); //00000010
    System.out.println(convertByte((byte)129)); //10000001
    System.out.println(convertByte((byte)255)); //11111111
  }


}

-1

แค่เดาที่นี่ แต่ถ้าคุณมี Byte คุณไม่สามารถเรียกใช้ toString () บนวัตถุเพื่อรับค่าได้หรือไม่? หรือมองไปที่apiโดยใช้ byteValue ()?

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.