[an error occurred while processing this directive]

HP OpenVMS Systems Documentation

Content starts here

OpenVMS 用户手册


前页 目录 索引

14.7.3 从命令过程返回数据

全局符号和逻辑名把来自命令过程的数据返回给调用过程或给 DCL 命令级。您可以在任何命令级读取全局符号或逻辑名。逻辑名可以把嵌套命令过程的数据返回给调用过程。

以下例子展示命令过程如何使用全局赋值语句建立的全局符号传递值:


$ @DATA "Paul Cramer"

$ ! DATA.COM
$ !
$ ! P1 is a full name.
$ ! NAME.COM returns the last name in the
$ ! global symbol LAST_NAME.
$ !
$ @NAME 'P1'
       $ ! NAME.COM
       $ ! P1 is a first name
       $ ! P2 is a last name
       $ ! return P2 in the global symbol LAST_NAME
       $ LAST_NAME == P2
       $ EXIT
$ ! write LAST_NAME to the terminal
$ WRITE SYS$OUTPUT "LAST_NAME = ''LAST_NAME'"

LAST_NAME = CRAMER

DATA.COM 调用命令过程 NAME.COM,为 NAME.COM 传递一个全名。NAME.COM 把它的姓放入全局符号 LAST_NAME。 NAME.COM 完成时,DCL 继续执行 DATA.COM,指定全局符号 LAST_NAME 读取它的姓。命令过程 NAME.COM 将放入一个单独文件中。为清晰起见,这个例子以缩排展示。

在这个命令过程中,REPORT.COM 获得一个报告的文件名,把这个文件名赋予逻辑名 REPORT_FILE,并且执行一个把报告写入 REPORT_FILE 的程序:



$! Obtain the name of a file and then run 
$! REPORT.EXE to write a report to the file 
$! 
$ INQUIRE FILE "Name of report file" 
$ DEFINE/NOLOG REPORT_FILE 'FILE' 
$ RUN REPORT 

$ EXIT 

在以下例子中,命令过程 REPORT.COM 被另一个过程调用。调用过程使用逻辑名 REPORT_FILE 查看这个报表文件。


$! Command procedure that updates data files
$! and optionally prepares reports
$!
$ UPDATE:
   .
   .
   .
$   INQUIRE REPORT "Prepare a report [Y or N]"
$   IF REPORT THEN GOTO REPORT_SEC
$   EXIT
$!
$ REPORT_SEC:
$   @REPORT
$   WRITE SYS$OUTPUT "Report written to ", F$TRNLNM("REPORT_FILE")
$   EXIT

14.7.4 重定向出错消息

以下几节描述如何重定向出错消息。

14.7.4.1 重定义 SYS$ERROR

按照默认,命令过程把系统出错消息发送到 SYS$ERROR 指出的文件。您可以重新定义 SYS$ERROR 把系统出错消息指引到一个指定的文件。然而,如果 SYS$ERROR 的重新定义不同于 SYS$OUTPUT (或如果重新定义 SYS$OUTPUT,但没有重新定义 SYS$ERROR),那么使用标准系统出错显示机制的 DCL 命令和映象将把系统出错级和系统严重级的出错消息发送到 SYS$ERROR 和 SYS$OUTPUT。因此,您会两次接收到这些消息 --- 一次是在 SYS$ERROR 定义指出的文件中,而另一次是在 SYS$OUTPUT 指出的文件中。成功、通知和警告级的消息只发送到 SYS$OUTPUT 指出的文件。如果想要抑制 DCL 命令的系统出错消息,要确保 SYS$ERROR 和 SYS$OUTPUT 都不能等同于终端。

如果从命令过程运行一个自己的映象并且该映象引用 SYS$ERROR,那么该映象把系统出错消息只发送到 SYS$ERROR 指出的文件 --- 即使 SYS$ERROR 不同于 SYS$OUTPUT。当这些文件不同时,只有使用标准系统出错显示机制的 DCL 命令和映象才把消息同时发送到 SYS$ERROR 和 SYS$OUTPUT。

这个命令过程接受目录名作为参数,把默认设置到这个目录,然后清除这个目录中的文件。为了抑制系统出错消息,这个过程临时把 SYS$ERROR 和 SYS$OUTPUT 定义为空设备:


$ ! Purge files in a directory and suppress messages
$ !
$ SET DEFAULT 'P1'
$ ! Suppress messages
$ !
$ DEFINE/USER_MODE SYS$ERROR NL:
$ DEFINE/USER_MODE SYS$OUTPUT NL:
$ PURGE
$ EXIT

14.7.4.2 抑制系统出错消息

也可以使用 SET MESSAGE 命令抑制系统消息。使用限定词 /NOFACILITY、/NOIDENTIFICATION、/NOSEVERITY 或 /NOTEXT,可以抑制设施名、消息标识、严重级或消息文本。

在以下例子中,设施、标识、严重性和文本消息被临时抑制,直到发出第二个 SET MESSAGE 命令:


$ ! Purge files in a directory and suppress system messages
$ !
$ SET DEFAULT 'P1'
$ ! Suppress system messages
$ !
$ SET MESSAGE/NOFACILITY -
             /NOIDENTIFICATION -
             /NOSEVERITY -
             /NOTEXT
$ PURGE
$ SET MESSAGE/FACILITY -
             /IDENTIFICATION -
             /SEVERITY
             /TEXT
$ EXIT

14.8 读取和写入文件 (文件 I/O)

从命令过程读取和写入文件的基本步骤是:

步骤 动作
1 使用 OPEN 命令打开文件。

这将把一个逻辑名赋值给这个文件,并且指定文件是否是读取、写入或读取和写入两者。后续的 READ、WRITE 和 CLOSE 命令使用这个逻辑名来查看文件。

2 使用 READ 或 WRITE 命令把记录读取或写入到文件。

完成输入和输出文件的方法通常是设计一个循环,在循环内读取记录、处理记录并且把修改的记录写入到同一文件或另一个文件。

3 使用 CLOSE 命令关闭文件。

如果您没有包括 CLOSE 命令,文件就保持打开,直到注销为止。

注意

由于注册时系统打开与进程并存的文件,如 SYS$INPUT、SYS$OUTPUT、SYS$COMMAND 和 SYS$ERROR,因此您不必为读取或写入它们而明确地打开这些文件。

以下几节描述:

  • 使用 OPEN 命令
  • 写入文件
  • 使用 WRITE 命令
  • 使用 READ 命令
  • 使用关闭命令
  • 修改文件
    • 更新记录
    • 建立新的输出文件
    • 为文件附加记录

14.9 使用 OPEN 命令

OPEN 命令打开顺序、相对或索引顺序文件。被打开的文件是与进程并存的;在您的进程期间,它们保持打开,除非您明确地关闭它们 (使用 CLOSE 命令)。在打开文件时,它们受到 OpenVMS RMS 对使用与进程并存文件的约束。

打开文件时,OPEN 命令把一个逻辑名 (指定为第一个参数) 分配给这个文件 (指定为第二个参数),并把这个名称放入进程逻辑名表。后续的 READ、WRITE 和 CLOSE 命令使用这个逻辑名引用这个文件。

在以下例子中,OPEN 命令把逻辑名 INFILE 分配给文件 DISK4:[MURPHY]STATS.DAT:


$ OPEN/READ INFILE DISK4:[MURPHY]STATS.DAT

注意

OPEN 命令中的逻辑名必须唯一。如果 OPEN 命令不起作用,而您的命令又似乎是正确的,那么更改 OPEN 命令中的逻辑名。要显示一列逻辑名定义,可使用 SHOW LOGICAL 命令。

要确保命令过程可以存取正确的文件,使用完整文件说明 (例如,DISK4:[MURPHY]STATS.DAT) 或者在打开文件之前使用 SET DEFAULT 命令指定适当的设备和目录。

您也可以指定可共享的文件。/SHARE 限定词允许其他已打开的文件。另外,用户可以用 DCL 命令 TYPE 和 SEARCH 存取可共享的文件。

OPEN/READ 命令打开文件,分配逻辑名给这个文件,并把记录指针放置在文件的开始。打开文件读取时,可以读取但是不能写入记录。每次您读取一个记录,指针移动到下一个记录。

在这个命令过程中,OPEN/READ 命令打开文件 STATS.DAT,并为这个文件分配逻辑名 INFILE:


$   OPEN/READ INFILE DISK4:[MURPHY]STATS.DAT
$ READ_FILE:
$   READ/END_OF_FILE=DONE INFILE DATA
$   GOTO READ_FILE
$ DONE:
$   CLOSE INFILE
$   EXIT

当您想要写入新文件时,使用 OPEN/WRITE 命令。OPEN/WRITE 命令按打印文件格式建立顺序文件。这个文件的记录格式是可变的,带固定的控制 (VFC) 的 2 字节记录报头。/WRITE 限定词不能与 /APPEND 限定词一起使用。

如果指定一个已经存在的文件,那么 OPEN/WRITE 命令打开一个新文件,其版本号比现有文件大 1 个数。

在以下例子中的命令过程建立一个可以写入的新文件 (NAMES.DAT):


$   OPEN/WRITE OUTFILE DISK4:[MURPHY]NAMES.DAT
$ UPDATE:
$   INQUIRE NEW_RECORD "Enter name"
$   WRITE OUTFILE NEW_RECORD
$   IF NEW_RECORD .EQS. "" THEN GOTO EXIT_CODE
$   GOTO UPDATE
$ EXIT_CODE:
$   CLOSE OUTFILE
$   EXIT

OPEN/APPEND 命令把记录附加到现有文件的末端。如果尝试打开一个不存在的文件,那就产生一个错误,并且不打开这个文件。/APPEND 限定词不能与 /WRITE 限定词一起使用。

在以下例子中,记录被附加到现有文件 NAMES.DAT 的末端:


$ OPEN/APPEND OUTFILE DISK4:[MURPHY]NAMES.DAT
$ INQUIRE NEW_RECORD "Enter name"
$ WRITE OUTFILE NEW_RECORD
   .
   .
   .
$ CLOSE OUTFILE

OPEN/READ/WRITE 命令把记录指针放置在文件的开始,因而可以读取第一个记录。当使用这个方法打开文件时,只可以替换最近读取的记录;不能写入新的记录到文件尾。另外,修正的记录必须与替换的记录有同样的大小。

在以下例子中,记录指针放置在文件 STATS.DAT 的开始,因而可以读取第一个记录:


$ OPEN/READ/WRITE FILE DISK4:[MURPHY]STATS.DAT

14.10 写入文件

要写入文件,使用以下过程:

步骤 动作
1 打开文件以便写入。
2 用一个标号开始写入循环。

文件 I/O 总是在一个循环中完成,除非您写入或读取单个记录。

3 读取要写入的数据。

使用 INQUIRE 命令或 READ 命令把数据读入一个符号。

4 测试数据。

检查包含数据的符号。如果这个符号为空 (例如,如果按下 Return 并且在这行中没有输入数据),就到达写入文件数据的末端,并且应该结束循环。否则,继续。

5 把数据写入文件。

使用 WRITE 命令把符号的值 (一个记录) 写入文件。

6 返回到循环的开始。

您保持在循环内,直到没有更多的数据写入文件。

7 结束循环并关闭文件。

以下命令过程把数据写入新文件 STATS.DAT。如果这个名称的文件存在,就建立一个新版本。


$ ! Write a file
$ ON ERROR THEN EXIT                         ! Exit if the command
$ !                                          !   procedure cannot
$ !                                          !   open the file
$ OPEN/WRITE IN_FILE DISK4:[MURPHY]STATS.DAT ! Open the file
$ ON CONTROL_Y THEN GOTO END_WRITE           ! Close the file if you
$ !                                          !   quit execution with
$ !                                          !   Ctrl/Y
$ ON ERROR THEN GOTO END_WRITE               ! Close the file if an
$ !                                          !   error occurs
$WRITE:                                      ! Begin the loop
$ INQUIRE STUFF "Input data"                 ! Prompt for input
$ IF STUFF .EQS. "" THEN GOTO END_WRITE      ! Test for the end of
$ !                                          !   the file
$ WRITE IN_FILE STUFF                        ! Write to the file
$ GOTO WRITE                                 ! Go to the beginning
$END_WRITE:                                  ! End the loop
$ !                                          !
$ CLOSE IN_FILE                              ! Close the file

14.10.1 使用唯一文件名建立文件

要用唯一名建立文件,使用 F$SEARCH 词法函数可查看这个名称是否已经在目录中。(有关 F$SEARCH 的详情,请参阅 OpenVMS DCL Dictionary 对词法函数的描述。)

这个命令过程提示用户输入一个文件名,然后使用 F$SEARCH 词法函数在默认目录中搜索这个名称。如果已经存在这个名称的文件,则把控制传递到 ERROR_1,这个过程打印消息 "The file already exists",并把控制返回到标号 GET_NAME。然后这个过程提示输入另一个文件名,如以下例子所示:


$ ! FILES.COM
$ !
$GET_NAME:
$ INQUIRE FILE "File"           ! Prompt the user for a file name
$ IF F$SEARCH (FILE) .NES. ""   ! Make sure the file name is unique
$ THEN
$    WRITE SYS$OUTPUT "The file already exists"
$    GOTO GET_NAME
$ ELSE
$    OPEN/WRITE IN_FILE 'FILE'  ! Open the file with WRITE access
$ ENDIF
   .
   .
   .
$ EXIT

14.11 使用 WRITE 命令

以下几节描述如何使用 WRITE 命令。

14.11.1 指定数据

当您为 WRITE 命令指定数据时,遵循第 12 章描述的字符串表达式规则。可以按以下方法指定数据:

  • 指定按字符串表达式写入数据。WRITE 命令自动替换符号和词法函数。
  • 作为文字字符串把一个字符串写入输出文件。WRITE 命令对括入引号的字符串不执行符号替换。
  • 结合文字字符串和符号名。要强制符号替换,把整个字符串放入引号内,并且在这个符号之前使用双省略号标识它,而在它之后放置一个单省略号。
    结合文字字符串和符号名的另一个方法是,在这个符号之前和之后插入一个逗号,用引号括住定界的符号,然后把整个字符串括入引号内。例如:


    $ WRITE OUTFILE "Count is ",COUNT,"."
    
  • 在 WRITE 命令行中使用省略号强制符号替换。
  • 使用省略号强制在字符串内的符号替换,可结合文字字符串和词法函数。

例子


$! Define symbols
$!
$ CREATED = "File created April 15, 2002"
$ COUNT = 4
$ P4 = "fourth parameter"
$!
$! Open the file DATA.OUT for writing
$!
$ OPEN/WRITE OUTFILE DISK4:[MURPHY]DATA.OUT
$!
$ WRITE OUTFILE CREATED                 (1)
$ WRITE OUTFILE "CREATED"               (2)
$!
$ WRITE OUTFILE "Count is ''COUNT'."    (3)
$ WRITE OUTFILE P'COUNT'                (4)
$!
$ WRITE OUTFILE "Mode is ''f$mode()'"   (5)
$!
$ CLOSE OUTFILE


$ TYPE DISK4:[MURPHY]DATA.OUT [Return]   (6)
File created April 15, 2002
CREATED
Count is 4.
fourth parameter
Mode is INTERACTIVE
$

检查这个例子时,注意以下几点:

  1. 指定数据作为字符串表达式写入。
  2. 把字符串 CREATED 作为文字字符串写入输出文件。
  3. 结合文字字符串和符号名 。
  4. 在 WRITE 命令行中使用省略号强制符号替换。在这个例子中,WRITE 命令替换符号 COUNT 的值,并在结果命令串 (P4)执行符号替换。
  5. 结合文字字符串和词法函数。
  6. 显示由以前的 WRITE 命令写入输出文件 DATA.OUT 的数据。

14.11.2 使用 /SYMBOL 限定词

当 WRITE 命令写入一个记录时,它把记录指针定位在刚才写入的记录之后。WRITE 命令写入的记录可以多达 2,048 个字节长。

如果存在以下任意一个条件,则使用 /SYMBOL 限定词写入记录:

  • 记录长度比 1,024 个字节要长。
  • 在 WRITE 命令中的表达式比 255 个字节要长。

有关写入长记录的详情,请参阅 OpenVMS DCL Dictionary 对 WRITE 命令的描述。

14.11.3 使用 /UPDATE 限定词

您可以使用带 /UPDATE 限定词的 WRITE 命令更改记录,而不是插入新记录。要使用 /UPDATE 限定词,必须打开文件供读取和写入。

14.12 使用 READ 命令

使用 READ 命令读取记录,并把它的内容赋值给一个符号。您可以使用 READ 命令读取小于或等于 1,024 个字符长的记录。要从一个文件中读取数据,使用以下过程:

步骤 动作
1 为读取打开文件。
2 用一个标号开始读取循环。

文件 I/O 总是在循环中完成,除非您读取或写入单个记录。

3 从这个文件读取数据。

使用带 /END_OF_FILE 限定词的 READ 命令读取记录,并把它的内容赋值给一个符号。当到达文件尾时,/END_OF_FILE 限定词使 DCL 把控制传递给 /END_OF_FILE 限定词指定的标号。一般,您指定标记读取循环结束的标号。

4 处理数据。

顺序地读取文件时,处理当前记录然后读取下一个记录。

5 返回到循环的开始。

保持在循环内,直到达到文件尾。

6 结束循环并关闭文件。

以下命令过程读取和处理文件 STATS.DAT 中的每个记录。这个过程重复地执行 READ 命令,直到返回文件结束状态。然后,这个过程转移到标记为 END_READ 的行。


$ OPEN/READ INFILE DISK4:[MURPHY]STATS.DAT  !Open the file
$ !
$READ_DATA:                                 !Begin the loop
$ READ/END_OF_FILE=END_READ INFILE RECORD   !Read a record; test for
$                                           !  end of file
$                                           ! Process the data
   .
   .
   .
$ GOTO READ_DATA                            !Go to the beginning
$                                           !   of the loop
$END_READ:                                  !End of loop
$ CLOSE INFILE                              !Close the file
$ EXIT

为 READ 命令指定一个符号名时,命令解释程序把这个符号名放在当前命令级的局部符号表。如果为一个以上 READ 命令使用同一符号名,那么每个 READ 命令重新定义这个符号名的值。例如,在上面的例子中,每次循环时,READ 命令从输入文件 (STATS.DAT) 读取新记录。然后,它使用这个记录重新定义符号 RECORD 的值。

14.12.1 使用 /END_OF_FILE 限定词

您读取文件时,通常您读取并处理每个记录,直到文件尾。使用 READ 命令的 /END_OF_FILE 限定词可以构造一个循环,在循环中从文件读取记录、处理记录并且当完成读取所有记录时退出循环。

注意,为 /END_OF_FILE 限定词指定的标号与 GOTO 命令指定的标号遵循同样的规则。(有关使用 GOTO 命令的详情,请参阅第 13 章。)

在循环中使用 READ 命令时,您应该总是使用 /END_OF_FILE 限定词。否则,当 OPENVMS 记录管理服务 (OpenVMS RMS) 返回指出文件结束的出错条件时,命令解释程序就执行当前 ON 命令指定的出错动作。例如,OpenVMS RMS 返回出错状态 %RMS-E-EOF。这回使命令过程退出,除非这个过程已建立自己的出错处理。


前页 后页 目录 索引