2012-01-19 22 views
9

Próbuję pobrać dane z http://api.freebase.com/api/trans/raw/m/0h47Java kodowania UTF-8 nie jest ustawiony na URLConnection

Jak widać w tekście są śpiewa tak: /ælˈdʒɪəriə/.

Kiedy próbuję dostać źródła ze strony otrzymuję tekst z śpiewa jak ú itp

Do tej pory próbowałem z następującego kodu:

urlConnection.setRequestProperty("Accept-Charset", "UTF-8"); 
urlConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=utf-8"); 

Co robię źle?

Cały mój kod:

URL url = null; 
URLConnection urlConn = null; 
DataInputStream input = null; 
try { 
url = new URL("http://api.freebase.com/api/trans/raw/m/0h47"); 
} catch (MalformedURLException e) {e.printStackTrace();} 

try { 
    urlConn = url.openConnection(); 
} catch (IOException e) { e.printStackTrace(); } 
urlConn.setRequestProperty("Accept-Charset", "UTF-8"); 
urlConn.setRequestProperty("Content-Type", "text/plain; charset=utf-8"); 

urlConn.setDoInput(true); 
urlConn.setUseCaches(false); 

StringBuffer strBseznam = new StringBuffer(); 
if (strBseznam.length() > 0) 
    strBseznam.deleteCharAt(strBseznam.length() - 1); 

try { 
    input = new DataInputStream(urlConn.getInputStream()); 
} catch (IOException e) { e.printStackTrace(); } 
String str = ""; 
StringBuffer strB = new StringBuffer(); 
strB.setLength(0); 
try { 
    while (null != ((str = input.readLine()))) 
    { 
     strB.append(str); 
    } 
    input.close(); 
} catch (IOException e) { e.printStackTrace(); } 

Odpowiedz

11

Strona HTML jest w UTF-8 i może używać znaków arabskich i innych. Jednak te znaki powyżej Unicode 127 są nadal kodowane jako obiekty numeryczne, takie jak ú. Funkcja Accept-Encoding nie obsługuje, nie pomaga i nie ładuje się, ponieważ kodowanie UTF-8 jest całkowicie poprawne.

Musisz samodzielnie dekodować obiekty. Coś jak:

String decodeNumericEntities(String s) { 
    StringBuffer sb = new StringBuffer(); 
    Matcher m = Pattern.compile("\\&#(\\d+);").matcher(s); 
    while (m.find()) { 
     int uc = Integer.parseInt(m.group(1)); 
     m.appendReplacement(sb, ""); 
     sb.appendCodepoint(uc); 
    } 
    m.appendTail(sb); 
    return sb.toString(); 
} 

Przy okazji tych podmiotów mogłoby wynikać z przetwarzanych formularzy HTML, tak po stronie edycji tej aplikacji internetowej.


Po kodu w pytaniu:

Wymieniłem DataInputStream z (buforowany) Czytnik tekstu. InputStreams odczytuje dane binarne, bajty; Tekst czytelników, ciągi znaków. InputStreamReader ma jako parametr InputStream i kodowanie i zwraca Reader.

try { 
    BufferedReader input = new BufferedReader(
      new InputStreamReader(urlConn.getInputStream(), "UTF-8")); 
    StringBuilder strB = new StringBuilder(); 
    String str; 
    while (null != (str = input.readLine())) { 
     strB.append(str).append("\r\n"); 
    } 
    input.close(); 
} catch (IOException e) { 
    e.printStackTrace(); 
} 
+0

Wydaje się, że jedyną rzeczą, która zadziała. Dziękuję Ci. – Ales

+0

Mam ten sam problem, proszę o pomoc. m.appendTail (m); ta linia mnie błąd. –

+0

@ ersyn61: Przepraszam, poprawiono; powinno być 'm.appendTail (sb);'. –

2

Dobrze myślę, że problem jest, gdy czytasz ze strumienia. Powinieneś zadzwonić na metodę readUTF na DataInputStream zamiast wywoływać readLine lub, co bym zrobił, to stworzyć InputStreamReader i ustawić kodowanie, następnie możesz czytać od BufferedReader wiersz po wierszu (to byłoby w twojej obecnej próbie/catch):

Charset charset = Charset.forName("UTF8"); 
InputStreamReader stream = new InputStreamReader(urlConn.getInputStream(), charset); 
BufferedReader reader = new BufferedReader(stream); 
StringBuffer responseBuffer = new StringBuffer(); 

String read = ""; 
while ((read = reader.readLine()) != null) { 
    responseBuffer.append(read); 
} 
5

spróbuj dodać również agenta użytkownika do URLConnection:

urlConnection.setRequestProperty("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.155 Safari/537.36"); 

to rozwiązać mój problem dekodowania jak czar.

+1

szukałem tej odpowiedzi przez kilka dni! – oferiko