2

いくつかの列がパック 10 進数形式で、いくつかの列が通常の数値形式である固定幅ファイルを生成する必要があります。生成できました。ファイルを圧縮して、メインフレーム チームに渡しました。彼らはそれをインポートしてファイルを解凍し、EBCDIC に変換しました。問題なくパック 10 進列を取得できましたが、通常の数値フィールドは混乱しているようで、読み取ることができませんでした。ファイルをメインフレームに送信する前に、ファイルを処理/圧縮する際に必要な特定のことはありますか? COMP3 パック 10 進数を使用しています。現在は Windows XP で作業していますが、実際の運用は RHEL で行う予定です。

助けてくれてありがとう。これは緊急です。


2011 年 6 月 6 日に編集:

HEXをONにするとこんな感じ。

. . . . . . . . . . A . .
333333333326004444
210003166750C0000

最初の行の「A」にはわずかなアクセントがあるため、実際の大文字の A ではありません。

210003166 は未加工の 10 進数です。comp3 変換前のパック 10 進数の値は 000000002765000 です (必要に応じて先行ゼロを無視できます)。


更新 2: 2011 年 6 月 7 日 これは、メインフレームにロードされるファイルを作成する際に変換する方法です。ファイルには、識別番号と金額の 2 つの列が含まれています。識別番号は comp3 変換を必要とせず、金額は comp3 変換を必要とします。Comp3 変換は、Oracle SQL の最後で実行されます。変換を実行するためのクエリは次のとおりです。

Select nvl(IDENTIFIER,' ') as IDENTIFIER, nvl(utl_raw.cast_to_varchar2(comp3.convert(to_number(AMOUNT))),'0') as AMOUNT from TABLEX where IDENTIFIER = 123456789

クエリを実行した後、Java で次のことを行います。

String query = "Select nvl(IDENTIFIER,' ') as IDENTIFIER, nvl(utl_raw.cast_to_varchar2(comp3.convert(to_number(AMOUNT))),'0') as AMOUNT from TABLEX where IDENTIFIER = 210003166"; // this is the select query with COMP3 conversion


ResultSet rs = getConnection().createStatement().executeQuery(sb.toString());
sb.delete(0, sb.length()-1);
StringBuffer appendedValue = new StringBuffer (200000);
while(rs.next()){
appendedValue.append(rs.getString("IDENTIFIER"))
.append(rs.getString("AMOUNT"));
}


File toWriteFile = new File("C:/transformedFile.txt");
FileWriter writer = new FileWriter(toWriteFile, true);
writer.write(appendedValue.toString());
//writer.write(System.getProperty(ComponentConstants.LINE_SEPERATOR));
writer.flush();
appendedValue.delete(0, appendedValue.length() -1);

このようにして生成されたテキスト ファイルは、winzip ツールによって手動で圧縮され、メインフレーム チームに提供されます。メインフレーム チームはファイルをメインフレームにロードし、HEXON でファイルを参照します。

さて、ゾーン 10 進数の上位 4 ビットの変換についてですが、ファイルに正しく変換する前に変換する必要がありますか? または、メインフレーム側でフリッピングを適用する必要がありますか? 今のところ、次のコードを使用して Java 側で反転を行いました。

public static String toZoned(String num) {
    if (num == null) {
        return "";
    }
    String ret = num.trim();

    if (num.equals("") || num.equals("-") || num.equals("+")) {
        // throw ...
        return "";
    }

    char lastChar = ret.substring(ret.length() - 1).charAt(0);
    //System.out.print(ret + " Char - " + lastChar);
    if (lastChar < '0' || lastChar > '9') {
    } else if (num.startsWith("-")) {
        if (lastChar == '0') {
            lastChar = '}';
        } else {
            lastChar = (char) (lastChar + negativeDiff);
        }
        ret = ret.substring(1, ret.length() - 1) + lastChar;

    } else  {
        if (num.startsWith("+")) {
            ret = ret.substring(1);
        }

        if (lastChar == '0') {
            lastChar = '{';
        } else {
            lastChar = (char) (lastChar + positiveDiff);
        }
        ret = ret.substring(0, ret.length() - 1) + lastChar;
    }
    //System.out.print(" - " + lastChar);

    //System.out.println(" -> " + ret);
    return ret;
}

識別子は Java の終わりで 21000316F になり、それがファイルに書き込まれます。ファイルをメインフレーム チームに渡し、HEXON での出力を待っています。何か不足している場合はお知らせください。ありがとう。


更新 3: 2011 年 6 月 9 日

OK、メインフレームの結果が得られました。私は今これをやっています。

 public static void main(String[] args) throws FileNotFoundException {
            // TODO Auto-generated method stub
            String myString = new String("210003166");
            byte[] num1 = new byte[16];
            try {
                PackDec.stringToPack("000000002765000",num1,0,15);
                System.out.println("array size: " + num1.length);
            } catch (DecimalOverflowException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            } catch (DataException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            } 
            byte[] ebc = null;
            try {
                ebc = myString.getBytes("Cp037");
            } catch (UnsupportedEncodingException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            PrintWriter pw = new PrintWriter("C:/transformationTextV1.txt");
            pw.printf("%x%x%x%x%x%x%x%x%x",ebc[0],ebc[1],ebc[2],ebc[3],ebc[4], ebc[5], ebc[6], ebc[7], ebc[8]);
            pw.printf("%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x",num1[0],num1[1],num1[2],num1[3],num1[4], num1[5], num1[6], num1[7],num1[8], num1[9],num1[10], num1[11],num1[12], num1[13], num1[14],num1[15]);
            pw.close();
        }

そして、次の出力が得られます。

Á.Á.Á.Á.Á.Á.Á.Á.Á.................Ä
63636363636363636333333333333333336444444444444444444444444444444444444444444444
62616060606361666600000000000276503000000000000000000000000000000000000000000000

私は何か非常に悪いことをしているに違いない!

更新 4: 2011 年 6 月 14 日

このクエリは、James の提案を使用した後に解決されました。現在、以下のコードを使用していますが、期待される出力が得られます。

    public static void main(String[] args) throws IOException {
        // TODO Auto-generated method stub
        String myString = new String("210003166");
        byte[] num1 = new byte[16];
        try {
            PackDec.stringToPack("02765000",num1,0,8);
        } catch (DecimalOverflowException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        } catch (DataException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        } 
        byte[] ebc = null;
        try {
            ebc = myString.getBytes("Cp037");
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        FileOutputStream writer = new FileOutputStream("C:/transformedFileV3.txt");
        writer.write(ebc,0,9);
        writer.write(num1,0,8);
        writer.close();
    }
4

4 に答える 4

2

Java でコーディングしていて、出力に EBCDIC と COMP-3 を混在させる必要があるため、独自のプログラムで Unicode から EBCDIC への変換を行う必要があります。

COMP-3 フィールドが破損するため、これをファイル転送ユーティリティに任せることはできません。

しかし幸いなことに、あなたは Java を使用しているので、文字列クラスの getBytes メソッドを使用するのは簡単です..

作業例:

package com.tight.tran;

import java.io.*;

import name.benjaminjwhite.zdecimal.DataException;
import name.benjaminjwhite.zdecimal.DecimalOverflowException;
import name.benjaminjwhite.zdecimal.PackDec;

public class worong {

    /**
     * @param args
     * @throws IOException 
     */
    public static void main(String[] args) throws IOException {
        // TODO Auto-generated method stub
        String myString = new String("210003166");
        byte[] num1 = new byte[16];
        try {
            PackDec.stringToPack("000000002765000",num1,0,15);
            System.out.println("array size: " + num1.length);
        } catch (DecimalOverflowException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        } catch (DataException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        } 
        byte[] ebc = null;
        try {
            ebc = myString.getBytes("Cp037");
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        FileOutputStream writer = new FileOutputStream("C:/transformedFile.txt");
        writer.write(ebc,0,9);
        writer.write(num1,0,15);
        writer.close();
    }

}

プロデュース(私にとって!):

0000000: f2f1 f0f0 f0f3 f1f6 f600 0000 0000 0000  ................
0000010: 0000 0000 2765 000c 0d0a                 ....'e....
于 2011-06-06T09:14:25.383 に答える
1

「彼らは問題なくパック 10 進列を取得できましたが、通常の数値フィールドが台無しになっているように見えました」は、ASCII を EBCDIC に変換しなかったことを示しているようです。

ASCII ゼロ x'30' は、EBCDIC ゼロ x'F0' に変換する必要があります。これが行われなかった場合 (EBCDIC コード ページによって異なります)、x'30' はほとんどの EBCDIC ディスプレイで有効な文字にマップされません。

ただし、変換したとしても、COMP-3 データのすべてまたは一部が破損するため、別の問題が発生します。単純な変換プログラムには、文字と comp-3 を区別する方法がないため、x'00303C' などの数値を x'00F06E' に変換します。これにより、メインフレーム プログラムは恐ろしい「0C7 10 進演算例外」で爆発します。 (文化的には「StackOverflow」と同等)。

したがって、基本的にあなたは失う/失う状況にあります。パック 10 進数を捨てて、数値にプレーンな ASCII 文字を使用することをお勧めします。

圧縮によって問題が発生することはありませんが、ファイル転送ユーティリティはおそらくプレーン テキスト ファイルでは ASCII から EBCDIC への変換を行っていましたが、圧縮されたファイルではそうではありませんでした。

于 2011-06-03T05:04:29.997 に答える
1

「... EBCDIC に変換...」が問題の一部である可能性があります。

メインフレーム変換プロセスが、処理しているレコード レイアウト (つまり、どの列にバイナリ データ、パック データ、および/または文字データが含まれているか) を「認識」していない限り、マッピング プロセスはフォーマットに依存するため、何かが台無しになります。

COMP-3データは問題ないことを示しました。「EBCDICに変換」が何もしないか、すべてのデータで何らかのASCIIからCOMP-3への変換を実行していると確信しています-したがってCOMP-3以外のデータを台無しにします。

メインフレームに到達すると、次のように表示されます。

COMP-3 - 各バイトには、最後の桁 (右端、最下位) を除く 2 桁が含まれます。最下位バイトには、上位 4 ビットに 10 進数 1 桁のみが含まれ、下位 4 ビットに符号フィールドが含まれます。各 10 進数は 16 進数で記録されます (例: 5 = B'0101')

ゾーン 10 進数 (通常の数値) - 各バイトには 10 進数が 1 桁含まれます。上位 4 ビットには常に HEX F が含まれている必要があります。ただし、上位 4 ビットに符号が含まれ、下位 4 ビットに 1 桁の最下位バイトが含まれる場合があります。4 ビットの数字は 16 進数で記録されます (例: 5 = B'0101')

解凍された変換済みデータがメインフレームでどのように見えるかを確認する必要があります。ファイルの実際の HEX コンテンツが何であるかを確認できるように、「HEX ON」を使用してメインフレーム上のファイルを「BROWSE」するよう誰かに依頼してください。そこから、これを機能させるためにジャンプする必要がある種類のフープとループを把握できるはずです。

以下に、役立つリンクをいくつか示します。

更新:メインフレームの担当者が「HEX ON」でブラウジングしたときに正しい数字が表示される場合、次の 2 つの問題が考えられます。

  • 数字が間違ったニブルに格納されています。数字は下位 4 ビットに表示されます。上位 4 ビットにある場合、それは間違いなく問題です。
  • 数字以外のニブル (上位 4 ビット) には、HEX 'F' または有効な符号値が含まれていません。符号なしの数字には、バイトの上位 4 ビットに常に HEX 'F' が含まれます。数値が署名されている場合 (例: PIC S9(4) - またはそのようなもの)、最下位桁 (最後の桁) の上位 4 ビットには、HEX 'C' または 'D' が含まれている必要があります。

以下は、'HEX ON' を使用した BROWSE のスクリーン ショットです。

   File  Edit  Edit_Settings  Menu  Utilities  Compilers  Test  Help            

 VIEW       USERID.TEST.DATA - 01.99                        Columns 00001 00072 
  Command ===>                                                  Scroll ===> CSR  
  ****** ***************************** Top of Data ******************************  
 000001 0123456789                                                              
        FFFFFFFFFF44444444444444444444444444444444444444444444444444444444444444  
        012345678900000000000000000000000000000000000000000000000000000000000000  
 ------------------------------------------------------------------------------   
  000002  |¬?"±°                                                              
        012345678944444444444444444444444444444444444444444444444444444444444444  
        FFFFFFFFF000000000000000000000000000000000000000000000000000000000000000  
 ------------------------------------------------------------------------------   
  000003  àíÃÏhr                                                              
        012345678944444444444444444444444444444444444444444444444444444444444444  
        012345678900000000000000000000000000000000000000000000000000000000000000   
 ------------------------------------------------------------------------------    

「000001」、「000002」、「000003」で始まる行は「プレーン」テキストを示しています。それぞれの下の 2 行は、その上の文字の HEX 表現を示しています。HEX の 1 行目は上位 4 ビット、2 行目は下位 4 ビットを示します。

  • 行 1 には、数字 '0123456789' とそれに続く空白スペース (HEX 40) が含まれています。
  • 行 2 は、上部ニブルと下部ニブルが反転しているため、ジャンクを示しています。正確な愚かな文字は、コード ページの選択の問題なので、表示される内容に夢中にならないでください。
  • 行 3 は、上位ニブルと下位ニブルの両方に数字が含まれているため、同様のジャンクを示しています。

行 '000001' は、EBCDIC (1 バイト文字セット) を使用する IBM メインフレームの符号なしゾーン 10 進数として表示されるものです。

更新 2

6 月 6 日に質問に HEX 表示を追加しました。たぶん、フォーマットの問題がいくつかあったと思います。これが表示しようとしていたものである場合は、次の説明が役立つ場合があります。

..........A..
33333333326004444
210003166750C0000

これは 2 つの「数字」の表示であることに注意してください。

  • ゾーン 10 進数で 210003166
  • COMP-3 の 000000002765000

これは、IBM メインフレームが期待するものです。

210003166    :Á :  <-- Display character  
FFFFFFFFF00002600  <-- Upper 4 bits of each byte  
2100031660000750C  <-- Lower 4 bits of each byte  

あなたが持っているものと上記のものとの違いに注意してください:

  • ディスプレイの Zoned Decimal データの上位 4 ビットには HEX '3' が含まれており、HEX 'F' が含まれている必要があります。下位 4 ビットには、予想される数字が含まれます。これらの上位 4 ビットを修正すれば、準備完了です。ところで...あなたがZoned Decimalに試みた「変換」は何の影響もないように見えます。Zoned Decimal の各桁のビット パターンは、ASCII 文字セットの桁に対応します。
  • COMP-3 フィールドで、先頭のゼロを切り捨てることができることを示しました。申し訳ありませんが、それらは数字の一部であるか、そうでないかのどちらかです! 上記の表示には先行ゼロが含まれています。ディスプレイでは、先頭のゼロが切り捨てられ、末尾のバイトがスペース (HEX 40) で埋められているように見えます。これはうまくいきません!COMP-3 フィールドは固定桁数で定義され、すべての桁を表す必要があります。つまり、各数値の上位桁を埋めるために先行ゼロが必要です。

Zoned Decimal の修正は非常に簡単なはずです... COMP-3 の修正は、おそらく先頭のゼロを取り除かないという問題です (それ以外の場合はかなり見栄えがします)。

更新 3...

4つの上位ビットをどのように反転しますか? Java プログラムを介して変換を行っている可能性があるという印象を受けました。残念ながら、私は COBOL プログラマーですが、試してみます (笑わないでください)...

ここで見たことに基づいて、各 ASCII 桁を取得し、上位 4 ビットを HEX F に反転するだけで、結果はゾーン 10 進数の EBCDIC 桁と同等になります。次のようなものを試してください...

public static byte AsciiToZonedDecimal(byte b) {
        //flip upper 4 bits to Hex F... 
        return (byte)(b | 0xF0)
};        

上記を各 ASCII 桁に適用すると、結果は符号なし EBCDIC ゾーン 10 進数になります。

更新 4...

この時点で、James Anderson によって提供された回答は、あなたを正しい軌道に乗せるはずです。

James はname.benjaminjwhite.zdecimalを指摘しましたが、これにはデータの変換に必要なすべての Java クラスが含まれているようです。StringToZone メソッドは、 Oracle から取得した IDENTIFIER 文字列をバイト配列に変換し、出力ファイルに追加できる必要があります。

私は Java にあまり詳しくありませんが、Java 文字列は 16 ビット長の Unicode 文字として内部的に格納されていると思います。作成しようとしている EBCDIC 文字の長さはわずか 8 ビットです。これを考えると、(文字列ではなく) バイト配列を使用して出力ファイルに書き込む方がよい場合があります。非 Java プログラマーの単なる予感です。

上記toZonedの質問の方法は、文字列の最初と最後の文字のみに関係しているようです。問題の一部は、すべての文字を変換する必要があることです。最後のバイトを除いて、各バイトの上位 4 ビットは、Hex F を含むようにパッチを適用する必要があります。下位 4 ビットには 1 桁が含まれます。

ところで... この Java ユーティリティ クラスのソースは、http: //www.benjaminjwhite.name/zdecimalで入手できます。

于 2011-06-02T17:16:31.643 に答える
0

問題はEBCDIC変換にあるようです。パック 10 進数は文字をバイト値として使用し、音訳 EBCDIC <-> ASCII の対象ではありません。

制御文字 (または Windows では四角いマーカー) が表示される場合、ASCII データを EBCDIC として表示している可能性があります。

「0123456789」の代わりに「ñòóôõö øù」が表示されている場合は、ANSI または拡張 ASCII を使用してビューアで EBCDIC 文字を表示しています。

于 2011-06-02T16:44:45.290 に答える