在将 EBCDIC 转换为十六进制时需要帮助

Posted

技术标签:

【中文标题】在将 EBCDIC 转换为十六进制时需要帮助【英文标题】:Need help in converting EBCDIC to Hexadecimal 【发布时间】:2019-06-17 07:18:31 【问题描述】:

我正在编写一个 hive UDF 来将 EBCDIC 字符转换为十六进制。 Hive 表中存在 Ebcdic 字符。目前我可以转换它,但它在转换时忽略了几个字符。

例子:

这是存储在表中的 EBCDIC 值:

AGNSAñA¦ûÃÃÂõÂjÂq  à ()

转换后的十六进制:

c1c7d5e2000a5cd4f6ef99187d07067203a0200258dd9736009f000000800017112400000000001000084008403c000000000000000080

我想要的输出:

c1c7d5e200010a5cd4f6ef99187d0706720103a0200258dd9736009f000000800017112400000000001000084008403c000000000000000080

忽略以下EBCDIC字符的转换:

01 - 这是航向的开始 10 - 这是一种逃避 15 - 新行。

以下是我目前尝试过的代码:

public class EbcdicToHex extends UDF 
  public String evaluate(String edata) throws UnsupportedEncodingException 
    byte[] ebcdiResult = getEBCDICRawData(edata);
    String hexResult = getHexData(ebcdiResult);
    return hexResult;
     

  public byte[] getEBCDICRawData (String edata) throws UnsupportedEncodingException 
    byte[] result = null;

    String ebcdic_encoding = "IBM-037"; 
    result = edata.getBytes(ebcdic_encoding);

    return result;
  

  public String  getHexData(byte[] result)
    String output = asHex(result);
    return output;
  

  public static String asHex(byte[] buf) 
    char[] HEX_CHARS = "0123456789abcdef".toCharArray();
    char[] chars = new char[2 * buf.length];
    for (int i = 0; i < buf.length; ++i) 
      chars[2 * i] = HEX_CHARS[(buf[i] & 0xF0) >>> 4];
      chars[2 * i + 1] = HEX_CHARS[buf[i] & 0x0F];
    
    return new String(chars);
  

在转换时,它会忽略几个 EBCDIC 字符。如何让它们也转换为十六进制?

【问题讨论】:

你能提供原始数据的十六进制转储吗?在查看提供的内容时,我想从源文件重复操作。您作为文件提供的内容不会为我呈现相同的十六进制值。我正在使用 EBCDIC 编码创建一个新文件并将数据粘贴到其中。我得到的十六进制值为: c1 c7 d5 e2 c1 66 8f c1 62 6a 66 8b 66 66 62 66 62 a0 62 91 62 98 62 62 62 62 40 62 40 66 40 4d 5d 15 【参考方案1】:

我认为问题出在其他地方,我创建了一个小测试用例,根据您声称被忽略的那 3 个字节创建了一个字符串,但在我的输出中它们似乎被正确转换:

  private void run(String[] args) throws Exception 
    byte[] bytes = new byte[] 0x01, 0x10, 0x15;
    String str = new String(bytes, "IBM-037");

    byte[] result = getEBCDICRawData(str);

    for(byte b : result) 
      System.out.print(Integer.toString(( b & 0xff ) + 0x100, 16).substring(1) + " ");
    

    System.out.println();
    System.out.println(evaluate(str));
  

输出:

01 10 15 011015

基于此,您的 getEBCDICRawDataevaluate 方法似乎都可以正常工作,并且让我相信您的 String 值一开始可能已经不正确。难道是字符串已经缺少这些字符了吗?或者可能是一个远射,但也许字符集不正确?有不同的 EBCDIC 字符集,所以字符串可能是使用不同的字符集组成的?虽然我怀疑这会对 01、10 和 15 字节产生很大影响。

作为最后一点,但可能与您的问题无关,我通常更喜欢使用 charset 对象上的编码/解码函数来进行此类转换:

String charset = "IBM-037";
Charset cs = Charset.forName(charset);
ByteBuffer bb = cs.encode(str);
CharBuffer cb = cs.decode(bb);

【讨论】:

非常感谢您提供的详细信息。我将尝试上述编码/解码功能并检查..

以上是关于在将 EBCDIC 转换为十六进制时需要帮助的主要内容,如果未能解决你的问题,请参考以下文章

解析ASCII十六进制转储以正确转换为二进制

将十六进制字符串转换为字节 []

c ++将字符串转换为十六进制[重复]

Java中的十进制到十六进制转换器

Python如何将浮点数作为十六进制转换为十进制

在 Delphi 中将宽字符代码点的十六进制字符串表示形式转换为宽字符