Tenho um sistema java comunicando que serve como gateway para diversos sistemas (java, mainframe, etc). Este sistema java recebe uma requisição usando, por exemplo, utf8 e a converte para a codificação do alvo
O problema é que existe um sistema de mainframe que está usando essa codificação obscura que não está disponível com o JDK que estamos usando (esse charset sendo o IBM-924 que é um "derivado" do IBM-1047 https: //en.wikibooks .org/wiki/Character_Encodings/Code_Tables/EBCDIC/EBCDIC_1047 ). sistema.
Pelo que vi esse charset parece vir apenas com o IBM JDK, que não é aquele que usamos ou queremos usar.
Existe uma maneira de incorporar este charset específico presente no IBM JDK em, por exemplo, um openjdk? Se não, existe alguma alternativa além de criar o charset manualmente? E em caso afirmativo, existe uma maneira de reutilizar a codificação IBM-1047 e substituir os 11 caracteres que não correspondem?
Tentei incorporar os charsets usando o charsets.jar presente no IBM JDK, mas dá problemas porque esse jar tem uma dependência de classes presentes apenas no rt.jar do IBM JDK, e com certeza não gostaria substitua o rt.jar, pois pode causar efeitos colaterais indesejados.
Oof, IBM_924 quase não existe em toda a internet. Olhando em volta, parece ser ISO-8859-15 direto (que é algo que os JDKs acompanham, então vá com
Charset.forName("ISO-8859-15")
, ou ..É isso , do ICU Data do Unicode Consortium .
Esse é algum arquivo de mapeamento aleatório que encontrei de algum projeto aleatório (reconhecidamente, o projeto icu-data da organização unicode; no que diz respeito às fontes, essa deve ser suficientemente confiável). Você lê assim:
Uma linha pode conter:
E isso significa:
0xA1
no fluxo de dados...|1
significa, mais ou menos: Não pode ser ida e volta; é um pseudônimo. Há um mapeamento mais canônico para o mesmo byte (0xA1
) no arquivo anterior.E, felizmente, sendo uma variante ISO-8559, é apenas '1 byte = 1 caractere', portanto, existem apenas no máximo 256 valores de bytes diferentes que você precisa mapear para um caractere.
Isso significa que é trivial escrever sua própria implementação de conjunto de caracteres!
E assim você resolveu todos os problemas: coloque o charset dentro de seu próprio projeto, e agora você não tem dependências e não precisa depender de uma JVM que vem com o IBM-924 integrado.
Não é muito difícil.
Crie um arquivo de origem chamado
Ibm924CharsetProvider.java
, estendendo-se da classe JavaCharsetProvider
. Copie/cole isso nele:Para usar como provedor
Se você quiser, por exemplo
new String(bytes, "IBM-924")
, que funcione, além de tê-lo listado na lista de todos os charsets disponíveis, esta classe precisa ser cadastrada. Para fazer isso, coloque o nome da classe totalmente qualificado (com.foo.yourapp.util.Ibm924CharsetProvider
, aquela string, por exemplo) em um arquivo de texto vazio. Você nomeia este arquivo de textojava.nio.charset.spi.CharsetProvider
. Este arquivo precisa estar no seu jar, no caminhoMETA-INF/services/java.nio.charset.spi.CharsetProvider
. Então, se esse jar estiver no seu caminho de classe, as coisas devem funcionar.Aff parece complicado
Você realmente não precisa fazer isso - isso é apenas para garantir
"IBM-924"
que uma string funcione. Você pode usá-lo como está sem registrar o provedor. Veja omain
método no trecho onde não me preocupo em registrá-lo, mas uso oCharset
objeto diretamente.Execute isso e imprima:
NB: Esta tomada simplista não lida com os aliases. Eles são relevantes apenas para codificação (se você precisar enviar texto formatado em IBM-924); eles não são úteis para decodificação (leitura de texto formatado IBM-924). E somente se você usar esses aliases em suas strings.