通过 Pyspark 编写 Mainframe 格式文件

问题描述 投票:0回答:2

我需要读取配置单元数据库表并以 EBCDIC 编码的文本格式写入该信息,因为这将用作大型机进程的输入。我们正在使用 cp037 编码。 为此,我将配置单元表读入 df,然后调用自定义 udf 将数值转换为 COMP3 格式(用于在大型机中存储数值),然后使用大型机 EBCDIC 字符集的 cp037 对其进行解码。问题是在写入文本文件或显示值时添加了一些额外的垃圾字符。

首先,我确保自定义 udf 工作正常。为此,我使用 cp037 编码回自定义 udf 的输出,下面的输出即将到来,这是完美的和预期的。这里的 newcol1 是 field1 的 MF comp3 等价物,newcol2 是 field2 的 MF COMP3 等价物。

root
 |-- field1: long (nullable = true)
 |-- newcol1: binary (nullable = true)
 |-- field2: long (nullable = true)
 |-- newcol2: binary (nullable = true)
+---------------+----------------------+---------------------------+----------------+
|field1         |newcol1               |field2                     |newcol2         |
+---------------+----------------------+---------------------------+----------------+
|2023097000     |[00 02 02 30 97 00 0C]|320264                     |[00 03 20 26 4F]|
|2023097000     |[00 02 02 30 97 00 0C]|343012                     |[00 03 43 01 2F]|
|2023100000     |[00 02 02 31 00 00 0C]|343012                     |[00 03 43 01 2F]|
|2023100000     |[00 02 02 31 00 00 0C]|320264                     |[00 03 20 26 4F]|
+---------------+----------------------+---------------------------+----------------+

但是当我在解码垃圾字符后尝试编写/显示相同内容时

after doing decoding
root
 |-- field1: long (nullable = true)
 |-- newcol11: string (nullable = true)
 |-- field2: long (nullable = true)
 |-- newcol21: string (nullable = true)

+---------------+--------+---------------------------+--------+
|field1        |newcol11|field2                     |newcol21|
+---------------+--------+---------------------------+--------+
|2023097000     |^@^B^B~Pp^@^L |320264                     |^@^C~@^W|   |
|2023097000     |^@^B^B~Pp^@^L |343012                     |^@^C?^A^G   |
|2023100000     |^@^B^B~Q^@^@^L |343012                     |^@^C?^A^G   |
|2023100000     |^@^B^B~Q^@^@^L |320264                     |^@^C~@^W|   |
+---------------+--------+---------------------------+--------+

Mainframe 文件如下所示(请注意,我已经将 HEX 设置为 ON 以显示实际的字节)

********************************
                                
                                
 -------------------------------
2023097000...Ì.p..320264..Ì..|  
FFFFFFFFFF00073900FFFFFF00722444
20230970000228070C32026403806F00
 -------------------------------

如果您注意到字节 X'78' 是添加的垃圾字符。

我正在使用的 pyspark 文件写入命令是 df.coalesce(1).write.format('text').option("encoding","cp037").mode('overwrite').save('/some_location/test/comp3_outputdata/')

似乎在写入文本格式时不支持编码选项。

根据以下链接,pyspark 在调用文本方法时似乎不支持编码。

Pyspark 文本方法中的传递编码选项

我负担不起任何其他格式,因为我的输出文件将直接由大型机进程获取。 有人可以帮我解决这个问题吗??

dataframe pyspark text encoding mainframe
2个回答
0
投票

COMP-3 是 COBOL 中使用的术语,指的是 IBM Z 硬件上的压缩十进制格式。其他格式包括二进制的 COMP。把它想象成一个 int32.

在十进制格式中,有几个十进制指令可以处理各种算术运算的数字。目前尚不清楚您想在问题中做什么,但由于您参考了 COMP-3,因此有一个合理的假设,即您希望 COBOL 程序使用 CP-037 代码页将您的数字数据处理为压缩十进制和文本信息。旁注,CP-037 通常用于欧洲系统,而 CP-1047 用于北美系统。

压缩十进制的二进制结构与代码页无关。

在您的情况下,您需要根据数据类型处理每一列。在你的情况下,你会根据你的例子得到这样的东西:

field1
- str
newcol1
- comp-3
field2
- str
newcol2
- comp-3

不是使用 CP 037 编码(仅对 field1 和 field2 有效)转换整个记录,您需要使用转换来转换 field1 和 field2。对于 newcol1 和 newcol2,您希望它们保持不变。将它们复制到新的输出记录或保持不变。因为它们是二进制编码,所以会产生像你在 x'78' 中看到的那样时髦的翻译。


0
投票

我在字段级别使用了 cp037 编码,正如@hogstorm 所强调的那样。事实证明,即将出现的额外字符是由于发送文件时的 SFT 问题……我的代码一直运行良好。来自 pyspark 的最终文件,包括普通字符串和编码的 comp3 字段,是 utf8 格式,但在将它们发送到 MF 时,我们没有以二进制模式发送它们,这就是大型机文件包含垃圾值的原因。 一旦在 sft 传输中将模式设置为二进制,问题就解决了..

© www.soinside.com 2019 - 2024. All rights reserved.