AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / coding / Perguntas / 76936549
Accepted
fnmps
fnmps
Asked: 2023-08-20 02:30:55 +0800 CST2023-08-20 02:30:55 +0800 CST 2023-08-20 02:30:55 +0800 CST

Conjunto de caracteres não presente no JDK usado

  • 772

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

Conversão de conjunto de caracteres

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.

java
  • 1 1 respostas
  • 57 Views

1 respostas

  • Voted
  1. Best Answer
    rzwitserloot
    2023-08-20T04:16:05+08:002023-08-20T04:16:05+08:00

    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:

    <UFF5E> \xA1 |1
    

    E isso significa:

    • Se você vir o byte 0xA1no fluxo de dados...
    • Então isso representa o caractere 0xFF5E na tabela unicode.
    • Isso |1significa, 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 Java CharsetProvider. Copie/cole isso nele:

    // Written by Reinier Zwitserloot
    // Public domain - use however you like.
    
    import java.nio.ByteBuffer;
    import java.nio.CharBuffer;
    import java.nio.charset.Charset;
    import java.nio.charset.CharsetDecoder;
    import java.nio.charset.CharsetEncoder;
    import java.nio.charset.CoderResult;
    import java.nio.charset.spi.CharsetProvider;
    import java.util.Collections;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.List;
    import java.util.Map;
    
    public class Ibm924CharsetProvider extends CharsetProvider {
        private static final Charset IBM924 = new Ibm924Charset();
        private static final List<Charset> IBM924_LIST = Collections.singletonList(IBM924);
        
        public static final Charset ibm924() {
            return IBM924;
        }
        
        @Override public Iterator<Charset> charsets() {
            return IBM924_LIST.iterator();
        }
        
        @Override public Charset charsetForName(String charsetName) {
            if (charsetName.equals(IBM924.name())) return IBM924;
            if (IBM924.aliases().contains(charsetName)) return IBM924;
            
            return null;
        }
        
        public static void main(String[] args) throws Exception {
            String in = "Hello, World!";
            byte[] b = in.getBytes(ibm924());
            System.out.print(in + " ->");
            for (byte a : b) System.out.printf(" %02X", a);
            System.out.println();
            String in2 = new String(b, ibm924());
            System.out.println("... -> " + in2);
            System.out.println("Equal? " + in.equals(in2));
        }
    }
    
    class Ibm924Charset extends Charset {
        public Ibm924Charset() {
            super("IBM-924", new String[] { "IBM924", "Cp924", "Cp-924" });
        }
        
        @Override public boolean contains(Charset cs) {
            return cs.name().equals("IBM-924"); // It isn't even a subset of ASCII!
        }
        
        @Override public CharsetDecoder newDecoder() {
            return new CharsetDecoder(this, 1F, 1F) {
                @Override protected CoderResult decodeLoop(ByteBuffer from, CharBuffer to) {
                    while (from.hasRemaining()) {
                        if (!to.hasRemaining()) return CoderResult.OVERFLOW;
                        byte c = from.get();
                        char d = IBM924[c & 0xFF];
                        to.put(d);
                    }
                    
                    return CoderResult.UNDERFLOW;
                }
            };
        }
        
        @Override public CharsetEncoder newEncoder() {
            return new CharsetEncoder(this, 1F, 1F) {
                @Override protected CoderResult encodeLoop(CharBuffer from, ByteBuffer to) {
                    while (from.hasRemaining()) {
                        if (!to.hasRemaining()) return CoderResult.OVERFLOW;
                        char d = from.get();
                        Byte v = LOOKUP.get(d);
                        if (v == null) {
                            // 'un'consume the character we consumed
                            from.position(from.position() - 1);
                            return CoderResult.unmappableForLength(1);
                        }
                        to.put(v.byteValue());
                    }
                    
                    return CoderResult.UNDERFLOW;
                }
            };
        }
        
        // SOURCE: https://github.com/unicode-org/icu-data/blob/main/charset/data/ucm/ibm-924_P100-1998.ucm
        private static final char[] IBM924 = {
            '\u0000', '\u0001', '\u0002', '\u0003', '\u009C', '\u0009', '\u0086', '\u007F',
            '\u0097', '\u008D', '\u008E', '\u000B', '\u000C', '\r', '\u000E', '\u000F',
            '\u0010','\u0011','\u0012','\u0013', '\u009D','\u0085','\u0008','\u0087',
            '\u0018','\u0019','\u0092','\u008F', '\u001C','\u001D','\u001E','\u001F',
            '\u0080','\u0081','\u0082','\u0083', '\u0084','\n','\u0017','\u001B',
            '\u0088','\u0089','\u008A','\u008B', '\u008C','\u0005', '\u0006', '\u0007',
            '\u0090', '\u0091', '\u0016', '\u0093', '\u0094', '\u0095', '\u0096', '\u0004',
            '\u0098', '\u0099', '\u009A', '\u009B', '\u0014', '\u0015', '\u009E', '\u001A',
            '\u0020', '\u00A0', '\u00E2', '\u00E4', '\u00E0', '\u00E1', '\u00E3', '\u00E5',
            '\u00E7', '\u00F1', '\u00DD', '\u002E', '\u003C', '\u0028', '\u002B', '\u007C',
            '\u0026', '\u00E9', '\u00EA', '\u00EB', '\u00E8', '\u00ED', '\u00EE', '\u00EF',
            '\u00EC', '\u00DF', '\u0021', '\u0024', '\u002A', '\u0029', '\u003B', '\u005E',
            '\u002D', '\u002F', '\u00C2', '\u00C4', '\u00C0', '\u00C1', '\u00C3', '\u00C5',
            '\u00C7', '\u00D1', '\u0160', '\u002C', '\u0025', '\u005F', '\u003E', '\u003F',
            '\u00F8', '\u00C9', '\u00CA', '\u00CB', '\u00C8', '\u00CD', '\u00CE', '\u00CF',
            '\u00CC', '\u0060', '\u003A', '\u0023', '\u0040', '\'', '\u003D', '\u0022',
            '\u00D8', '\u0061', '\u0062', '\u0063', '\u0064', '\u0065', '\u0066', '\u0067',
            '\u0068', '\u0069', '\u00AB', '\u00BB', '\u00F0', '\u00FD', '\u00FE', '\u00B1',
            '\u00B0', '\u006A', '\u006B', '\u006C', '\u006D', '\u006E', '\u006F', '\u0070',
            '\u0071', '\u0072', '\u00AA', '\u00BA', '\u00E6', '\u017E', '\u00C6', '\u20AC',
            '\u00B5', '\u007E', '\u0073', '\u0074', '\u0075', '\u0076', '\u0077', '\u0078',
            '\u0079', '\u007A', '\u00A1', '\u00BF', '\u00D0', '\u005B', '\u00DE', '\u00AE',
            '\u00A2', '\u00A3', '\u00A5', '\u00B7', '\u00A9', '\u00A7', '\u00B6', '\u0152',
            '\u0153', '\u0178', '\u00AC', '\u0161', '\u00AF', '\u005D', '\u017D', '\u00D7',
            '\u007B', '\u0041', '\u0042', '\u0043', '\u0044', '\u0045', '\u0046', '\u0047',
            '\u0048', '\u0049', '\u00AD', '\u00F4', '\u00F6', '\u00F2', '\u00F3', '\u00F5',
            '\u007D', '\u004A', '\u004B', '\u004C', '\u004D', '\u004E', '\u004F', '\u0050',
            '\u0051', '\u0052', '\u00B9', '\u00FB', '\u00FC', '\u00F9', '\u00FA', '\u00FF',
            '\\', '\u00F7', '\u0053', '\u0054', '\u0055', '\u0056', '\u0057', '\u0058',
            '\u0059', '\u005A', '\u00B2', '\u00D4', '\u00D6', '\u00D2', '\u00D3', '\u00D5',
            '\u0030', '\u0031', '\u0032', '\u0033', '\u0034', '\u0035', '\u0036', '\u0037',
            '\u0038', '\u0039', '\u00B3', '\u00DB', '\u00DC', '\u00D9', '\u00DA', '\u009F',
        };
        
        private static final Map<Character, Byte> LOOKUP;
        static {
            Map<Character, Byte> map = new HashMap<>();
            for (int i = 0; i < IBM924.length; i++) map.put(IBM924[i], (byte) i);
            LOOKUP = Collections.unmodifiableMap(map);
        }
    }
    

    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 texto java.nio.charset.spi.CharsetProvider. Este arquivo precisa estar no seu jar, no caminho META-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 o mainmétodo no trecho onde não me preocupo em registrá-lo, mas uso o Charsetobjeto diretamente.

    Execute isso e imprima:

    Hello, World! -> C8 85 93 93 96 6B 40 E6 96 99 93 84 5A
    ... -> Hello, World!
    Equal? true
    

    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.

    • 4

relate perguntas

  • Lock Condition.notify está lançando java.lang.IllegalMonitorStateException

  • Resposta de microsserviço Muitos para Um não aparece no carteiro

  • Validação personalizada do SpringBoot Bean

  • Os soquetes Java são FIFO?

  • Por que não é possível / desencorajado definir um lado do servidor de tempo limite de solicitação?

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    destaque o código em HTML usando <font color="#xxx">

    • 2 respostas
  • Marko Smith

    Por que a resolução de sobrecarga prefere std::nullptr_t a uma classe ao passar {}?

    • 1 respostas
  • Marko Smith

    Você pode usar uma lista de inicialização com chaves como argumento de modelo (padrão)?

    • 2 respostas
  • Marko Smith

    Por que as compreensões de lista criam uma função internamente?

    • 1 respostas
  • Marko Smith

    Estou tentando fazer o jogo pacman usando apenas o módulo Turtle Random e Math

    • 1 respostas
  • Marko Smith

    java.lang.NoSuchMethodError: 'void org.openqa.selenium.remote.http.ClientConfig.<init>(java.net.URI, java.time.Duration, java.time.Duratio

    • 3 respostas
  • Marko Smith

    Por que 'char -> int' é promoção, mas 'char -> short' é conversão (mas não promoção)?

    • 4 respostas
  • Marko Smith

    Por que o construtor de uma variável global não é chamado em uma biblioteca?

    • 1 respostas
  • Marko Smith

    Comportamento inconsistente de std::common_reference_with em tuplas. Qual é correto?

    • 1 respostas
  • Marko Smith

    Somente operações bit a bit para std::byte em C++ 17?

    • 1 respostas
  • Martin Hope
    fbrereto Por que a resolução de sobrecarga prefere std::nullptr_t a uma classe ao passar {}? 2023-12-21 00:31:04 +0800 CST
  • Martin Hope
    比尔盖子 Você pode usar uma lista de inicialização com chaves como argumento de modelo (padrão)? 2023-12-17 10:02:06 +0800 CST
  • Martin Hope
    Amir reza Riahi Por que as compreensões de lista criam uma função internamente? 2023-11-16 20:53:19 +0800 CST
  • Martin Hope
    Michael A formato fmt %H:%M:%S sem decimais 2023-11-11 01:13:05 +0800 CST
  • Martin Hope
    God I Hate Python std::views::filter do C++20 não filtrando a visualização corretamente 2023-08-27 18:40:35 +0800 CST
  • Martin Hope
    LiDa Cute Por que 'char -> int' é promoção, mas 'char -> short' é conversão (mas não promoção)? 2023-08-24 20:46:59 +0800 CST
  • Martin Hope
    jabaa Por que o construtor de uma variável global não é chamado em uma biblioteca? 2023-08-18 07:15:20 +0800 CST
  • Martin Hope
    Panagiotis Syskakis Comportamento inconsistente de std::common_reference_with em tuplas. Qual é correto? 2023-08-17 21:24:06 +0800 CST
  • Martin Hope
    Alex Guteniev Por que os compiladores perdem a vetorização aqui? 2023-08-17 18:58:07 +0800 CST
  • Martin Hope
    wimalopaan Somente operações bit a bit para std::byte em C++ 17? 2023-08-17 17:13:58 +0800 CST

Hot tag

python javascript c++ c# java typescript sql reactjs html

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve