2009-08-26 8 views
6

Possiedo un'applicazione Java che riceve dati tramite un socket utilizzando InputStreamReader. Si segnala "Cp1252" dal suo metodo getEncoding:Come si specifica un valore di file.encoding Java coerente con la tabella codici di Windows sottostante?

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

che non necessariamente corrisponde a ciò che i rapporti di sistema come la sua pagina di codice. Ad esempio:

 
C:\>chcp 
Active code page: 850 

L'applicazione può ricevere byte 0x81, che nella tabella codici 850 rappresenta il carattere ü. Il programma interpreta quel byte con la tabella codici 1252, che non definisce alcun carattere con quel valore, quindi ricevo invece un punto interrogativo.

sono stato in grado di risolvere questo problema per un cliente che ha usato codici 850 con l'aggiunta di un'altra opzione della riga di comando nel file batch che avvia l'applicazione:

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

Ma non tutti i miei clienti utilizzano il codice pagina 850, ovviamente. Come posso ottenere Java per utilizzare una tabella codici compatibile con il sistema Windows sottostante? La mia preferenza sarebbe qualcosa che ho potuto solo mettere nel file batch, lasciando il codice Java intatta:

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

risposta

5

Per quanto riguarda il codice di snippit, la risposta giusta è utilizzare il appropriate constructor per InputStreamReader che esegue la conversione codice corretto . In questo modo non importa quale codifica sia il default sul sistema, sai che stai ricevendo una codifica corretta che corrisponde a ciò che stai ricevendo sul socket.

Quindi è possibile specificare la codifica quando si scrivono i file, se necessario, piuttosto che fare affidamento sulla codifica del sistema, ma ovviamente quando aprono i file su quel sistema possono avere problemi, ma i moderni sistemi Windows supportano UTF- 8, quindi è possibile scrivere il file in UTF-8 se necessario (internamente Java rappresenta tutte le stringhe come unicode a 16 bit).

Penso che questa sia la soluzione "giusta" in generale che sarebbe più compatibile con la più ampia gamma di sistemi sottostanti.

+0

+1. BTW Sul mio sistema Windows 7 la tabella codici attiva è 850, ma Java riporta "Cp1252" come proprietà di sistema "file.encoding". –

+1

I client e il server devono essere configurati con la stessa codifica, qualunque cosa possa essere per un determinato cliente. Un'app non Java invia i dati carattere al server utilizzando la code page locale, il server memorizza i dati e successivamente il server li invia all'app Java. Nessuno memorizza ciò che è la tabella codici, perché fino a quando tutti hanno usato lo stesso, non importa. Il problema è che l'app Java non collabora; utilizza sempre Cp1252. (La soluzione "giusta" è quella di cambiare il protocollo per forzare tutto, ad esempio, su UTF-8, ma una modifica del protocollo interrompe tutte le installazioni esistenti.) –

+0

Sembra che G_A abbia la tua risposta. Un'altra opzione consiste nel fare in modo che l'app non java riporti all'applicazione java quale pensa sia la codifica, quindi utilizzare il costruttore appropriato, come descritto sopra. – Yishai

4

Windows ha l'ulteriore complicazione di avere due codepage attivi. Nell'esempio, 1252 e 850 sono corretti, ma dipendono dal modo in cui viene eseguito il programma. Per le applicazioni GUI, Windows utilizzerà la tabella codici ANSI, che per le lingue dell'Europa occidentale sarà in genere 1252. Tuttavia, la riga di comando segnalerà la tabella codici OEM che è 850 per le stesse impostazioni locali.

+0

Hai fatto affermazioni vere, ma non sono sicuro di come rispondono alla mia domanda. Evidentemente, la tabella codici OEM è quella con cui il programma Java deve essere compatibile. Quindi, come faccio a scegliere un valore 'file.encoding' basato su quello? Il modo in cui viene eseguito il programma è tramite 'java.exe'. –

4

Se il valore di pagina di codice che ritorna da un comando chcp restituirà il valore che è necessario, è possibile utilizzare il seguente comando per ottenere la tabella codici

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

Questo imposta la variabile CodePage al codice valore pagina restituita dal chcp

C:\>echo %CodePage% 
437 

si potrebbe utilizzare questo valore nel file bat dal prefisso con Cp

C:\>echo Cp%CodePage% 
Cp437 

Se quando si mette questo in un file bat, sarà necessario l'% Valori I nel primo comando da sostituire con %% I

+0

Sembrava promettente, ma si basa su alcune ipotesi sul formato dell'output di 'chcp', che può differire sui sistemi non inglesi. In tedesco, ad esempio, la tabella codici è in token 3 e c'è un punto dopo il numero: "Aktive Codepage: 850." –

+0

Funziona così anche per un sistema tedesco: 'FOR/F" TOKENS = 2 DELIMS = :."%% I IN ('chcp') DO SET cp = %% I', quindi assegna spazi con' set cp =% cp: =% 'e infine' echo Cp% cp% ' – fubar

+0

Vedi questa soluzione qui: [Ottieni codepage di windows cmd con file batch o comando singolo] (http://stackoverflow.com/a/26675217/2773737) – fubar

6

La codifica di default usata da cmd.exe è Cp850 (o qualsiasi altra cosa CP "OEM" è nativo al sistema operativo); la codifica del sistema è Cp1252 (o qualunque sia il CP "ANSI" nativo per il sistema operativo). Gory details here. Un modo per scoprire la codifica della console è di farlo via native code (vedere GetConsoleOutputCP per la codifica della console corrente, vedere GetACP per la codifica "ANSI" predefinita; etc.).

L'alterazione della codifica tramite lo switch -D ha effetto su tutti i meccanismi di codifica predefiniti, incluso lo stdout/stdin/stderr reindirizzati. Non è una soluzione ideale.

Mi è venuto in mente questo script WSH in grado di impostare la console sulla codepage ANSI di sistema, ma non ho capito come passare a un carattere TrueType al livello di programmazione.

'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 

(questo è il mio primo script WSH, quindi potrebbe essere viziata - Non ho dimestichezza con permessi di lettura registro.)

Utilizzo di un tipo di carattere TrueType è un altro requisito per l'utilizzo di ANSI/Unicode con cmd.exe . Vado a guardare un interruttore programmatico su un font migliore quando il tempo lo consente.

Problemi correlati