Преобразование EBCDIC в ASCII в java

Я должен конвертировать файл EBCDIC в ASCII с помощью Java. Пока у меня есть этот код:

public class Migration {
    InputStreamReader reader;
    StringBuilder builder;

    public Migration(){
        try {
            reader = new InputStreamReader(new FileInputStream("C:\\TI3\\Legacy Systemen\\Week 3\\Oefening 3\\inputfile.dat"),
                   java.nio.charset.Charset.forName("ibm500") );
        } catch(FileNotFoundException e){
            e.printStackTrace();
        }
        builder = new StringBuilder();
    }

    public void read() throws IOException {
        int theInt;
        while((theInt = reader.read()) != -1){
            char theChar = (char) theInt;
            builder.append(theChar);

        }

        reader.close();
    }

    @Override
    public String toString(){
        return builder.toString();
    }
}

Описание файла следующее:

 02 KDGEX.
      05 B1-LENGTH PIC S9(04) USAGE IS COMP.
      05 B1-CODE PIC S9(04) USAGE IS COMP.
      05 B1-NUMBER PIC X(08).
      05 B1-PPR-NAME PIC X(06).
      05 B1-PPR-FED PIC 9(03).
      05 B1-PPR-RNR PIC S9(08) USAGE IS COMP.
      05 B1-DATA.
        10 B1-VBOND PIC 9(02).
        10 B1-KONST.
          20 B1-AFDEL PIC 9(03).
          20 B1-KASSIER PIC 9(03).
          20 B1-DATZIT-DM PIC 9(04).
        10 B1-BETWYZ PIC X(01).
        10 B1-RNR PIC X(13).
        10 B1-BETKOD PIC 9(02).
        10 B1-VOLGNR-INF PIC 9(02).
        10 B1-QUAL-PREST PIC 9(03).
        10 B1-REKNUM PIC 9(12).
        10 B1-REKNR REDEFINES B1-REKNUM.
          20 B1-REKNR-PART1 PIC 9(03).
          20 B1-REKNR-PART2 PIC 9(07).
          20 B1-REKNR-PART3 PIC 9(02).
        10 B1-VOLGNR-M30 PIC 9(03).
        10 B1-OMSCHR.
          15 B1-OMSCHR1 PIC X(14).
          15 B1-OMSCHR2 PIC X(14).
        10 B1-OMSCHR-INF REDEFINES B1-OMSCHR.
          15 B1-AANT-PREST PIC 9(02).
          15 B1-VERSTR PIC 9(01).
          15 B1-LASTDATE PIC 9(06).
          15 B1-HONOR PIC 9(06).
          15 B1-RIJKN PIC X(13).
        10 FILLER--1 PIC 9(02).
        10 B1-INFOREK PIC 9(01).
        10 B1-BEDRAG-EUR PIC 9(08).
        10 B1-BEDRAG-DV PIC X(01).
        10 B1-BEDRAG-RMG-DV REDEFINES B1-BEDRAG-DV PIC X(01).
      05 FILLER PIC X(5).

Мы можем игнорировать первые 2 байта в каждой строке. Проблема в байтах, где используется USAGE IS COMP, поскольку читатель не конвертирует их должным образом, я думаю, что я должен читать их как байты или что-то еще, хотя я понятия не имею, как.

Ответ 1

Если я правильно интерпретирую этот формат, у вас есть формат двоичного файла с фиксированными записями. Некоторые из этих записей не являются символьными данными (COBOL вычислительные поля?)

Итак, вам нужно будет прочитать записи, используя более низкоуровневый подход, обрабатывающий отдельные поля каждой записи:

import java.io.*;

public class Record {
  private byte[] kdgex = new byte[2]; // COMP
  private byte[] b1code = new byte[2]; // COMP
  private byte[] b1number = new byte[8]; // DISPLAY
  // other fields

  public void read(DataInput data) throws IOException {
    data.readFully(kdgex);
    data.readFully(b1code);
    data.readFully(b1number);
    // other fields
  }

  public void write(DataOutput out) throws IOException {
    out.write(kdgex);
    out.write(b1code);
    out.write(b1number);
    // other fields
  }
}

Здесь я использовал байтовые массивы для первых трех полей записи, но при необходимости вы могли использовать другие более подходящие типы (например, short для первого поля с readShort.) Примечание: моя интерпретация ширины поля, скорее всего, неверна; это просто пример.

DataInputStream обычно используется как DataInput.

Поскольку все символы в исходном и целевом кодировках используют одну октетовую кодовую точку, вы должны иметь возможность перекодировать поля данных символов, используя способ, подобный этому:

public static byte[] transcodeField(byte[] source, Charset from, Charset to) {
  byte[] result = new String(source, from).getBytes(to);
  if (result.length != source.length) {
    throw new AssertionError(result.length + "!=" + source.length);
  }
  return result;
}

Я предлагаю пометить ваш вопрос с помощью COBOL (предположим, что это источник этого формата), чтобы кто-то еще мог говорить с большим количеством полномочий в формате источника данных.

Ответ 2

Я также столкнулся с такой же проблемой, как преобразование EBCDIC в строку ASCII. Пожалуйста, найдите код ниже, чтобы преобразовать одну строку EBCDIC в ASCII.

public class EbcdicConverter
{
    public static void main(String[] args) 
        throws Exception
    {
        String ebcdicString =<your EBCDIC string>;
        // convert String into InputStream
        InputStream is = new ByteArrayInputStream(ebcdicString.getBytes());
        ByteArrayOutputStream baos=new ByteArrayOutputStream();

        int line;
         while((line = is.read()) != -1) {
             baos.write((char)line);
         }
         String str = baos.toString("Cp500");
         System.out.println(str);
    }
}