PL/I - 如何在没有 opening/closing 文件的情况下循环读取文件多次
PL/I - How do I read a file in a loop without opening/closing the file multiple times
我有一个正在读取文件 (FILE1) 的程序。对于 FILE1 中的每条记录,它都获取字段 'A',然后搜索 FILE2 以查找具有字段 'B' 匹配值的记录。当 A = B 时,两个文件中的一些字段都被读出。该程序目前正在使用如下代码。但是,问题是我在循环中多次打开和关闭 FILE2。我在没有打开循环内文件的情况下尝试过这个,但如果我这样做,我会得到重复的记录,因为 FILE2 是从上一个搜索停止的地方读入的。每次从 FILE1 读取新记录时,有什么方法可以指向 File2 的开头?代码如下:
READ FILE(FILE1) INTO (IN_LAYOUT);
DO WHILE (MORE_RECS1);
OPEN FILE(FILE2);
READ FILE(FILE2) INTO (IN_LAYOUT2);
MORE_RECS2 = '1'B;
DO WHILE (MORE_RECS2);
IF (A = B) THEN
DO;
VAL = VAL2;
WRITE FILE (OUFILE) FROM (OUT_LAYOUT);
S_MORE_RECS2 = '0'B;
CLOSE FILE(FILE2);
END; /* ENDIF */
ELSE READ FILE(FILE2) INTO (IN_LAYOUT2);
END; /* INNER DOWHILE */
READ FILE(FILE1) INTO (IN_LAYOUT);
END;
这看起来像是匹配合并。首先尝试按您匹配的键对文件进行排序。
至少一些大型机排序实用程序内置了这种匹配合并功能,例如 Syncsort 具有 JOIN 运算符。我确定 DFSORT 也有这个能力。
在这种情况下,@cschneid 的回答是最好的解决方案。为了完整起见,还有其他可用的解决方案:
- 对键上的 2 个输入文件进行排序,并在您的程序中进行合并
- 将 File2 加载到 VSAM 文件中并进行索引查找
排序合并处理
如果按键对 2 个输入文件进行排序,您可以执行以下操作:
DO WHILE (MORE_RECS1 and MORE_RECS2);
if (key_file1 < key_file2) then do;
READ FILE(FILE1) INTO (IN_LAYOUT);
end; else if (key_file1 > key_file2) then do;
READ FILE(FILE2) INTO (IN_LAYOUT2);
end; else do;
VAL = VAL2;
WRITE FILE (OUFILE) FROM (OUT_LAYOUT);
READ FILE(FILE1) INTO (IN_LAYOUT);
end;
end;
当排序的逻辑过于复杂时(例如你
需要数据库查找
将 File2 加载到 VSAM 文件中
另一种方法是将 File2 加载到 VSAM 文件中并进行键控读取。
这对于避免多次执行昂贵的数据库查找很有用
(特别是对于不如 DB2 灵活的 IMS)。
在大多数情况下,上面的排序合并处理将比 VSAM 查找更快。
我有一个正在读取文件 (FILE1) 的程序。对于 FILE1 中的每条记录,它都获取字段 'A',然后搜索 FILE2 以查找具有字段 'B' 匹配值的记录。当 A = B 时,两个文件中的一些字段都被读出。该程序目前正在使用如下代码。但是,问题是我在循环中多次打开和关闭 FILE2。我在没有打开循环内文件的情况下尝试过这个,但如果我这样做,我会得到重复的记录,因为 FILE2 是从上一个搜索停止的地方读入的。每次从 FILE1 读取新记录时,有什么方法可以指向 File2 的开头?代码如下:
READ FILE(FILE1) INTO (IN_LAYOUT);
DO WHILE (MORE_RECS1);
OPEN FILE(FILE2);
READ FILE(FILE2) INTO (IN_LAYOUT2);
MORE_RECS2 = '1'B;
DO WHILE (MORE_RECS2);
IF (A = B) THEN
DO;
VAL = VAL2;
WRITE FILE (OUFILE) FROM (OUT_LAYOUT);
S_MORE_RECS2 = '0'B;
CLOSE FILE(FILE2);
END; /* ENDIF */
ELSE READ FILE(FILE2) INTO (IN_LAYOUT2);
END; /* INNER DOWHILE */
READ FILE(FILE1) INTO (IN_LAYOUT);
END;
这看起来像是匹配合并。首先尝试按您匹配的键对文件进行排序。
至少一些大型机排序实用程序内置了这种匹配合并功能,例如 Syncsort 具有 JOIN 运算符。我确定 DFSORT 也有这个能力。
在这种情况下,@cschneid 的回答是最好的解决方案。为了完整起见,还有其他可用的解决方案:
- 对键上的 2 个输入文件进行排序,并在您的程序中进行合并
- 将 File2 加载到 VSAM 文件中并进行索引查找
排序合并处理
如果按键对 2 个输入文件进行排序,您可以执行以下操作:
DO WHILE (MORE_RECS1 and MORE_RECS2);
if (key_file1 < key_file2) then do;
READ FILE(FILE1) INTO (IN_LAYOUT);
end; else if (key_file1 > key_file2) then do;
READ FILE(FILE2) INTO (IN_LAYOUT2);
end; else do;
VAL = VAL2;
WRITE FILE (OUFILE) FROM (OUT_LAYOUT);
READ FILE(FILE1) INTO (IN_LAYOUT);
end;
end;
当排序的逻辑过于复杂时(例如你 需要数据库查找
将 File2 加载到 VSAM 文件中
另一种方法是将 File2 加载到 VSAM 文件中并进行键控读取。 这对于避免多次执行昂贵的数据库查找很有用 (特别是对于不如 DB2 灵活的 IMS)。
在大多数情况下,上面的排序合并处理将比 VSAM 查找更快。