Java Byte Array na String to Byte Array

180

Próbuję zrozumieć bajt [] na ciąg znaków, ciąg znaków reprezentujący konwersję bajtu [] na bajt [] ... Przekształcam mój bajt [] na ciąg znaków do wysłania, a następnie oczekuję mojej usługi sieci web (napisanej w python) aby wysłać dane bezpośrednio do klienta.

Kiedy wysyłam dane z mojej aplikacji Java ...

Arrays.toString(data.toByteArray())

Bajty do wysłania ..

[B@405217f8

Send (jest to wynik Arrays.toString (), który powinien być ciągiem reprezentującym moje dane bajtowe, dane te zostaną przesłane przewodem):

[-47, 1, 16, 84, 2, 101, 110, 83, 111, 109, 101, 32, 78, 70, 67, 32, 68, 97, 116, 97]

Po stronie python serwer python zwraca ciąg wywołujący (który widzę jest taki sam jak ciąg wysłany na serwer

[-47, 1, 16, 84, 2, 101, 110, 83, 111, 109, 101, 32, 78, 70, 67, 32, 68, 97, 116, 97]

Serwer powinien zwrócić te dane do klienta, gdzie można je zweryfikować.

Odpowiedź, którą otrzymuje mój klient (jako ciąg), wygląda

[-47, 1, 16, 84, 2, 101, 110, 83, 111, 109, 101, 32, 78, 70, 67, 32, 68, 97, 116, 97]

Nie mogę wymyślić, jak przywrócić otrzymany ciąg znaków do bajtu []

Niezależnie od tego, co próbuję, w końcu otrzymuję tablicę bajtów, która wygląda następująco ...

[91, 45, 52, 55, 44, 32, 49, 44, 32, 49, 54, 44, 32, 56, 52, 44, 32, 50, 44, 32, 49, 48, 49, 44, 32, 49, 49, 48, 44, 32, 56, 51, 44, 32, 49, 49, 49, 44, 32, 49, 48, 57, 44, 32, 49, 48, 49, 44, 32, 51, 50, 44, 32, 55, 56, 44, 32, 55, 48, 44, 32, 54, 55, 44, 32, 51, 50, 44, 32, 54, 56, 44, 32, 57, 55, 44, 32, 49, 49, 54, 44, 32, 57, 55, 93]

lub mogę uzyskać reprezentację bajtów, która jest następująca:

B@2a80d889

Oba są inne niż moje przesłane dane ... Jestem pewien, że brakuje mi czegoś naprawdę prostego ....

Jakaś pomoc?!

0909EM
źródło

Odpowiedzi:

272

Nie możesz po prostu pobrać zwróconego ciągu i zbudować z niego ciąg ... to już nie jest byte[]typ danych, to już ciąg; musisz to przeanalizować. Na przykład :

String response = "[-47, 1, 16, 84, 2, 101, 110, 83, 111, 109, 101, 32, 78, 70, 67, 32, 68, 97, 116, 97]";      // response from the Python script

String[] byteValues = response.substring(1, response.length() - 1).split(",");
byte[] bytes = new byte[byteValues.length];

for (int i=0, len=bytes.length; i<len; i++) {
   bytes[i] = Byte.parseByte(byteValues[i].trim());     
}

String str = new String(bytes);

** EDYCJA **

W swoim pytaniu pojawia się wskazówka dotycząca Twojego problemu, gdy mówisz „ Whatever I seem to try I end up getting a byte array which looks as follows... [91, 45, ...”, ponieważ 91jest to wartość bajtu dla [, podobnie [91, 45, ...jak tablica bajtów ciągu „ [-45, 1, 16, ...”.

Metoda Arrays.toString()zwróci Stringreprezentację określonej tablicy; co oznacza, że ​​zwrócona wartość nie będzie już tablicą. Na przykład :

byte[] b1 = new byte[] {97, 98, 99};

String s1 = Arrays.toString(b1);
String s2 = new String(b1);

System.out.println(s1);        // -> "[97, 98, 99]"
System.out.println(s2);        // -> "abc";

Jak widać, s1zawiera ciąg znaków reprezentujący tablicę b1 , podczas gdy s2zawiera ciąg znaków bajtów zawartych wb1 .

Teraz, w twoim problemie, serwer zwraca ciąg podobny do s1, dlatego aby odzyskać reprezentację tablicy, potrzebujesz odwrotnej metody konstruktora. Jeśli s2.getBytes()jest odwrotnie new String(b1), musisz znaleźć przeciwieństwo Arrays.toString(b1), więc kod wkleiłem w pierwszym fragmencie tej odpowiedzi.

Yanick Rochon
źródło
Niesamowite! Wydaje mi się, że całkowicie zrozumiałeś, o co mi chodzi ... Nie pochodzę z języka Java, więc nie mogłem naprawdę ustalić, jakiej konwersji potrzebowałem. Tylko dla informacji wysyłam s1 na serwer, a serwer odpowiada s1 (mogę sprawdzić, czy serwer odebrał i odpowiedział danymi w s1), więc potrzebowałem przeciwieństwa Arrays.toString () jako zasugerowałeś ... I twoje rozwiązanie jest naprawdę dobre! Twoje zdrowie!
0909EM,
Dziękuję Yanick. Ale zapętla się 2046 razy dla każdego obrazu, ponieważ wartość bajtów. Długość wynosi 2046. Czy istnieje inna metoda, aby to zrobić?
Gugan
Jeśli dane, które otrzymujesz, są w rzeczywistości ciągiem czytelnym dla człowieka, który musi zostać przeanalizowany jak wartość zmiennej responsew mojej odpowiedzi, to niestety nie, nie ma innego wyjścia. Najlepszym sposobem byłoby otrzymanie bajtów jako nieprzetworzonych danych (jako plik binarny) zamiast ciągu, a może nawet jako ciąg Base64, co wymagałoby jedynie konwersji go z powrotem jako wartość podstawową 256 (binarną).
Yanick Rochon
3
Aby dodać do tego, co poza tym jest poprawną (choć niekompletną) odpowiedź: 1) Każda tablica bajtów [] konwertowana na String w Javie powinna określać zestaw znaków. Czy tablica bajtów [] UTF-8 czy coś innego? Brak szczegółowości lub wiedza o tym, co to może powodować błędy. 2) Java wykorzystuje kodowanie Big-Endian, ale na przykład systemy M $ używają Little-Endian. W przypadku tablic bajtów [] zawierających ciągi (oparte na znakach) nie stanowi to problemu. Jeśli jednak tablica bajtów [] reprezentuje liczbę, „endianess” systemów źródłowych / docelowych ma znaczenie.
Darrell Teague,
130
String coolString = "cool string";

byte[] byteArray = coolString.getBytes();

String reconstitutedString = new String(byteArray);

System.out.println(reconstitutedString);

To wysyła „fajny ciąg” do konsoli.

To jest cholernie łatwe.

CorayThan
źródło
6
Tyle głosów negatywnych, ale tak mało wyjaśnień ... Czy to, co powiedziałem, nie działa? Działało, kiedy go używałem, a pytanie brzmi: jak przekonwertować bajty na ciągi znaków iz powrotem, prawda?
CorayThan
2
Odpowiedź, która to rozwiązała, jest faktycznie oznaczona jako odpowiedź. Z pamięci nie jest tak proste, jak sugerowałeś ... Zobacz odpowiedź Yanicka, myślę, że źle zrozumiałeś, o co prosiłem, ale dzięki za wkład.
0909EM,
9
@CorayThan Właściwie nie, to wcale nie dotyczy pytania OP. Jeśli faktycznie to czytasz, zobaczysz, że byte[]on otrzymuje jest reprezentowany jako String; tzn . "[97, 98, 99]"nie [97, 98, 99]. Oznacza to, że twoja odpowiedź nawet nie dotyczy tej sytuacji.
b1nary.atr0phy
2
Twoja odpowiedź jest Stringdo byte[]celu String. Myślę, że pytanie jest wymóg byte[], aby Stringdo byte[].
Wundwin Urodzony
13
Może nawet być złą odpowiedzią na zadane pytanie, ale pomogło mi to rozwiązać problem. Dlatego ludzie powinni pomyśleć trochę dłużej, zanim obniżysz czyjąś odpowiedź. Dziękuję CorayThan!
Roberto Santos
21

Co ja zrobiłem:

powrót do klientów:

byte[] result = ****encrypted data****;

String str = Base64.encodeBase64String(result);

return str;

otrzymywać od klientów:

 byte[] bytes = Base64.decodeBase64(str);

Twoje dane zostaną przesłane w tym formacie:

OpfyN9paAouZ2Pw+gDgGsDWzjIphmaZbUyFx5oRIN1kkQ1tDbgoi84dRfklf1OZVdpAV7TonlTDHBOr93EXIEBoY1vuQnKXaG+CJyIfrCWbEENJ0gOVBr9W3OlFcGsZW5Cf9uirSmx/JLLxTrejZzbgq3lpToYc3vkyPy5Y/oFWYljy/3OcC/S458uZFOc/FfDqWGtT9pTUdxLDOwQ6EMe0oJBlMXm8J2tGnRja4F/aVHfQddha2nUMi6zlvAm8i9KnsWmQG//ok25EHDbrFBP2Ia/6Bx/SGS4skk/0couKwcPVXtTq8qpNh/aYK1mclg7TBKHfF+DHppwd30VULpA== 
Saorikido
źródło
7

Co Arrays.toString() robi jest stworzyć reprezentację ciąg każdego bajta w ByteArray.

Sprawdź dokumentację API Arrays API

Aby przekonwertować ciąg odpowiedzi z powrotem na oryginalną tablicę bajtów, musisz użyć split(",")lub coś i przekształcić go w kolekcję, a następnie przekonwertować każdy pojedynczy element na bajt, aby odtworzyć tablicę bajtów.

Kal
źródło
5

Łatwo przekonwertować tablicę bajtów na łańcuch i łańcuch znaków z powrotem na tablicę bajtów w Javie. musimy wiedzieć, kiedy używać „nowego” we właściwy sposób. Można to zrobić w następujący sposób:

konwersja tablicy bajtów na ciąg znaków:

byte[] bytes = initializeByteArray();
String str = new String(bytes);

Konwersja ciągów na bajty:

String str = "Hello"
byte[] bytes = str.getBytes();

Aby uzyskać więcej informacji, zobacz: http://evverythingatonce.blogspot.in/2014/01/tech-talkbyte-array-and-string.html

użytkownik3469161
źródło
2
Nie, nie przeczytałeś pytania lub być może nie zrozumiałeś problemu. Jak zauważysz, na pytanie udzielono odpowiedzi lata temu ...
0909EM,
3

Rodzaj danych wyjściowych z tablicy bajtów ( [B@405217f8) jest również wynikiem tablicy bajtów o zerowej długości (tj new byte[0].). Wygląda na to, że ten ciąg jest odniesieniem do tablicy, a nie opisem zawartości tablicy, tak jak możemy oczekiwać od zwykłej kolekcjitoString() metodzie .

Podobnie jak w przypadku innych respondentów, wskazałbym na Stringkonstruktory, które akceptują byte[]parametr służący do skonstruowania ciągu z zawartości tablicy bajtów. Powinieneś być w stanie odczytać surowe bajty z gniazd, InputStreamjeśli chcesz uzyskać bajty z połączenia TCP.

Jeśli te bajty zostały już odczytane jako String(za pomocą an InputStreamReader), wówczas ciąg można przekonwertować na bajty za pomocą getBytes()funkcji. Przekaż żądany zestaw znaków zarówno konstruktorowi String, jak i getBytes()funkcjom, a to zadziała tylko wtedy, gdy dane bajtów mogą zostać przekonwertowane na znaki przez InputStreamReader.

Jeśli chcesz poradzić sobie z surowymi bajtami, naprawdę powinieneś unikać korzystania z tej warstwy czytnika strumienia.

fuzzyBSc
źródło
2

Czy nie możesz po prostu wysłać bajtów jako bajtów lub przekonwertować każdy bajt na znak i wysłać jako ciąg? Robiąc to tak, jak jesteś, zajmie co najmniej 85 znaków w ciągu, gdy masz tylko 11 bajtów do wysłania. Możesz utworzyć ciąg znaków bajtów, więc będzie to „[B @ 405217f8”, które można łatwo przekonwertować na obiekt byteslub bytearrayw Pythonie. W przeciwnym razie możesz przedstawić je jako ciąg cyfr szesnastkowych („5b42403430353231376638”), zajmujących 22 znaki, które można łatwo rozszyfrować po stronie Pythona binascii.unhexlify().

UKŁUCIE
źródło
1
[B@405217f8jest identyfikatorem obiektu Java tablicy, a nie zawartością tablicy. Identyfikatora obiektu z pewnością nie można „łatwo przekonwertować na bajt lub obiekt bajtowy w pythonie”. Najlepsze, co możesz zrobić, jeśli chodzi o rozmiar, to konwersja bajtu [] na ciąg base64.
Boris B.,
Masz rację, naiwnie zakładałem, że 0909EM wiedział wystarczająco dużo, aby odróżnić (wpisany na maszynie) adres obiektu od jego zawartości.
JAB,
2

[JDK8]

import java.util.Base64;

Do ciągu:

String str = Base64.getEncoder().encode(new byte[]{ -47, 1, 16, ... });

Aby bajtować tablicę:

byte[] bytes = Base64.getDecoder().decode("JVBERi0xLjQKMyAwIG9iago8P...");
Patricio Córdova
źródło
1

Jeśli chcesz przekonwertować ciąg znaków z powrotem na tablicę bajtów, musisz użyć String.getBytes()(lub równoważnej funkcji Pythona), co pozwoli wydrukować oryginalną tablicę bajtów.

Jaskółka oknówka
źródło
0

Użyj poniższego kodu API do konwersji kodu bajtowego jako ciągu na tablicę bajtów.

 byte[] byteArray = DatatypeConverter.parseBase64Binary("JVBERi0xLjQKMyAwIG9iago8P...");
Ajay Kumar
źródło
-1

[JAVA 8]

import java.util.Base64;

String dummy= "dummy string";
byte[] byteArray = dummy.getBytes();

byte[] salt = new byte[]{ -47, 1, 16, ... }
String encoded = Base64.getEncoder().encodeToString(salt);
3logy
źródło