在 Apache Beam 中将 EBCDIC 转换为 ASCII

Convert EBCDIC to ASCII in Apache Beam

我正在尝试使用来自 Apache Beam 中 JRecord 的 CobolIoProvider class 将 EBCDIC 文件转换为 ASCII。

我正在使用的代码:

CobolIoProvider ioProvider = CobolIoProvider.getInstance();
AbstractLineReader reader  = ioProvider.getLineReader(Constants.IO_FIXED_LENGTH, Convert.FMT_MAINFRAME,CopybookLoader.SPLIT_NONE, copybookname, cobolfilename);

代码根据需要读取并转换文件。我只能从本地系统读取 cobolfilename 和 copybookname,它们基本上分别是 EBCDIC 文件和 copybook 的路径。但是,当我尝试从 GCS 读取文件时,它失败并显示 FileNotFoundException – “文件名、目录名或卷标语法不正确”。

有没有办法使用 CobolIoProvider class 从 GCS 读取 Cobol 文件 (EBCDIC)?

如果没有,是否有任何其他 class 可用于将 Cobol 文件 (EBCDIC) 转换为 ASCII 并允许从 GCS 读取文件。

使用 ICobolIOBuilder:-

我使用的代码:

ICobolIOBuilder iob = JRecordInterface1.COBOL.newIOBuilder("copybook.cbl")
                                    .setFileOrganization(Constants.IO_FIXED_LENGTH)
                      .setSplitCopybook(CopybookLoader.SPLIT_NONE);

AbstractLineReader reader = iob.newReader(bs); //bs is an InputStream object of my Cobol file

但是,这里有一些问题:-

1) 我必须将 copybook.cbl 保存在本地。有什么方法可以从 GCS 读取副本文件。我尝试了以下代码,试图将我的抄写本从 GCS 读取到 Stream 并将流传递给 LoadCopyBook()。但是代码没有用。

示例代码如下:

InputStream  bs2 = new ByteArrayInputStream(copybookfile.toString().getBytes());
LayoutDetail schema = new CobolCopybookLoader()
                     .loadCopyBook(   bs, " copybook.cbl",
                         CopybookLoader.SPLIT_NONE, 0, "",
                         Constants.USE_STANDARD_COLUMNS,
                         Convert.FMT_INTEL, 0, new TextLog())
                           .asLayoutDetail();

AbstractLineReader reader = LineIOProvider.getInstance().getLineReader(schema);

reader.open(inputStream, schema);

2) 使用 newReader 从流中读取 EBCDIC 文件没有将我的文件转换为 ascii。

谢谢。

将 Beam/Dataflow 用于新型基于文件的来源的最简单方法是首先使用 FileIO 获得 PCollection<ReadableFile> 然后使用 DoFn阅读那个文件。这将需要实现代码以从给定通道读取。类似于以下内容:

Pipeline p = ...
p.apply(FileIO.match().filepattern("..."))
 .apply(FileIO.readMatches(...))
 .apply(new DoFn<ReadableFile, String>() {
   @ProcessElement
   public void processElement(ProcessContext c) {
     try (ReadableByteChannel channel = c.element().open()) {
       // Use CobolIO to read from the byte channel
     }
   });

我没有完整的答案。如果您使用的是最新版本,建议更改 JRecord 代码以使用 JRecordInterface1IO-Builder 比旧的 CobolIoProvider 接口灵活得多。

String encoding = "cp037"; // cp037/IBM037 US ebcdic; cp273 - German ebcdic 
ICobolIOBuilder iob = JRecordInterface1.COBOL
       .newIOBuilder("CopybookFile.cbl") 
            .setFileOrganization(Constants.IO_FIXED_LENGTH)
            .setFont(encoding);  // should set encoding if you can

AbstractLineReader reader = iob.newReader(datastream);

通过 IO-Builder 接口,您可以使用流。这个问题 是关于从 GCS 创建流的,可能会有用。希望对 GCS 有更多了解的人可以提供帮助。

或者,您可以直接从 GCS 读取并使用 JRecord-IO-Builder[=] 的 newLine 方法创建数据行(数据记录) 28=]:

     AbstractLine l = iob.newLine(byteArray);

我将着眼于为 JRecord 创建一个基本的 Read/Write 接口,以便 JRecord 用户可以编写自己的 GCS 或 IBM 大型机访问 (ZFile) 等接口。但这需要时间。