【问题标题】:JRecord - Formatting file transferred from MainframeJRecord - 从大型机传输的格式化文件
【发布时间】:2016-07-30 09:07:32
【问题描述】:

我正在尝试使用 JRecord 库在 Eclipse RCP 应用程序中显示大型机文件。我已经将 COBOL 副本作为文本文件。 为了做到这一点,

  1. 我正在通过以下方式将文件从大型机传输到我的桌面 apache commons net FTPClient API
  2. 现在我有一个文本文件
  3. 我正在删除换行符和回车符
  4. 然后我通过 CobolIoProvider 读取它并将其转换为 AbstractLine 类型的 ArrayList

但由于一些特殊字符,我有抵消问题。 这是问题

  1. 当我不执行第 3 步时,会出现偏移问题 记录 1. 因此我包括了第 3 步
  2. 即使我执行第 3 步,前几千条记录似乎也被 AbstractLineReader 正确格式化(或读取),除非它遇到特殊字符(不确定,但这是我的假设)。

代码sn-p:

ArrayList<AbstractLine> lines = new ArrayList<AbstractLine>();
        InputStream copyStream;
        InputStream fis;
        try {
            copyStream = new FileInputStream(new File(copybookfile));

            String filec = FileUtils.readFileToString(new File(datafile));
            System.out.println("initial len: "+filec.length());
            filec=filec.replaceAll("\r", "");
            filec=filec.replaceAll("\n", "");
            System.out.println("initial len: "+filec.length());

            fis= new ByteArrayInputStream(filec.getBytes());

            CobolIoProvider ioProvider = CobolIoProvider.getInstance();
            AbstractLineReader reader = ioProvider.newIOBuilder(copyStream, "REQUEST",
                    Convert.FMT_MAINFRAME).newReader(fis);
            AbstractLine line;
            while ((line = reader.read()) != null) {
                lines.add(line);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

我在这里缺少什么?我需要对从大型机传输的文件进行额外的预处理吗?

【问题讨论】:

  • 如果你有一个文本文件,你所说的“特殊字符”是什么?能否包含 COBOL 记录布局和导致问题的数据样本?
  • 布局和数据是专有的,因此我将尝试解释到目前为止我发现的内容。我能够找出导致问题的字段。在 Mainframe 中,该字段定义为 X(24),用于存储 MQ 消息 id。该字段是大多数记录的空格。但是在不是空格的记录中,就是格式出错的时候。因此,虽然步骤 3(在我的问题中解释)是使记录连续所必需的,但这也会导致这种副作用。
  • 我怀疑的“副作用”是这个 MQ 消息 id 字段具有 \r 或 \n 并且由于我的第 3 步而被替换
  • 这也引出了另一个问题。当我使用 apache commons FTPClient 从大型机传输文件时,是否可以选择不带字符“\n”和“\r”
  • 如果您所指的专有布局是 MQMD,那就是 documented by IBM。请注意消息 ID 字段内容的文档。

标签: ftp eclipse-rcp cobol apache-commons-net jrecord


【解决方案1】:

如果是带有 \r\n 行分隔符的文本文件(无二进制数据),请尝试:

    ArrayList<AbstractLine> lines = new ArrayList<AbstractLine>();
    InputStream copyStream;
    InputStream fis;
    try {
        copyStream = new FileInputStream(new File(copybookfile));

        AbstractLineReader reader = CobolIoProvider.getInstance() 
            .newIOBuilder(copyStream, "REQUEST", ICopybookDialects.FMT_MAINFRAME)
                .setFileOrganization(Constants.IO_STANDARD_TEXT_FILE)
            .newReader(datafile);
        AbstractLine line;
        while ((line = reader.read()) != null) {
            lines.add(line);
        }
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

注意: setFileOrganization 告诉 JRecord 它是什么类型的文件。所以 .setFileOrganization(Constants.IO_STANDARD_TEXT_FILE) 告诉 JRecord 它是一个带有 \n 或 \r\n 行尾标记的文本文件。这是Description of FileOrganisation in JRecord。

特殊字符让我担心,如果“数据”中有\n,它将被视为行尾。如果是 VB 文件,您可能需要进行二进制传输并保留 RDW(Record-Descriptor-Word)。

如果文件包含二进制数据,您将需要:

  • 进行二进制传输(如果是 VB 文件,则使用 RDW)
  • 使用适当的文件组织
  • 指定 Ebcdic(.setFont("cp037") 告诉 JRecord 是 US-Ebcdic)

我将使用 RecordEditor

为 Generating Code 添加第二个答案

如果您绝对确定所有记录的长度相同,则可以使用低级例程进行读取,请参阅 https://sourceforge.net/p/jrecord/discussion/678634/thread/4b00fed4/ 中的 ReadAqtrans.java 程序

基本上你会这样做:

    ICobolIOBuilder iobuilder = CobolIoProvider.getInstance()
            .newIOBuilder("copybookFileName", ICopybookDialects.FMT_MAINFRAME)
                    .setFont("CP037")
                    .setFileOrganization(Constants.IO_FIXED_LENGTH);
    LayoutDetail layout = iobuilder.getLayout();
    FixedLengthByteReader br 
         = new FixedLengthByteReader(layout.getMaximumRecordLength() + 2);
    br.open("...");

    byte[] bytes;
    while ((bytes = br.read()) != null) {           
        lines.add(iobuilder.newLine(bytes));
    }

【讨论】:

  • 谢谢布鲁斯。该解决方案就像一个魅力。 Constants.IO_STANDARD_TEXT_FILE 有何不同?
  • 我也注意到你的另一个答案 reg binary file processing
  • @ssdimmanuel,我添加了一个 Wiki 条目,希望能够解释 sourceforge.net/p/jrecord/wiki/File%20Organisation
【解决方案2】:

未来参考/二进制文件

如果文件确实包含二进制数据,您确实需要进行二进制传输。您可能会发现RecordEditor 很有用。

RecordEditor 0.98 有一个 JRecord code Generation 功能。使用 RecordEditor Generate 功能的优点是

  • Recordeditor 将尝试通过查看文件来计算出适当的文件属性
  • 您可以尝试各种属性(左侧窗格)并查看带有这些属性的文件的外观 (右手边)。
  • 高兴时,点击生成按钮,RecordEditor 将生成 JRecord 代码。有几个代码模板 可用:

    • 标准 - 将生成基本的 JRecord 代码(带有字段名称类
    • lineWrapper - 将生成一个“包装器”类,其中 Cobol 字段表示为 get/set 方法

RecordEditor 生成

在RecordEditor中选择Generate >>> Java~JRecord code for Cobol

生成屏幕

输入 Cobol CopyBook / Sample 文件并根据需要调整属性

代码模板

接下来你可以选择代码模板

生成的代码

最后,RecordEditor 会根据输入的属性生成 JRecord 代码。

【讨论】:

  • Writer 类中自动生成的代码有一个方法: private AbstractLine createFfibmf(ICobolIOBuilder iob, UserData data) throws IOException 这个方法中 UserData 是什么?我们要创建一个这种类型的类吗?看不懂。
  • RecordEditor 生成示例读写程序,您应该修改这些程序。如果不需要写入程序,请将其删除。 RecordEditor 程序无法读懂你的想法,它不知道要写入 Cobol 文件的数据来自哪里,你大概知道。如果源是 SQL-Fetch,则可以使用 ResultSet。该代码是预期的。该程序旨在作为一个示例,您可以修改或复制 && 修改。如果您愿意,可以使用它。
  • 另外,如果源是数据库,您可以删除 UserData 数据参数并在方法顶部添加 SQL 代码
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-07-03
  • 2013-05-27
  • 1970-01-01
  • 1970-01-01
  • 2012-05-06
  • 2021-08-18
  • 2021-11-08
相关资源
最近更新 更多