Распаковка данных COMP-3 на Java (встроено в Пентахо)
Мы сталкиваемся с проблемой чтения данных COMP-3 на Java, встроенных в ETL Pentaho. Есть несколько значений Float, которые хранятся в виде упакованных десятичных знаков в плоском файле вместе с другим простым текстом. В то время как простые тексты читаются правильно, мы попытались использовать Charset.forName("CP500");
, но это никогда не работало. Мы все еще получаем ненужные персонажи.
Поскольку сценарии Pentaho не поддерживают COMP-3, на своих форумах они предлагали User Defined Java class
, Может ли кто-нибудь помочь нам, если вы столкнулись и решили такое?
1 ответ
Это Cobol File???, у вас есть Cobol Copybook???. Возможные варианты включают
- Как сказал Билл, конвертируйте Comp-3 в текст на исходном компьютере.
- Написать свой код конверсии
- Используйте библиотеку, как JRecord. Примечание: я автор JRecord
Конвертация Comp-3
в Comp-3,
Value Comp-3 (signed) Comp-3 (Unsigned) Zoned-Decimal
123 x'123c' x'123f' ?? "12C"
-123 x'123d' "12L"
Существует более одного способа преобразования comp-3 в десятичное целое число. Одним из способов является
- Connvert x'123c' ->> Строка "123c"
- Брось последний символ и проверь на наличие знака
Java-код для преобразования comp3 (из байтового массива:
public static String getMainframePackedDecimal(final byte[] record,
final int start,
final int len) {
String hex = getDecimal(record, start, start + len);
//Long.toHexString(toBigInt(start, len).longValue());
String ret = "";
String sign = "";
if (! "".equals(hex)) {
switch (hex.substring(hex.length() - 1).toLowerCase().charAt(0)) {
case 'd' : sign = "-";
case 'a' :
case 'b' :
case 'c' :
case 'e' :
case 'f' :
ret = sign + hex.substring(0, hex.length() - 1);
break;
default:
ret = hex;
}
}
if ("".equals(ret)) {
ret = "0";
}
}
public static String getDecimal(final byte[] record, final int start, final int fin) {
int i;
String s;
StringBuffer ret = new StringBuffer("");
int b;
for (i = start; i < fin; i++) {
b = toPostiveByte(record[i]);
s = Integer.toHexString(b);
if (s.length() == 1) {
ret.append('0');
}
ret.append(s);
}
return ret.toString();
}
JRecord
В JRecord, если у вас есть тетрадь Cobol, есть
- Cobol2Csv - программа для преобразования файла Cobol-Data в CSV с использованием Cobol Copybook
- Data2Xml преобразует файл данных Cobol в Xml, используя Cobol Copybook.
- Прочитайте Cobol-Data File с помощью Cobol Copybook.
- Прочитать файл фиксированной ширины с описанием XML
- Определите поля в Java
ICobolIOBuilder ioBldr = JRecordInterface1.COBOL
.newIOBuilder(copybookName)
.setDialect( ICopybookDialects.FMT_MAINFRAME)
.setFont("cp037")
.setFileOrganization(Constants.IO_FIXED_LENGTH)
.setDropCopybookNameFromFields(true);
AbstractLine saleRecord;
AbstractLineReader reader = ioBldr.newReader(salesFile);
while ((saleRecord = reader.read()) != null) {
....
}
reader.close();
Определение файла в Java с помощью JRecord AbstractLineReader reader = JRecordInterface1.FIXED_WIDTH.newIOBuilder()
.defineFieldsByLength()
.addFieldByLength("Sku" , Type.ftChar, 8, 0)
.addFieldByLength("Store", Type.ftNumRightJustified, 3, 0)
.addFieldByLength("Date" , Type.ftNumRightJustified, 6, 0)
.addFieldByLength("Dept" , Type.ftNumRightJustified, 3, 0)
.addFieldByLength("Qty" , Type.ftNumRightJustified, 2, 0)
.addFieldByLength("Price", Type.ftNumRightJustified, 6, 2)
.endOfRecord()
.newReader(this.getClass().getResource("DTAR020_tst1.bin.txt").getFile());
AbstractLine saleRecord;
while ((saleRecord = reader.read()) != null) {
}
Десятичная зона
Другой числовой формат мэйнфреймов-коболов - Zoned-Decimal. Это текстовый формат, в котором знак набирается последней цифрой. В зонально-десятичном виде 123 - "12C", а -123 - "12L".