如何在单个文件中包含十进制和普通文本?

时间:2011-06-02 15:41:53

标签: decimal cobol ebcdic packed-decimal

我需要生成一个固定宽度的文件,其中包含几个压缩十进制格式的列和少数正常数字格式的列。我能够生成。我将文件压缩并传递给大型机团队。他们导入并解压缩文件并转换为EBCDIC。他们能够得到压缩的十进制列没有任何问题,但正常的数字字段似乎搞砸了,并且是不可读的。在将文件发送到大型机之前处理/压缩文件时,是否需要执行某些特定操作?我正在使用COMP3压缩十进制。目前正在使用Windows XP,但实际生产将在RHEL上进行。

先谢谢你帮助我。这很紧急。


于2011年6月6日编辑:

这是我打开HEX时的样子。

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

第一行中的'A'具有轻微的重音,因此它不是实际的大写字母A.

210003166是原始小数。 comp3转换前的压缩十进制值为000000002765000(如果需要,我们可以忽略前导零)。


更新2:2011年6月7日 这是我如何转换创建加载到大型机的文件: 文件包含两列 - 标识号和&量。标识号不需要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浏览文件。

现在,要转换为分区十进制的高四位,我应该在将其置于文件之前进行吗?或者我是否应该在大型机端应用翻转?现在,我已经使用以下代码完成了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日

好的,我有大型机的结果。我现在正在这样做。

 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 个答案:

答案 0 :(得分: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....

答案 1 :(得分:1)

答案 2 :(得分:1)

“他们能够得到压缩的十进制列没有任何问题,但正常的数字字段似乎搞砸了”似乎表明他们没有将ASCII转换为EBCDIC。

ASCII零x'30'应转换为EBCDIC零x'F0'。如果没有这样做(取决于EBCDIC代码页),则x'30'不会映射到大多数EBCDIC显示器上的有效字符。

然而,即使他们确实翻译了您也会遇到不同的问题,因为您的所有或部分COMP-3数据都将被破坏。简单的翻译程序无法区分字符和comp-3,因此它们会将x'00303C'等数字转换为x'00F06E',这将导致任何大型机程序以可怕的“0C7十进制算术异常”轰炸出来(文化上等同于“StackOverflow”)。

所以基本上你处于输/输状态。我建议你丢弃压缩小数,并使用纯ASCII字符作为数字。

压缩不应该导致问题,除了文件传输实用程序可能在纯文本文件上执行ASCII到EBCDIC,但不在压缩文件上。

答案 3 :(得分:0)

听起来问题出在EBCDIC转换中。压缩十进制将使用字符作为字节值,并且不受音译EBCDIC&lt; - &gt;的影响。 ASCII。

如果他们看到控制字符(或Windows上的方形标记),那么他们可能会将ASCII数据视为EBCDIC。

如果他们看到“ñòóôõöøù”代替“0123456789”,那么他们就会在使用ANSI或扩展ASCII的查看器中查看EBCDIC字符。