2013-06-28 12 views
6

G-Clef (U + 1D11E) nie jest częścią Basic Multilingual Plane (BMP), co oznacza, że ​​wymaga więcej niż 16 bitów. Prawie wszystkie funkcje odczytu języka Java zwracają tylko wartość char lub int zawierającą również only 16 bit. Która funkcja odczytuje pełne symbole Unicode, w tym SMP, SIP, TIP, SSP i PUA?Jak odczytać kod Unicode G-Clef (U + 1D11E) z pliku?

Aktualizacja

mam pytanie jak czytać pojedynczy symbol Unicode (lub punkt kodu) ze strumienia wejściowego. Nie mam żadnej tablicy całkowitej ani nie chcę czytać linii.

Możliwe jest zbudowanie punktu kodowego z Character.toCodePoint(), ale ta funkcja wymaga char. Z drugiej strony czytanie char nie jest możliwe, ponieważ read() zwraca int. Moja najlepsza dotychczasowa praca jest taka, ale nadal zawiera niebezpieczne rzuty:

public int read_code_point (Reader input) throws java.io.IOException 
{ 
    int ch16 = input.read(); 
    if (Character.isHighSurrogate((char)ch16)) 
    return Character.toCodePoint((char)ch16, (char)input.read()); 
    else 
    return (int)ch16; 
} 

Jak to zrobić lepiej?

Aktualizacja 2

Inna wersja powrocie String ale wciąż przy odlewane:

public String readchar (Reader input) throws java.io.IOException 
{ 
    int i16 = input.read(); // UTF-16 as int 
    if (i16 == -1) return null; 
    char c16 = (char)i16; // UTF-16 
    if (Character.isHighSurrogate(c16)) { 
    int low_i16 = input.read(); // low surrogate UTF-16 as int 
    if (low_i16 == -1) 
     throw new java.io.IOException ("Can not read low surrogate"); 
    char low_c16 = (char)low_i16; 
    int codepoint = Character.toCodePoint(c16, low_c16); 
    return new String (Character.toChars(codepoint)); 
    } 
    else 
    return Character.toString(c16); 
} 

Pozostała kwestia: czy opatrunki bezpieczny i jak ich uniknąć?

+0

Nie ma potrzeby, aby dodać główną tag w tytule. –

+3

możliwy duplikat [czytania w języku Java w strumieniach znaków z dodatkowymi znakami Unicode] (http://stackoverflow.com/questions/7721293/java-reading-in-character-streams-w-suplement- tuned-characters) –

+1

Możliwy duplikat nie zawiera odpowiedzi. – ceving

Odpowiedz

0

Moja najlepsza dotychczasowa praca to to, ale nadal zawiera niebezpieczne rzuty

Jedyną niebezpieczną rzeczą w przedstawionym kodzie jest to, że ch16 może mieć wartość -1, jeśli input osiągnął EOF. Jeśli najpierw sprawdzisz ten warunek, możesz zagwarantować, że pozostałe odlewy (char) są bezpieczne, ponieważ zwracają wartość -1 lub wartość w zakresie od char (0 - 0xFFFF).

public int read_code_point (Reader input) throws java.io.IOException 
{ 
    int ch16 = input.read(); 
    if (ch16 < 0 || !Character.isHighSurrogate((char)ch16)) 
    return ch16; 
    else { 
    int loSurr = input.read(); 
    if(loSurr < 0 || !Character.isLowSurrogate((char)loSurr)) 
     return ch16; // or possibly throw an exception 
    else 
     return Character.toCodePoint((char)ch16, (char)loSurr); 
    } 
} 

To nadal nie jest idealna, naprawdę trzeba obsłużyć przypadek krawędzi, gdzie pierwszy char odczytu jest wysoka surogat ale drugi nie jest dopasowanie niskie zastępczym, w tym przypadku prawdopodobnie chcesz zwróć pierwszą char taką, jaka jest i wykonaj kopię zapasową czytnika, aby następny odczyt dawał kolejną postać. Ale działa to tylko wtedy, gdy input.markSupported() == true. Jeśli może gwarancji, że to jak o

public int read_code_point (Reader input) throws java.io.IOException 
{ 
    int firstChar = input.read(); 
    if (firstChar < 0 || !Character.isHighSurrogate((char)firstChar)) { 
    return firstChar; 
    } else { 
    input.mark(1); 
    int secondChar = input.read(); 
    if(secondChar < 0) { 
     // reached EOF 
     return firstChar; 
    } else if(!Character.isLowSurrogate((char)secondChar)) { 
     // unpaired surrogates, un-read the second char 
     input.reset(); 
     return firstChar; 
    } 
    else { 
     return Character.toCodePoint((char)firstChar, (char)secondChar); 
    } 
    } 
} 

Lub można zawinąć oryginalnego czytnika w PushbackReader i używać unread(secondChar)

+0

co przekształca to w punkt kodowy? jeśli chcesz zrobić cokolwiek pożytecznego, najprawdopodobniej chcesz dane w String. – jtahlborn

+0

@jtahlborn Każdy analizator składni potrzebuje następnego znaku, a nie następnego ciągu. Czy powiedziałbyś, że parsery nie są przydatne? – ceving

-1

Pełny kod Unicode może być reprezentowany zarówno w UTF-8, jak i UTF-16, według sekwencji bajtów lub. pary bajtów ("znaki java"). Od String pełny kod Unicode punkt mogą być pozyskiwane z:

int[] codePoints = { 0x1d11e }; 
String s = new String(codePoints, 0, codePoints.length); 

for (int i = 0; i < s.length();) { 
    int cp = s.codePointAt(i); 
    i += Character.charCount(cp); 
} 

Dla pliku z postaciami zasadzie Łacińskiej, UTF-8 wydaje się w porządku.

Tho następujące brzmi pełny standardowy plik Unicode (UTF-8):

try (BufferedReader in = new BufferedReader(
     new InputStreamReader(new FileInputStream(file), "UTF-8"))) { 
    for (;;) { 
     String line = in.readLine(); 
     if (line == null) { 
      break; 
     } 
     ... do some thing with a Unicode line ... 
    } 
} catch (FileNotFoundException e) { 
    System.err.println("No file: " + file.getPath()); 
} catch (IOException e) { 
    ... 
} 

funkcję, która dostarcza Java String jednego (lub więcej kodów Unicode):

String s = unicodeToString(0x1d11e); 
String s = unicodeToString(0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x1d11e); 

public static String unicodeToString(int... codepoints) { 
    return new String(codePoints, 0, codePoints.length); 
} 
+0

Odpowiedź nie wskazuje na funkcję strumienia wejściowego. – ceving

+0

Szczegółowe to więcej; tutaj czytam z pliku FileInputStream. Może błąd polega na tym, że Unicode samo w sobie nie jest formatem, ale standardową numeracją symboli. UTF-8, UTF-16LE, UTF-16BE, UTF-16 są faktycznymi formatami binarnymi. W efekcie Java używa Unicode w 2 formatach: chociaż 'char' jest UTF-16, w .class Stałe ciągowe są przechowywane jako UTF-8. ** UTF-8 obejmuje pełny kod Unicode. ** W powyższym kodzie tablica 'codePoints' używa numerów Unicode. –

+1

To pytanie wymagało pojedynczego symbolu, a nie pełnej linii. Użycie 'readline' powoduje konieczność nieprzeczytania reszty linii. – ceving

Powiązane problemy