Javaを使用してEBCDICファイルをASCIIに変換することになっています。これまでのところ私はこのコードを持っています:
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が存在するバイトにあります。私はこれらをバイトまたは何かとして読み取ることになっていると思いますが、方法はわかりません。
この形式を正しく解釈している場合は、固定長レコードのバイナリファイル形式があります。これらのレコードの一部は文字データではありません(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
}
}
ここでは、レコードの最初の3つのフィールドにバイト配列を使用しましたが、必要に応じて他のより適切なタイプを使用できます(最初のフィールドにshort
のように readShort を付けます)。注:フィールド幅の私の解釈はおそらく間違っています。これは単なる例です。
DataInputStream は一般的に DataInput 実装として使用されます。
ソースエンコーディングとターゲットエンコーディングのすべての文字は1オクテットあたりのコードポイントを使用するので、次のような方法を使用して文字データフィールドをトランスコードできるはずです。
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のタグを付けることをお勧めします(これがこの形式のソースであると想定しています)。
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);
}
}