好的,以下是手册对您的情况的说明:
企业 COBOL 编程指南
默认情况下,DFSORT 诊断消息被发送到 SYSOUT 数据集。如果要更改此默认值,请使用 DFSORT OPTION 控制卡的 MSGDDN 参数或使用 SORT-MESSAGE 专用寄存器。
企业 COBOL 语言参考
您可以使用 SORT-MESSAGE 特殊寄存器来指定数据集的 ddname,排序实用程序应使用该数据集代替 SYSOUT 数据集。在 SORT-MESSAGE 中指定的 ddname 等同于在排序控制文件中的 'MSGDDN=' 控制语句中指定的名称。
DFSORT 应用程序编程指南(我的重点)
//SYSOUT DD
标识 DFSORT 消息数据集。默认 ddname 是 SYSOUT,但您可以使用 MSGDDN 安装或运行时选项为消息数据集指定备用 ddname。如果不使用编目过程,请始终为消息数据集提供 DD 语句。(如果您从 COBOL 程序调用 DFSORT 并且使用 ddname SYSOUT 作为消息数据集,那么在您的 COBOL 程序中使用 DISPLAY 会产生不确定的打印结果。)
DFSORT 使用RECFM=FBA、LRECL=121 和为消息数据集指定的 BLKSIZE。如果您指定的 BLKSIZE 不是 121 的倍数,则 DFSORT 使用 BLKSIZE=121。如果不指定 BLKSIZE,DFSORT 会按照 SDBMSG 安装选项的指示选择块大小(请参阅 z/OS DFSORT 安装和定制)。
如果您使用临时或永久消息数据集,最好指定 MOD 的配置以确保您看到消息数据集中的所有消息和控制语句。
和:
MSGDDN
MSGDDN=ddname
临时覆盖 MSGDDN 安装选项,该选项指定消息数据集的备用 ddname。MSGDDN 必须在以下情况下生效:
v调用 DFSORT 的程序使用 SYSOUT(例如,COBOL 使用 SYSOUT)并且您不希望 DFSORT 消息与程序消息混合。
v 您的 E15 和 E35 例程是用 COBOL 编写的,并且您不希望 DFSORT 消息与程序消息混合。
v 一个程序多次调用 DFSORT,并且您希望每次调用 DFSORT 时都有单独的消息。
ddname 可以是任何 1 到 8 个字符的名称,但在作业步骤中必须是唯一的;不要使用 DFSORT 使用的名称(例如,SORTIN)。如果指定的 ddname 在运行时不可用,则使用 SYSOUT。有关使用消息数据集的详细信息,请参阅 z/OS DFSORT 消息、代码和诊断指南 注意:只有在扩展参数列表或 DFSPARM 中的 OPTION 控制语句上传递 MSGDDN 时,才会处理它。
尽管手册中有建议,但您所做的是混合来自 COBOL 和 DFSORT 的 SYSOUT 输出(实际上是多次调用 DFSORT)。您在将 SYSOUT 定向到顺序数据集的同时完成了该操作,该数据集具有与 DFSORT 使用的不同特征。由于 DFSORT 将始终输出消息,因此如果 COBOL 程序在运行中至少在 DISPLAY 上使用,则可以保证您的数据集已损坏。
如果您在测试期间的任何时候将 SYSOUT DD 定向到 SYSOUT= (spool) 数据集(我猜接近 100% 的人都这样做),您会注意到 SYSOUT 数据集上的混合输出那一步。我不确定它的外观(从未这样做过,或者知道会这样做),但您至少能够识别多次使用的来源(同一个 COBOL 程序,做自己的 DISPLAY,并且还进行多个内部排序)。
您已经通过使用 DFSORT 的 MSGDD= 修改默认输出 DD (SYSOUT) 解决了您的问题。
值得注意的是,您还可以使用编译器选项 OUTDD(somedd) 将用于 COBOL DISPLAY 的 DD 的名称从其默认值 (SYSOUT) 更改为其他名称。
语言环境默认也使用 SYSOUT,但您可以使用运行时选项 MSGFILE 来修改它(LE 运行时选项可以通过各种方式设置,请参阅语言环境文档(我发现最简单的是//CEEDOPT DD
在 JCL对于批处理程序)。
确保从 Rexx 程序中为程序的一次执行分配的文件随后被取消分配,并且不重复使用数据集名称是每次都需要注意的事情。确保您始终检查 RC,只要有东西可以设置 RC。不要在不需要的语句上指定选项。
这是您在我将其粘贴到您的问题之前显示的数据,来自我提供的程序:
0000000121
4FFFFFFFFFF
00000000121
' ` expected message text
4070007004
00D0009000
第二次尝试:
预期的消息文本
44
00
我不确定“预期的消息文本”是什么意思,也不确定“第一条记录出现两次”,也不确定“总共 4 条消息行”。
数据没有排列。在您的问题中,我更正了 0000000121 部分,但没有更正其他记录。
忽略“预期消息文本”,您将以“十六进制”格式显示两条数据记录(如果您使用它来浏览假脱机输出,请在 SDSF 中设置 HEX ON)。
第一个空白可能是 SDSF 的产物。当您第一次查看假脱机文件时,如果您查看 COLS,您会看到数据从第二列开始。如果您将屏幕向左移动,您将看到第一列,它不是数据。
因此,我们可以猜测您实际上有两条记录。一种是 10 个分区十进制数字(或“字符”),另一种是绝对不一样的。
第一条记录看起来像一个固定长度的记录,有 10 个字节。第二个看起来是一个可变长度的记录。实际上,它是一个可变长度数据块。
该文件将绝对肯定地为您提供“错误长度记录”。
但是,即便如此,您所展示的内容还是有些不妥。我认为您所做的并不是复制所有尾随空格。
我们知道您的 LRECL 为 121,对于固定长度的记录,这意味着记录的长度为 121 字节,但您显示的是 10 字节。好的,可以从覆盖长度到 10 的内容中写入。
但是,对于可变长度数据,它是这样的
X'007D' = 块长度,125 字节,块描述符字 (BDW) 的前半部分,包括 BDW 的长度(四)。X'0000' = BDW 的后半部分 X'0079' = 记录长度,121 字节,记录描述符字 (RDW) 的前半部分,包括 RDW 的长度(四)。121 字节的数据,显示为 X'40'。所以让我们假设有 121 个字节的空间。
因此,让我们回过头来假设固定长度的记录是 121 个字节,后面有空格。看到在您的“答案”中,第一条“线”没有对齐,我们可以假设您对前导空白以及第二条记录进行了调整。
目前尚不清楚从哪里开始,但您的文件绝对是“混合”。您有一个固定长度的记录,然后是一个可变长度的块(仅包含一条记录) 您需要准确粘贴您在选择假脱机文件后看到的内容,输出为十六进制模式。一直从屏幕的左到右。复制/粘贴,而不是丝网印刷。
你认为哪条线是正确的?空白,还是 0000000121?
好的,仍然没有很多工作要做:-)
您的问题与tmpDS
. 看不到内容,但这就是问题所在。
它的名称看起来非常临时,但内容使事情比您预期的要永久得多。
当发生故障的用户在您的系统上并开始运行 COBOL 程序时,该文件(具有该确切名称的数据集)已经存在于系统上。COBOL 将轻松地破坏它,可能使用 FBA 121。如果以前使用的文件不是COBOL 破坏它的文件,您将得到您详细说明的确切情况。
这是如何发生的有多种可能性。在不同的 rexx 程序中使用相同的名称是最简单的。使用 TSO-userid 作为前缀可能会有所帮助,但您需要让系统决定名称或自己生成名称,以免重复。
如果没有看到您的代码,就无法确定这一点。只有 99.3% 肯定,除非你告诉我 :-)
这是一个简短的程序,您可以使用它来读取文件并查看其中的内容:
ID DIVISION.
PROGRAM-ID. STOB26.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT IN-FILE ASSIGN TO INFILE
FILE STATUS IS W-FILE-STATUS.
DATA DIVISION.
FILE SECTION.
FD IN-FILE
RECORD IS VARYING
DEPENDING ON W-REC-LENGTH
RECORDING MODE U.
01 IN-REC.
05 FILLER OCCURS 1 TO 32760 TIMES
DEPENDING ON W-REC-LENGTH PIC X.
WORKING-STORAGE SECTION.
01 W-FILE-STATUS PIC XX.
88 FILE-STATUS-GOOD VALUE "00".
88 FILE-STATUS-OK-FOR-INPUT VALUE "00" "10".
88 END-OF-FILE VALUE "10".
01 W-REC-LENGTH PIC 9(8) COMP.
PROCEDURE DIVISION.
DISPLAY 'Start of program'
OPEN INPUT IN-FILE
IF NOT FILE-STATUS-GOOD
DISPLAY
'OPEN FAILED'
'>'
W-FILE-STATUS
'<'
CALL 'FRED'
END-IF
PERFORM UNTIL END-OF-FILE
READ IN-FILE
IF NOT FILE-STATUS-OK-FOR-INPUT
DISPLAY
"READ FAILED"
'>'
W-FILE-STATUS
'<'
CALL 'FRED'
END-IF
DISPLAY
'Record length is>'
W-REC-LENGTH
'<'
DISPLAY
'Data is>'
IN-REC
'<'
END-PERFORM
CLOSE IN-FILE
IF NOT FILE-STATUS-GOOD
DISPLAY
'CLOSE FAILED'
'>'
W-FILE-STATUS
'<'
CALL 'FRED'
END-IF
DISPLAY 'End of program'
GOBACK
.
JCL 很简单,可以基于此:
//RUNIT EXEC PGM=VARA,TIME=(,2)
//STEPLIB DD DSN=loadlibrary,DISP=SHR
//SYSOUT DD SYSOUT=*
//INFILE DD DSN=yourbusteddsn,LRECL=32760,RECFM=U,DISP=SHR