Console Java, UTF-8 e Windows
Pergunta
Tentamos usar Java e UTF-8 no Windows.O aplicativo grava logs no console e gostaríamos de usar UTF-8 para os logs, pois nosso aplicativo possui logs internacionalizados.
É possível configurar a JVM para gerar UTF-8, utilizando -Dfile.encoding=UTF-8
como argumentos para a JVM.Funciona bem, mas a saída em um console do Windows está distorcida.
Então, podemos definir a página de código do console para 65001 (chcp 65001
), mas neste caso, o .bat
arquivos não funcionam.Isso significa que quando tentamos iniciar nossa aplicação através de nosso script (chamado start.bat), absolutamente nada acontece.O comando simples retorna:
C:\Application> chcp 65001
Activated code page: 65001
C:\Application> start.bat
C:\Application>
Mas sem chcp 65001
, não há problema e o aplicativo pode ser iniciado.
Alguma dica sobre isso?
Solução
Tentar chcp 65001 && start.bat
Outras dicas
Java no Windows NÃO suporta saída Unicode por padrão.Eu escrevi um método de solução alternativa chamando a API nativa com a biblioteca JNA. O método chamará WriteConsoleW para saída unicode no console.
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.win32.StdCallLibrary;
/** For unicode output on windows platform
* @author Sandy_Yin
*
*/
public class Console {
private static Kernel32 INSTANCE = null;
public interface Kernel32 extends StdCallLibrary {
public Pointer GetStdHandle(int nStdHandle);
public boolean WriteConsoleW(Pointer hConsoleOutput, char[] lpBuffer,
int nNumberOfCharsToWrite,
IntByReference lpNumberOfCharsWritten, Pointer lpReserved);
}
static {
String os = System.getProperty("os.name").toLowerCase();
if (os.startsWith("win")) {
INSTANCE = (Kernel32) Native
.loadLibrary("kernel32", Kernel32.class);
}
}
public static void println(String message) {
boolean successful = false;
if (INSTANCE != null) {
Pointer handle = INSTANCE.GetStdHandle(-11);
char[] buffer = message.toCharArray();
IntByReference lpNumberOfCharsWritten = new IntByReference();
successful = INSTANCE.WriteConsoleW(handle, buffer, buffer.length,
lpNumberOfCharsWritten, null);
if(successful){
System.out.println();
}
}
if (!successful) {
System.out.println(message);
}
}
}
Tivemos alguns problemas semelhantes no Linux.Nosso código estava em ISO-8859-1 (principalmente compatível com cp-1252), mas o console era UTF-8, fazendo com que o código não fosse compilado.Simplesmente mudar o console para ISO-8859-1 faria com que o script de construção, em UTF-8, quebrasse.Encontramos algumas opções:
1- defina alguma codificação padrão e siga-a.Essa foi a nossa escolha.Optamos por manter tudo em ISO-8859-1, modificando os scripts de construção.
2- Definir a codificação antes de iniciar qualquer tarefa, mesmo dentro dos scripts de construção.Algum código como o Erickson disse.No Linux era assim:
lang=pt_BR.ISO-8859-1 /usr/local/xxxx
Meu eclipse ainda está assim.Ambos funcionam bem.
O Windows não oferece suporte à página de código 65001: http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/chcp.mspx?mfr=true
Você tentou PowerShell em vez do antigo cmd.exe.