2011-12-23 14 views
5

Wejście konsoli (wygrana), jak działa konwertowanie zestawu znaków?java console charset translation

Kod poniżej, wyjście spoza kodu ASCII - InputStreamReader w poniższym przykładzie nie przyjmuje zestawu znaków jako argumentu.

BufferedReader console = new BufferedReader(new InputStreamReader(System.in)); 
String inp = console.readLine(); 
System.out.println(inp.toUpperCase()); 

Będąc niezależnym od OS, w jaki sposób Java rozwiązuje wszystkie możliwe konfiguracje zestawu znaków dotyczące wprowadzania sygnału przez konsolę?

Odpowiedz

12

Właściwie Java nie obsługuje tego problemu w ogóle.

Po prostu zakłada, że ​​kodowanie konsoli jest takie samo jak domyślne kodowanie systemowe. This assumption is wrong on Windows systems, w związku z tym Java nie zapewnia dobrego rozwiązania do wykonywania poprawnego IO konsoli w odniesieniu do znaków innych niż ASCII w systemie Windows.

Możliwe rozwiązania to:

  • Zastosowanie System.console() wprowadzony w Javie 6:

    BufferedReader in = new BufferedReader(System.console().reader()); 
    BufferedWriter out = new PrintWriter(System.console().writer(), true); 
    
    out.println(in.readLine().toUpperCase()); 
    

    Zauważ, że System.console() może powrócić null podczas przebiegu programu z przekierowanego IO, na przykład, w IDE. W tym przypadku potrzebujesz pomocy zastępczej.

  • Określ kodowanie konsoli wyraźnie:

    String consoleEncoding = "..."; 
    BufferedReader in = new BufferedReader(new InputStreamReader(System.in, consoleEncoding)); 
    BufferedWriter out = new PrintWriter(new OutputStreamWriter(System.in, consoleEncoding), true); 
    
    out.println(in.readLine().toUpperCase()); 
    

    O ile mi wiadomo, nie istnieją dobre sposoby na ustalenie rzeczywistej kodowanie konsoli programowo bez natywnego kodu.

  • Określ kodowanie konsoli jako domyślnego kodowania przy użyciu file.encoding nieruchomości, tak, że założenie, że konsola IO używa domyślnego kodowania byłoby poprawne:

    java -Dfile.encoding=... ... 
    
5

1) Praktycznie rzecz biorąc: jak zrobić kodowanie znaków pracę, i jak należy radzić sobie z nimi:

Każdy strumień znaków, które są odczytywane są kodowane/dekodowane. Java zawiera specyfikacje kodowania/dekodowania jako część JDK: http://docs.oracle.com/javase/1.6/docs/guide/intl/encoding.doc.html. Przykład: UTF-8 issue in Java code.

2) Twoje szczegółowe pytanie: W jaki sposób wieloplatformowy język JAVA obsługuje wejście konsoli, które jest specyficzne dla systemu operacyjnego?

Krótka odpowiedź: Mimo że kod bajtowy Java jest neutralny dla platformy, JVM NIE jest. Oznacza to, że funkcja przesyłania strumieniowego Java "System" "in/out/err" nie jest w pełni zaimplementowana w zwykłej starej wersji java!

Po uruchomieniu java, ładowana jest klasa "System", która abstrahuje podstawowe pojęcie systemu, w którym działa JVM. W tym czasie są to strumienie wejściowe/wyjściowe/błędów (tzn. Obiekty, do których uzyskujesz dostęp po wpisaniu System.in, System.out, System.err są ustawione w RUNTIME przez ClassLoader, który jest odpowiedzialny za ... klasy loading Java.

W przypadku „system”, ClassLoading to wyrafinowana zadanie, jak sugerujesz, ponieważ konfigurowania systemu klasy (podobnie jak konfigurowania Java Runtime klasa) jest niższy poziom Problem z implementacją JVM jest specyficzny dla systemu operacyjnego:

Jeszcze raz, dla jasności: Mimo że JĘZYK JĘZYKOWY jest niezależny od platformy, JVM dla twojej platformy jest, w przeciwieństwie do języka programowania Java, Środowisko specyficzne dla OS, które tworzy zasoby, które przywołujemy w naszym kodzie dla nas w czasie wykonywania.

Dla lepszego zrozumienia: Sprawdź rzeczywisty kod źródłowy klasy System, jest bardzo czytelny i pozwoli lepiej zrozumieć, co się dzieje. W szczególności, należy spojrzeć na metody nullInputStream():

http://www.java2s.com/Open-Source/Java-Document/6.0-JDK-Core/lang/java/lang/System.java.htm

Powiązane problemy