简体   繁体   English

在Java中将字符串从ASCII转换为EBCDIC?

[英]Convert String from ASCII to EBCDIC in Java?

I need to write a 'simple' util to convert from ASCII to EBCDIC? 我需要编写一个'简单'的工具来从ASCII转换为EBCDIC?

The Ascii is coming from Java, Web and going to an AS400. Ascii来自Java,Web和AS400。 I've had a google around, can't seem to find a easy solution (maybe coz there isn't one :( ). I was hoping for an opensource util or paid for util that has already been written. 我有一个谷歌周围,似乎找不到一个简单的解决方案(也许因为没有一个:()。我希望有一个开源工具或支付已经编写的实用工具。

Like this maybe? 也许这样吗?

Converter.convertToAscii(String textFromAS400)
Converter.convertToEBCDIC(String textFromJava)

Thanks, 谢谢,

Scott 斯科特

Please note that a String in Java holds text in Java's native encoding. 请注意,Java中的String包含Java本机编码的文本。 When holding an ASCII or EBCDIC "string" in memory, prior to encoding as a String, you'll have it in a byte[]. 在内存中保存ASCII或EBCDIC“字符串”时,在编码为字符串之前,您将在字节[]中使用它。

ASCII -> Java:   new String(bytes, "ASCII")
EBCDIC -> Java:  new String(bytes, "Cp1047")
Java -> ASCII:   string.getBytes("ASCII")
Java -> EBCDIC:  string.getBytes("Cp1047")

JTOpen , IBM's open source version of their Java toolbox has a collection of classes to access AS/400 objects, including a FileReader and FileWriter to access native AS400 text files. JTOpen ,IBM的Java工具箱的开源版本具有一组用于访问AS / 400对象的类,包括用于访问本机AS400文本文件的FileReader和FileWriter。 That may be easier to use then writing your own conversion classes. 这可能更容易使用,然后编写自己的转换类。

From the JTOpen homepage: 来自JTOpen主页:

Here are just a few of the many i5/OS and OS/400 resources you can access using JTOpen: 以下是您可以使用JTOpen访问的许多i5 / OS和OS / 400资源中的一小部分:

  • Database -- JDBC (SQL) and record-level access (DDM) 数据库 - JDBC(SQL)和记录级访问(DDM)
  • Integrated File System 集成文件系统
  • Program calls 程序调用
  • Commands 命令
  • Data queues 数据队列
  • Data areas 数据区域
  • Print/spool resources 打印/假脱机资源
  • Product and PTF information 产品和PTF信息
  • Jobs and job logs 工作和工作日志
  • Messages, message queues, message files 消息,消息队列,消息文件
  • Users and groups 用户和组
  • User spaces 用户空间
  • System values 系统值
  • System status 系统状态
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 "";

    }


}

}

You should use either the Java character set Cp1047 (Java 5) or Cp500 (JDK 1.3+). 您应该使用Java字符集Cp1047(Java 5)或Cp500(JDK 1.3+)。

Use the String constructor: String(byte[] bytes, [int offset, int length,] String enc) 使用String构造函数: String(byte[] bytes, [int offset, int length,] String enc)

You can create one yoursef with this translation table . 您可以使用此转换表创建一个yoursef。

But here is a site that has a link to a Java example. 但是这里有一个链接到Java示例的站点。

I make a code that transforms data types easily. 我制作了一个可以轻松转换数据类型的代码。

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);
    }
}

This is what I've been using. 这就是我一直在使用的。

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 ();
  }
}

It should be fairly simple to write a map for the EBCDIC character set, and one for the ASCII character set, and in each return the character representation of the other. 为EBCDIC字符集编写一个映射应该相当简单,为ASCII字符集编写一个映射,并在每个字符集中返回另一个字符表示。 Then just loop over the string to translate, and look up each character in the map and append it to an output string. 然后循环遍历要翻译的字符串,并查找地图中的每个字符并将其附加到输出字符串。

I don't know if there are any converter's publicly available, but it shouldn't take more than an hour or so to write one. 我不知道是否有公开的转换器,但写一个转换器不应该花费超过一个小时左右。

Perhaps, like me you were not strictly using a JDBC feature (Writing to a Dataqueue, in my instance), so the auto-magical encoding didn't apply to you since we're communicating through multiple APIs. 也许, 像我一样,你并没有严格使用JDBC功能(在我的实例中写入数据队列),所以自动魔法编码不适用于你,因为我们通过多个API进行通信。

My issue was similar to @scottyab's issue with certain characters not mapping. 我的问题类似于@ scottyab的问题,某些字符没有映射。 In my case, the example code I was referencing worked perfectly, but writing an xml string to a dataqueue resulted in [ being replaced with £. 在我的例子中,我引用的示例代码工作得很好,但是将xml字符串写入数据队列会导致[替换为£。

As a web developer working with a pre-existing database backend with decades of information, I didn't simply have the ability to "right" the "mis-configuration" as one other commenter suggests. 作为一名网络开发人员,使用已有数十年信息的预先存在的数据库后端, 我并没有像其他评论者所说的那样简单地“纠正”“错误配置”

However, I was able to see which Coded Character Set Identifier the i was likely using by issuing a command to the 400 to display file field information on a known good file: DSPFFD *LIB*/*FILE* . 但是,我能够通过向400发出命令来查看我可能使用的编码字符集标识符,以显示已知正确文件的文件字段信息: DSPFFD *LIB*/*FILE*

Doing so gave me good information, including the specific CCSID set: 这样做给了我很好的信息,包括特定的CCSID集: CCSID标识符

After some information sought on CCSIDs , I ran into a page on IBM for EBCDIC with key information printed on the page (since that has a habit of disappearing): 收到有关CCSID的一些信息之后,我在IBM的EBCDIC页面上遇到了一个页面上打印的关键信息(因为它有消失的习惯):

Version 11.0.0 Extended Binary Coded Decimal Interchange Code (EBCDIC) is an encoding scheme that is typically used on zSeries (z/OS®) and iSeries (System i®). 版本11.0.0扩展二进制编码十进制交换代码(EBCDIC)是一种通常用于zSeries(z /OS®)和iSeries(Systemi®)的编码方案。

And most helpful: 最有帮助的:

Some example EBCDIC CCSIDs are 37, 500, and 1047. 一些示例EBCDIC CCSID是37,500和1047。

Since I already learned from this question itself that Cp1047 is another good character set to try (This time, the £ turned into an accented "Y"), I tried Cp37 to see no such charsset existed, but attempted Cp037 and got the right encoding. 因为我已经从这个问题本身中学到Cp1047是另一个很好的角色设置(这次,£变成了重音的“Y”),我试过Cp37看不到这样的charsset存在, 但尝试了Cp037并得到了正确的编码。

It looks like the key is finding which Coded Character Set Identifier (CCSID) is used in your system, and ensuring that your jt400 instance - which otherwise is working perfecting - matches up 100% to the encoding set on the as400, in my case way before my lifetime and decades of business logic ago. 它看起来像关键是找到其编码字符集标识符(CCSID)在你的系统中使用,并确保您的jt400实例-否则正在完善- 100%相匹配对AS400设置编码,在我的情况的方式在我的一生和几十年的商业逻辑之前。

I want to add on to what Kwebble and Shawn S have said. 我想补充一下Kwebble和Shawn S所说的内容。 I can use JTOpen to do this. 我可以使用JTOpen来做到这一点。

I needed to write to a field which was 6 0P (6 bytes, nothing behind the decimal, packed). 我需要写一个6 0P的字段(6个字节,没有小数点后面,打包)。 That's a decimal(11,0) for those of you who don't grok DDM. 对于那些没有理解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));

Yes, I used the library KWebble mentioned. 是的,我使用了KWebble提到的库。 Looking at DSPPFD as Shawn S mentioned, I discovered that the table was using CCSID 37. This worked. 看看Shawn S提到的DSPPFD,我发现该表使用的是CCSID 37.这很有效。

I originally tried using Cp1047, as per Alan Krueger's suggestion. 根据Alan Krueger的建议,我最初尝试使用Cp1047。 It seemed to work. 它似乎工作。 Unfortunately, if my custId ended with a 5, the data rendered into the file was B0 instead of 5F. 不幸的是,如果我的custId以5结尾,则渲染到文件中的数据是B0而不是5F。 Changing it to Cp037 fixed that. 将其更改为Cp037修复了该问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM