我需要编写一个“简单”实用程序来从 ASCII 转换为 EBCDIC?
Ascii 来自 Java、Web 和 AS400。我有一个谷歌,似乎找不到一个简单的解决方案(也许因为没有一个:()。我希望有一个开源工具或为已经编写的工具付费。
也许像这样?
Converter.convertToAscii(String textFromAS400)
Converter.convertToEBCDIC(String textFromJava)
谢谢,
斯科特
我需要编写一个“简单”实用程序来从 ASCII 转换为 EBCDIC?
Ascii 来自 Java、Web 和 AS400。我有一个谷歌,似乎找不到一个简单的解决方案(也许因为没有一个:()。我希望有一个开源工具或为已经编写的工具付费。
也许像这样?
Converter.convertToAscii(String textFromAS400)
Converter.convertToEBCDIC(String textFromJava)
谢谢,
斯科特
请注意,Java 中的字符串以 Java 的本机编码保存文本。当在内存中保存 ASCII 或 EBCDIC“字符串”时,在编码为字符串之前,您将在 byte[] 中拥有它。
ASCII -> Java:新字符串(字节,“ASCII”) EBCDIC -> Java:新字符串(字节,“Cp1047”) Java -> ASCII:string.getBytes("ASCII") Java -> EBCDIC: string.getBytes("Cp1047")
JTOpen是 IBM 的 Java 工具箱的开源版本,它包含一组用于访问 AS/400 对象的类,包括用于访问本机 AS400 文本文件的 FileReader 和 FileWriter。这可能比编写自己的转换类更容易使用。
从 JTOpen 主页:
这里只是您可以使用 JTOpen 访问的众多 i5/OS 和 OS/400 资源中的一小部分:
- 数据库——JDBC (SQL) 和记录级访问 (DDM)
- 集成文件系统
- 程序调用
- 命令
- 数据队列
- 数据区
- 打印/假脱机资源
- 产品和 PTF 信息
- 作业和作业日志
- 消息、消息队列、消息文件
- 用户和组
- 用户空间
- 系统价值
- 系统状态
您应该使用 Java 字符集 Cp1047 (Java 5) 或 Cp500 (JDK 1.3+)。
使用字符串构造函数:String(byte[] bytes, [int offset, int length,] String enc)
package javaapplication1;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
public class ConvertBetweenCharacterSetEncodingsWithCharBuffer {
public static void main(String[] args) {
//String cadena = "@@@@@@@@@@@@@@@ñâæÃÈÄóöó@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ÔÁâãÅÙÃÁÙÄ@ÄÅÂÉã@âæÉãÃÈ@@@@@@@@";
String cadena = "ñâæÃÈÄóöó";
System.out.println(Convert(cadena,"CP1047","ISO-8859-1"));
cadena = "1SWCHD363";
System.out.println(Convert(cadena,"ISO-8859-1","CP1047"));
}
public static String Convert (String strToConvert,String in, String out){
try {
Charset charset_in = Charset.forName(out);
Charset charset_out = Charset.forName(in);
CharsetDecoder decoder = charset_out.newDecoder();
CharsetEncoder encoder = charset_in.newEncoder();
CharBuffer uCharBuffer = CharBuffer.wrap(strToConvert);
ByteBuffer bbuf = encoder.encode(uCharBuffer);
CharBuffer cbuf = decoder.decode(bbuf);
String s = cbuf.toString();
//System.out.println("Original String is: " + s);
return s;
} catch (CharacterCodingException e) {
//System.out.println("Character Coding Error: " + e.getMessage());
return "";
}
}
}
也许,像我一样,您并没有严格使用 JDBC 功能(在我的例子中写入数据队列),因此自动魔法编码不适用于您,因为我们通过多个 API 进行通信。
我的问题类似于@scottyab 的某些字符未映射的问题。就我而言,我引用的示例代码运行良好,但是将 xml 字符串写入数据队列导致 [ 被替换为 £。
作为一名使用具有数十年信息的预先存在的数据库后端的 Web 开发人员,我并没有像其他评论者所说的那样简单地“纠正”“错误配置”。
但是,通过向 400 发出命令以显示已知良好文件的文件字段信息,我能够看到我可能使用的编码字符集标识符:DSPFFD *LIB*/*FILE*
.
在CCSIDs 上搜索了一些信息后,我在 IBM 的EBCDIC页面上看到了一个页面,该页面上印有关键信息(因为它有消失的习惯):
版本 11.0.0 扩展二进制编码十进制交换码 (EBCDIC) 是一种编码方案,通常用于 zSeries (z/OS®) 和 iSeries (System i®)。
最有帮助的:
一些示例 EBCDIC CCSID 是 37、500 和 1047。
由于我已经从这个问题本身了解到这是Cp1047
另一个值得尝试的好字符集(这次,£ 变成了重音“Y”),我试图Cp37
查看不存在这样的字符集,但尝试Cp037
并获得了正确的编码。
看起来关键是找到您的系统中使用了哪个编码字符集标识符(CCSID),并确保您的 jt400 实例(否则正在完善)与 as400 上的编码集 100% 匹配,以我为例在我有生之年和几十年的商业逻辑之前。
我编写了一个可以轻松转换数据类型的代码。
public class Converter{
public static void main(String[] args) {
Charset charsetEBCDIC = Charset.forName("CP037");
Charset charsetACSII = Charset.forName("US-ASCII");
String ebcdic = "(((((((";
System.out.println("String EBCDIC: " + ebcdic);
System.out.println("String converted to ASCII: " + convertTO(ebcdic, charsetEBCDIC, charsetACSII));
String ascII = "MMMMMM";
System.out.println("String ASCII: " + ascII);
System.out.println("String converted to EBCDIC: " + convertTO(ascII, charsetACSII, charsetEBCDIC));
}
public static String convertTO(String dados, Charset encondingFrom, Charset encondingTo) {
return new String(dados.getBytes(encondingFrom), encondingTo);
}
}
我想补充一下 Kwebble 和 Shawn S 所说的话。我可以使用 JTOpen 来做到这一点。
我需要写入一个 6 0P 的字段(6 个字节,小数点后面没有,打包)。对于那些不了解 DDM 的人来说,这是一个小数 (11,0)。
AS400PackedDecimal convertedCustId = new AS400PackedDecimal(11, 0);
byte[] packedCust = convertedCustId.toBytes((int) custId);
String packedCustStr = new String(packedCust, "Cp037");
StringBuilder jcommData = new StringBuilder();
jcommData.append(String.format("%6s", packedCustStr));
是的,我使用了 KWebble 提到的库。查看 Shawn S 提到的 DSPPFD,我发现该表使用的是 CCSID 37。这很有效。
根据 Alan Krueger 的建议,我最初尝试使用 Cp1047。它似乎奏效了。不幸的是,如果我的 custId 以 5 结尾,则呈现到文件中的数据是 B0 而不是 5F。将其更改为 Cp037 可以解决此问题。
为 EBCDIC 字符集和 ASCII 字符集编写一个映射应该相当简单,并在每个映射中返回另一个的字符表示。然后只需遍历要翻译的字符串,并在地图中查找每个字符并将其附加到输出字符串中。
我不知道是否有任何公开的转换器,但写一个应该不会超过一个小时左右。
这是我一直在使用的。
public static final int[] ebc2asc = new int[256];
public static final int[] asc2ebc = new int[256];
static
{
byte[] values = new byte[256];
for (int i = 0; i < 256; i++)
values[i] = (byte) i;
try
{
String s = new String (values, "CP1047");
char[] chars = s.toCharArray ();
for (int i = 0; i < 256; i++)
{
int val = chars[i];
ebc2asc[i] = val;
asc2ebc[val] = i;
}
}
catch (UnsupportedEncodingException e)
{
e.printStackTrace ();
}
}