Преобразовать строку из ASCII в EBCDIC в Java?
-
21-08-2019 - |
Вопрос
Мне нужно написать «простую» утилиту для преобразования ASCII в EBCDIC?
Ascii поступает из Java, Web и переходит на AS400.Я гуглил, но не нашел простого решения (возможно, потому что его нет :().Я надеялся на утилиту с открытым исходным кодом или заплатил за уже написанную утилиту.
Вот так, может быть?
Converter.convertToAscii(String textFromAS400)
Converter.convertToEBCDIC(String textFromJava)
Спасибо,
Скотт
Решение
JTOpen, Версия IBM с открытым исходным кодом их набора инструментов Java содержит набор классов для доступа к объектам AS/400, включая FileReader и FileWriter для доступа к собственным текстовым файлам AS400.Это может быть проще в использовании, чем писать собственные классы преобразования.
С домашней страницы JTOpen:
Вот лишь некоторые из множества ресурсов i5/OS и OS/400, к которым можно получить доступ с помощью JTOpen:
- База данных — JDBC (SQL) и доступ на уровне записей (DDM).
- Интегрированная файловая система
- Программные вызовы
- Команды
- Очереди данных
- Области данных
- Печать/капсула ресурсов
- Информация о продукте и PTF
- Задания и журналы заданий
- Сообщения, очереди сообщений, файлы сообщений
- Пользователи и группы
- Пользовательские пространства
- Системные ценности
- Состояние системы
Другие советы
Обратите внимание, что строка в Java содержит текст в собственной кодировке Java.При хранении в памяти «строки» ASCII или EBCDIC перед кодированием в виде строки она будет иметься в виде байта[].
ASCII -> Java: new String(bytes, "ASCII") EBCDIC -> Java: new String(bytes, "Cp1047") Java -> ASCII: string.getBytes("ASCII") Java -> EBCDIC: string.getBytes("Cp1047")
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 "";
}
}
}
Вам следует использовать либо набор символов Java Cp1047 (Java 5), либо Cp500 (JDK 1.3+).
Используйте конструктор String: String(byte[] bytes, [int offset, int length,] String enc)
Вы можете создать его самостоятельно с помощью этого таблица перевода.
Но здесь это сайт, на котором есть ссылка на пример Java.
Я создаю код, который легко преобразует типы данных.
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);
}
}
Должно быть довольно просто написать карту для набора символов 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 ();
}
}
Возможно, как я вы не использовали строго функцию JDBC (в моем случае запись в очередь данных), поэтому автомагический кодирование к вам не относится, поскольку мы общаемся через несколько API.
Моя проблема была похожа на проблему @scottyab с несопоставлением некоторых символов.В моем случае пример кода, на который я ссылался, работал отлично, но запись строки xml в очередь данных привела к замене [ на £.
Как веб-разработчик, работающий с уже существующей базой данных, содержащей десятилетия информации, У меня не было просто возможности «исправить» «неправильную конфигурацию». как предполагает еще один комментатор.
Тем не менее, я смог увидеть, какой идентификатор кодированного набора символов я, вероятно, использовал, введя команду на 400 для отображения информации о полях файла в заведомо исправном файле: DSPFFD *LIB*/*FILE*
.
Это дало мне полезную информацию, включая конкретный набор CCSID:
После некоторого информация, запрашиваемая по CCSID, я наткнулся на страницу IBM для EBCDIC с ключевой информацией, напечатанной на странице (поскольку она имеет обыкновение исчезать):
Версия 11.0.0 Расширенная бинарная кодированная десятичная кода обмена (EBCDIC) - это схема кодирования, которая обычно используется на ZSERIES (Z/OS®) и ISERIES (SYSTEM I®).
И самое полезное:
Некоторые примеры CCSID EBCDIC: 37, 500 и 1047.
Поскольку я уже узнал из этого самого вопроса что Cp1047
еще один хороший набор символов, который стоит попробовать (на этот раз £ превратился в букву «Y» с акцентом), я попробовал Cp37
чтобы увидеть, что такой кодировки не существует, но попытался Cp037
и получил правильную кодировку.
Похоже, ключ в том, чтобы найти, какой Идентификатор кодированного набора символов (CCSID) используется в вашей системе и гарантирует, что ваш экземпляр jt400, который в противном случае работает идеально, соответствует на 100% кодировке, установленной на as400, в моем случае способ до моей жизни и десятилетий бизнес-логики назад.
Я хочу добавить к тому, что сказали Квеббл и Шон С.Для этого я могу использовать JTOpen.
Мне нужно было записать в поле размером 6 0P (6 байт, ничего после десятичной дроби, упакованное).Это десятичная дробь (11,0) для тех из вас, кто не понимает DDM.
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));
Да, я использовал упомянутую библиотеку KWebbble.Посмотрев на DSPPFD, как упоминал Шон С., я обнаружил, что в таблице используется CCSID 37.Это сработало.
Первоначально я пытался использовать Cp1047 по предложению Алана Крюгера.Казалось, это сработало.К сожалению, если мой custId заканчивался на 5, данные, отображаемые в файле, были B0 вместо 5F.Изменение его на Cp037 исправило это.