2009-08-26 10 views
6

Mam aplikację Java, która odbiera dane przez gniazdo przy użyciu InputStreamReader. donosi, że „CP1252” od sposobu jej getEncoding:W jaki sposób określasz wartość Java file.encoding zgodną z podstawową stroną kodową systemu Windows?

/* java.net. */ Socket Sock = ...; 
InputStreamReader is = new InputStreamReader(Sock.getInputStream()); 
System.out.println("Character encoding = " + is.getEncoding()); 
// Prints "Character encoding = Cp1252" 

To niekoniecznie pasuje co raporty systemowe jak jego strony kodowej. Na przykład:

 
C:\>chcp 
Active code page: 850 

Aplikacja może odbierać bajt 0x81, który w CP850 symbolizuje postać ü. Program interpretuje ten bajt za pomocą strony kodowej 1252, która nie definiuje żadnego znaku o tej wartości, więc zamiast tego otrzymuję znak zapytania.

udało mi się obejść ten problem dla jednego klienta, który używany CP850 dodając innej opcji wiersza poleceń w pliku wsadowym, który uruchamia aplikację:

 
java.exe -Dfile.encoding=Cp850 ... 

Ale nie wszyscy moi klienci korzystają z kodu strona 850, oczywiście. Jak mogę przekonać Javę do używania strony kodowej zgodnej z bazowym systemem Windows? Moje preferencje byłoby coś może po prostu umieścić w pliku wsadowym, pozostawiając kodu Java nietknięty:

 
ENC=... 
java.exe -Dfile.encoding=%ENC% ... 

Odpowiedz

5

W odniesieniu do snippit kodu, właściwą odpowiedzią jest użycie appropriate constructor dla InputStreamReader, dokłada poprawną konwersję kodu . W ten sposób nie ma znaczenia, jakie jest kodowanie domyślne w systemie, wiesz, że otrzymujesz poprawne kodowanie, które odpowiada temu, co dostajesz do gniazda.

Następnie można określić kodowanie podczas wypisywania plików, jeśli trzeba, zamiast polegać na kodowaniu systemu, ale oczywiście, gdy otwierają pliki w systemie, mogą mieć problemy, ale nowoczesne systemy Windows obsługują kodowanie UTF- 8, więc możesz napisać plik w UTF-8, jeśli potrzebujesz (wewnętrznie Java reprezentuje wszystkie łańcuchy jako 16-bitowy kod Unicode).

Uważam, że jest to "właściwe" rozwiązanie, które byłoby najbardziej zgodne z największą gamą podstawowych systemów.

+0

+1. BTW W moim systemie Windows 7 aktywna strona kodowa to 850, ale Java zgłasza "Cp1252" jako właściwość systemową "file.encoding". –

+1

Klientów i serwera należy skonfigurować za pomocą tego samego kodowania, niezależnie od tego, co może być dla danego klienta. Aplikacja inna niż Java przesyła dane znakowe do serwera za pomocą lokalnej strony kodowej, serwer przechowuje dane, a następnie serwer wysyła je do aplikacji Java. Nikt nie przechowuje tego, co jest stroną kodową, ponieważ tak długo, jak wszyscy używali tego samego, nie miało to znaczenia. Problem polega na tym, że aplikacja Java nie współpracuje; zawsze używa Cp1252. ("Właściwym" rozwiązaniem jest zmiana protokołu, aby wymusić wszystko, na przykład, UTF-8, ale zmiana protokołu powoduje zerwanie wszystkich istniejących instalacji.) –

+0

To brzmi jak G_A ma twoją odpowiedź. Inną opcją jest posiadanie tego raportu aplikacji innej niż java do aplikacji java, co według niej oznacza kodowanie, a następnie użycie odpowiedniego konstruktora, jak opisano powyżej. – Yishai

4

Windows ma dodatkowe powikłanie posiadania dwóch aktywnych stron kodowych. W twoim przykładzie zarówno 1252 jak i 850 są poprawne, ale zależą one od sposobu uruchomienia programu. W przypadku aplikacji GUI system Windows będzie korzystał ze strony kodowej ANSI, która dla języków zachodnioeuropejskich będzie zwykle wynosić 1252. Jednak w wierszu polecenia zostanie zgłoszona strona kodowa OEM, która wynosi 850 dla tych samych ustawień narodowych.

+0

Złożyłeś prawdziwe oświadczenia, ale nie jestem pewien, jak odpowiedzą na moje pytanie. Najwyraźniej strona kodowa OEM jest tą, z którą program Java musi być kompatybilny. Jak więc wybrać na tej podstawie wartość 'file.encoding'? Sposób uruchamiania programu odbywa się przez 'java.exe'. –

4

Jeżeli wartość strony kodowej, która wraca z poleceniem chcp zwróci wartość, że trzeba, można użyć następującego polecenia, aby strona kodowa

C:\>for /F "Tokens=4" %I in ('chcp') Do Set CodePage=%I 

ta ustawia zmienną codePage do kodu wartość strona wrócił z chcp

C:\>echo %CodePage% 
437 

można użyć tej wartości w pliku bat poprzedzając go Cp

C:\>echo Cp%CodePage% 
Cp437 

przypadku gdy włożysz to do pliku BAT% wartości I w pierwszym poleceniu będą musiały być zastąpione %% I

+0

To wydawało się obiecujące, ale opierało się na pewnych założeniach dotyczących formatu pliku "chcp", który może się różnić w systemach innych niż angielski. Na przykład w języku niemieckim strona kodowa znajduje się w tokenie 3, a po numerze jest kropka: "Aktywna strona kodowa: 850". –

+0

Tak to działa nawet w przypadku systemu niemieckiego: "FOR/F" TOKENS = 2 DELIMS = :."%% I IN (" chcp ") ZESTAW cp = %% I', następnie przycinam spacje za pomocą' set cp =% cp: =% 'i wreszcie' echo Cp% cp% ' – fubar

+0

Zobacz to rozwiązanie tutaj: [Get windowsowa strona kodowa cmd z plikiem wsadowym lub pojedynczym poleceniem] (http://stackoverflow.com/a/26675217/2773737) – fubar

6

Domyślne kodowanie używane przez cmd.exe jest Cp850 (lub cokolwiek „OEM” CP jest rodzimy do systemu operacyjnego); kodowanie systemu to Cp1252 (lub jakakolwiek "ANSI" CP jest natywna dla systemu operacyjnego). Gory details here. Jednym ze sposobów odkrycia kodowania konsoli jest wykonanie go pod via native code (patrz GetConsoleOutputCP dla aktualnego kodowania konsoli; zobacz GetACP dla domyślnego kodowania "ANSI"; etc.).

Zmiana kodowania za pomocą przełącznika -D wpłynie na wszystkie domyślne mechanizmy kodowania, w tym przekierowane standardowe wyjście/stdin/stderr. To nie jest idealne rozwiązanie.

Wpadłem na ten skrypt WSH, który może ustawić konsolę na stronę kodową ANSI systemu, ale nie wiem, jak programowo przejść na czcionkę TrueType.

'file: setacp.vbs 
'usage: cscript /Nologo setacp.vbs 
Set objShell = CreateObject("WScript.Shell") 
'replace ACP (ANSI) with OEMCP for default console CP 
cp = objShell.RegRead("HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001" &_ 
           "\Control\Nls\CodePage\ACP") 
WScript.Echo "Switching console code page to " & cp 
objShell.Exec "chcp.com " & cp 

(To jest mój pierwszy skrypt WSH, więc to może być wadliwy - nie jestem zaznajomiony z uprawnieniami do odczytu rejestru).

Korzystanie z czcionek TrueType to kolejny wymóg korzystania z ANSI/Unicode cmd.exe . Zamierzam spojrzeć na programowy przełącznik na lepszą czcionkę, gdy pozwoli na to czas.

Powiązane problemy