Jak przekonwertować bajt na jego reprezentację w postaci łańcucha binarnego

94

Na przykład bity w bajcie Bto 10000010, jak mogę przypisać bity do ciągu strdosłownie, to znaczy str = "10000010".

Edytować

Czytam bajt z pliku binarnego i zapisuję go w tablicy bajtów B. Używam System.out.println(Integer.toBinaryString(B[i])). problemem jest

(a) gdy bity zaczynają się od (skrajnie lewy) 1, dane wyjściowe są nieprawidłowe, ponieważ są konwertowane B[i]na ujemną wartość int.

(b) jeśli bity zaczynają się od 0, wyjście ignoruje 0, na przykład, załóżmy, że B[0]ma 00000001, wyjście jest 1zamiast00000001

Sean
źródło
2
Jestem zmieszany; czy to sztuczka?
Dave Newton,
1
Czy pytasz, jak przekonwertować byteciąg znaków w bazie 2?
SLaks,
Właśnie dodałem odpowiedź do innego wątku dla tej operacji (przekształcenie wartości ciąg cyfr binarnych), która działa na Boolean, Byte, Short, Char, Int, i Long. stackoverflow.com/a/54950845/501113
chaotic3quilibrium
String # Format () mógłby to obsłużyć, gdybyś powiedział mu, aby używał szerokości 8. Podobnie System.out.printf ().
NomadMaker

Odpowiedzi:

171

Zastosowanie 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 .

João Silva
źródło
Wypróbowałem tę metodę. W moim przypadku odczytałem bajt z pliku binarnego i zapisałem w tablicy bajtów B. Używam System.out.println(Integer.toBinaryString(B[i])). Kiedy używam tej metody, problem polega na tym, że (a) gdy bity zaczynają się od (skrajnie lewy) 1, dane wyjściowe są nieprawidłowe, ponieważ są konwertowane B[i]na ujemną wartość int. (b) jeśli bity zaczynają się od 0, wyjście ignoruje 0, na przykład, załóżmy, że B[0]ma 00000001, wyjście jest 1zamiast00000001
Sean
1
@Sean: a) dzieje się, ponieważ a bytew Javie jest 8-bitową liczbą całkowitą uzupełnienia do dwóch ze znakiem . Jego minimalna wartość to -128 (2 ^ 8), a maksymalna to 127; b) Możesz to łatwo naprawić, używając tego String.format("%8s", Integer.toBinaryString(b)).replace(' ', '0')do wypełnienia otrzymanego ciągu zerami w lewo.
João Silva,
1
@ João: dziękuję za twoją radę. Czy masz pomysł, jak zaadresować (a), jak przechowywać oryginalny format bitu (zaczyna się od 1) w ciągu?
Sean,
1
@Sean: Tak, po prostu &to z 0xFF.
João Silva,
14
@Sean: w & 0xFFzasadzie konwertuje a signed bytena unsigned integer. Na przykład, -129jak powiedziałeś, jest reprezentowany przez 11111111111111111111111110000001. W tym przypadku w zasadzie potrzebujesz pierwszych (najmniej znaczących) 8 bitów, więc ORAZ ( &) to za pomocą 0xFF( 00000000000000000000000011111111), skutecznie czyszcząc jedynki po lewej stronie, na których nam nie zależy, pomijając tylko 10000001.
João Silva,
37

Użyłem tego. Podobny pomysł do innych odpowiedzi, ale nigdzie nie widziałem dokładnego podejścia :)

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

0xFFwynosi 255 lub 11111111(maksymalna wartość dla bajtu bez znaku). 0x100to 256 lub100000000

&Upcasts bajtu do całkowitej. W tym momencie może to być wszystko od 0- 255( 00000000do 11111111, wykluczyłem początkowe 24 bity). + 0x100i .substring(1)upewnij się, że na początku będą zera.

Zmierzyłem czas w porównaniu z odpowiedzią João Silvy , a to ponad 10 razy szybciej. http://ideone.com/22DDK1 Nie zamieściłem odpowiedzi Pshemo, ponieważ nie jest ona poprawnie wypełniona.

Raekye
źródło
Hej! mam pytanie na ten temat. Mam ciąg reprezentujący plik PDF w formacie Base64, muszę przekonwertować go na binarny. Zasadniczo Base64-> byte-> binary. Czy ten kod zadziała?
Sid
Co dokładnie robi + 0x100? Dodajesz 256 do wynikowej liczby całkowitej, ale dlaczego?
Conner Dassen
1
@ConnerDassen Zapewnia, że ​​ciąg binarny jest wypełniony 0. Na przykład, jeśli btak 1, bez + 0x100ciebie po prostu otrzymasz "1"jako swój ciąg. Dodając 1, otrzymujesz 100000001, a jeśli weźmiesz podciąg, ignorując pierwszy znak, otrzymasz właściwy "00000001". Jeśli nie chcesz, aby Twój sznurek był wyściełany, możesz po prostu użyć Integer.toBinaryString(b & 0xff). Te & 0xffpoprawki negatywne / two za kwestie dopełniacza
Raekye
8

Czy tego szukasz?

konwertowanie z String na bajt

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

konwertowanie z bajtu na ciąg

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

Lub, jak powiedział João Silva w swoim komentarzu, aby dodać początek 0, możemy sformatować ciąg do długości 8 i zamienić wynikowe spacje wiodące na zero, więc w przypadku łańcucha takiego jak " 1010"otrzymamy"00001010"

System.out.println(String.format("%8s", Integer.toBinaryString((b + 256) % 256))
                         .replace(' ', '0'));
Pshemo
źródło
6

Możesz sprawdzić każdy bit w bajcie, a następnie dołączyć 0 lub 1 do ciągu. Oto mała pomocnicza metoda, którą napisałem do testowania:

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();
}
Martyn
źródło
3

Pobierz każdy bit bajtu i przekonwertuj go na łańcuch. Powiedzmy, że bajt ma 8 bitów i możemy je uzyskać jeden po drugim za pomocą ruchu bitowego. Na przykład, przesuwamy drugi bit z bajtu 6 bitów w prawo, drugi bit na końcu z 8 bitów, a następnie (&) za pomocą 0x0001, aby wyczyścić bity przednie.

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();
}
jamee
źródło
Czy mógłbyś zmienić swoją odpowiedź, aby wyjaśnić, dlaczego ten kod odpowiada na pytanie? Odpowiedzi zawierające tylko kod są odradzane , ponieważ nie uczą rozwiązania.
DavidPostill
2

Ten kod pokaże, jak java int można podzielić na 4 kolejne bajty. Następnie możemy sprawdzić każdy bajt za pomocą metod Java w porównaniu z zapytaniem bajt / bit niskiego poziomu.

To jest oczekiwany wynik po uruchomieniu poniższego kodu:

[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

Oto kod do uruchomienia:

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() );
    }

}
Naresh Maharaj
źródło
2
Integer.toBinaryString((byteValue & 0xFF) + 256).substring(1)
Timofey Gorshkov
źródło
2

Przepraszam, wiem, że to trochę za późno ... Ale mam o wiele łatwiejszy sposób ... Do łańcucha binarnego:

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

metoda 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;
}
Jp Silver
źródło
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();
}
Shahidul
źródło
1

Możesz pracować z BigInteger, jak na poniższym przykładzie, szczególnie jeśli masz 256 bitów lub więcej:

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));

Inny przykład, który akceptuje bajty:

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

Wynik:

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

binary: 101010001101000011001010010000001100111011010010111001001101100001000000110111101101110001000000111010001101000011001010010000001110010011001010110010000100000011001000111001001100101011100110111001100101110
hex: 546865206769726c206f6e20746865207265642064726573732e

Możesz także pracować nad konwersją formatu binarnego do formatu bajtowego

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

Uwaga: do formatowania ciągów znaków w formacie binarnym można użyć poniższego przykładu

String.format("%256s", biStr.toString(2).replace(' ', '0'));  // this is for the 256 bit formatting
Josef Panerio
źródło
1

Prosta odpowiedź może brzmieć:

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
Daniel De León
źródło
0

Wszyscy wiemy, że Java nie zapewnia niczego podobnego do słowa kluczowego unsigned. Ponadto byteprymityw zgodnie ze specyfikacją Javy reprezentuje wartość między −128a 127. Na przykład, jeśli a bytejest castdla intjęzyka Java, zinterpretuje pierwsze bitjako rozszerzenie signi użyje rozszerzenia znaku.

Jak więc przekonwertować bajt większy niż 127na jego reprezentację w postaci łańcucha binarnego?

Nic nie stoi na przeszkodzie, aby bytetraktować po prostu jako 8-bitów i interpretować te bity jako wartość między 0a 255. Pamiętaj też, że nie możesz nic zrobić, aby narzucić swoją interpretację metodom innej osoby. Jeśli metoda akceptuje a byte, wówczas ta metoda przyjmuje wartość między −128a127 chyba że wyraźnie określono inaczej.

Dlatego najlepszym sposobem rozwiązania tego problemu jest przekonwertowanie bytewartości na intwartość przez wywołanie Byte.toUnsignedInt()metody lub rzutowanie jej jako intprymitywu (int) signedByte & 0xFF. Tutaj masz przykład:

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);
    }
}

Wynik

8-bit header:
10000000
11100010
01100000
11101010
Teocci
źródło
0

Kolejna wskazówka dla tych, którzy muszą masowo konwertować bajty na ciągi binarne: używaj tabeli przeglądowej zamiast używać tych operacji na ciągach znaków przez cały czas. Jest to o wiele szybsze niż ciągłe wywoływanie funkcji konwersji

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
  }


}
rloeffel
źródło
-1

Zgaduję, ale jeśli masz Byte, czy nie możesz po prostu wywołać metody toString () na obiekcie, aby uzyskać wartość? Albo spoglądając na interfejs API , używając byteValue ()?

geogaddi
źródło