我有一个java系统进行通信,作为不同系统(java、大型机等)的网关。该java系统使用例如utf8接收请求并将其转换为目标的编码
问题在于,有一个大型机系统正在使用这种晦涩的编码,而我们正在使用的 JDK 不提供这种编码(该字符集是 IBM-924,它是 IBM-1047 的“衍生品”https://en .wikibooks.org/wiki/Character_Encodings/Code_Tables/EBCDIC/EBCDIC_1047)。 系统。
据我所知,该字符集似乎仅随 IBM JDK 提供,这不是我们使用或想要使用的字符集。
是否有一种方法可以将 IBM JDK 上存在的这一特定字符集合并到例如 openjdk 中? 如果没有,除了手动创建字符集之外还有其他选择吗? 如果是这样,有没有办法重用 IBM-1047 编码并替换 11 个不匹配的字符?
我尝试使用 IBM JDK 上存在的 charsets.jar 来合并字符集,但它遇到了问题,因为该 jar 依赖于仅存在于 IBM JDK 的 rt.jar 上的类,我当然不希望替换 rt.jar,因为它可能会导致不必要的副作用。
哦,IBM_924 在整个互联网上几乎不存在。环顾四周,它似乎要么是 ISO-8859-15(这是 JDK 附带的东西,所以只需使用 Charset.forName("ISO-8859-15")
,或者..
)是这个
。 这是我从某个随机项目中找到的一些随机映射文件(诚然,来自 unicode 组织的 icu-data 项目;就来源而言,应该具有足够的权威性)。您阅读如下:
一行可能包含:
<UFF5E> \xA1 |1
这意味着:
如果您在数据流中看到字节
0xA1
|1
因此您已经解决了所有问题:将字符集放在您自己的项目中,现在您没有依赖项,也无需依赖内置 IBM-924 的 JVM。
不太难。
创建一个名为
Ibm924CharsetProvider.java
的源文件并将其复制/粘贴到其中:
// 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("US-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;
}
};
}
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);
}
}
作为提供者使用
new String(bytes, "IBM-924")
要工作,以及将其列在所有可用字符集列表中,需要注册此类。为此,您可以将完全限定的类名(例如,该字符串)粘贴到一个空的文本文件中。您将此文本文件命名为
com.foo.yourapp.util.Ibm924CharsetProvider
。该文件需要位于您的 jar 中,路径为 java.nio.charset.spi.CharsetProvider
。然后,如果该 jar 位于您的类路径中,那么一切就应该可以正常工作。哦,听起来很复杂您实际上并不需要这样做 - 这只是为了确保 META-INF/services/java.nio.charset.spi.CharsetProvider
"IBM-924"
方法,其中我不费心注册它,而是直接使用
main
对象。运行它,它会打印:Charset