Piszę aplikację internetową w Google App Engine. Pozwala ludziom zasadniczo edytować kod HTML, który jest przechowywany jako .html
plik w blobstore.
Używam fetchData, aby zwrócić byte[]
wszystkie znaki w pliku. Próbuję drukować do html, aby użytkownik mógł edytować kod HTML. Wszystko działa świetnie!
Oto mój jedyny teraz problem:
Tablica bajtów ma pewne problemy podczas konwersji z powrotem na ciąg. Sprytne cytaty i kilka postaci wyglądają fajnie. (? lub japońskie symbole itp.) W szczególności widzę, że kilka bajtów ma wartości ujemne, które powodują problem.
Cudzysłowy powracają jako -108
iw -109
tablicy bajtów. Dlaczego tak się dzieje i jak mogę zdekodować ujemne bajty, aby pokazać prawidłowe kodowanie znaków?
InputStream
a następnie dobyte[]
. Teraz, gdy próbuję zamienićbyte[]
tekst na String (muszę użyć treści odpowiedzi do ataków), otrzymuję naprawdę zabawne postacie pełne sprytnych cudzysłowów i znaków zapytania, a co nie. Wierzę ciebie problemem jest taki sam jak mój, jak oboje mają do czynienia zhtml
wbyte[]
. Czy możesz prosić o poradę?String str=new String(buffer, "Cp1252");
ale bez pomocy.Odpowiedzi:
Tablica bajtów zawiera znaki w specjalnym kodowaniu (które powinieneś wiedzieć). Sposób na przekonwertowanie go na String to:
String decoded = new String(bytes, "UTF-8"); // example for one encoding type
Nawiasem mówiąc - surowe bajty mogą pojawiać się jako ujemne liczby dziesiętne tylko dlatego, że typ danych java
byte
jest podpisany, obejmuje zakres od -128 do 127.-109 = 0x93: Control Code "Set Transmit State"
Wartość (-109) to niedrukowalny znak kontrolny w UNICODE. Więc UTF-8 nie jest poprawnym kodowaniem dla tego strumienia znaków.
0x93
w „Windows-1252” to „inteligentny cytat”, którego szukasz, więc nazwa Java tego kodowania to „Cp1252”. Następna linia zawiera kod testowy:System.out.println(new String(new byte[]{-109}, "Cp1252"));
źródło
byte
typ danych Javy jest podpisany. Wartości „ujemne” to po prostu bajty z najbardziej znaczącym zestawem bajtów. Wyjaśnia również, jaki jest najbardziej prawdopodobny zestaw znaków, którego powinieneś używać - Windows-1252. Powinieneś jednak wiedzieć, jakiego zestawu znaków użyć z kontekstu lub konwencji, bez zgadywania.Java 7 i nowsze
Możesz również przekazać żądane kodowanie do
String
konstruktora jakoCharset
stałą z StandardCharsets . Może to być bezpieczniejsze niż przekazywanie kodowania jako aString
, jak sugerowano w innych odpowiedziach.Na przykład do kodowania UTF-8
String bytesAsString = new String(bytes, StandardCharsets.UTF_8);
źródło
Możesz tego spróbować.
String s = new String(bytearray);
źródło
public class Main { /** * Example method for converting a byte to a String. */ public void convertByteToString() { byte b = 65; //Using the static toString method of the Byte class System.out.println(Byte.toString(b)); //Using simple concatenation with an empty String System.out.println(b + ""); //Creating a byte array and passing it to the String constructor System.out.println(new String(new byte[] {b})); } /** * @param args the command line arguments */ public static void main(String[] args) { new Main().convertByteToString(); } }
Wynik
65 65 A
źródło
public static String readFile(String fn) throws IOException { File f = new File(fn); byte[] buffer = new byte[(int)f.length()]; FileInputStream is = new FileInputStream(fn); is.read(buffer); is.close(); return new String(buffer, "UTF-8"); // use desired encoding }
źródło
read
zgłosi wyjątek.sugeruję
Arrays.toString(byte_array);
To zależy od twojego celu. Na przykład chciałem zapisać tablicę bajtów dokładnie w formacie, który można zobaczyć w czasie debugowania, który jest
[1, 2, 3]
mniej więcej taki : Jeśli chcesz zapisać dokładnie tę samą wartość bez konwersji bajtów na format znakowy,Arrays.toString (byte_array)
zrób to. Ale jeśli chcesz zapisać znaki zamiast bajtów, powinieneś użyćString s = new String(byte_array)
. W tym przypadkus
jest to odpowiednik[1, 2, 3]
w formacie znaku.źródło
Poprzednia odpowiedź od Andreas_D jest dobra. Dodam tylko, że wszędzie tam, gdzie wyświetlasz dane wyjściowe, będzie czcionka i kodowanie znaków i może nie obsługiwać niektórych znaków.
Aby sprawdzić, czy problem stanowi Java, czy wyświetlacz, wykonaj następujące czynności:
for(int i=0;i<str.length();i++) { char ch = str.charAt(i); System.out.println(i+" : "+ch+" "+Integer.toHexString(ch)+((ch=='\ufffd') ? " Unknown character" : "")); }
Java odwzoruje wszystkie znaki, których nie może zrozumieć, na 0xfffd oficjalny znak nieznanych znaków. Jeśli widzisz znak „?” w danych wyjściowych, ale nie jest odwzorowany na 0xfffd, problem stanowi czcionka ekranu lub kodowanie, a nie Java.
źródło