SQR中的文件操作

在SQR中使用input/output操作

像大多数编程语言一样,SQR使用Open、Read、Write 和 Close命令处理文件。

1.打开文件

访问一个文件之前,必须先打开它。可以将一个已经存在的文件作为input文件打开以读取其中的数据,或者将文件作为output文件打开以向其写数据。打开文件的数目最多只能是256个。
当打开输入文件时,Open命令中指定的Record长度必须 >= 文件中使用的最长记录的长度。最大Record长度是(32K - 1)字节(32767)。
当打开输出文件时,除非特别指定了For-Append 参数,否则就会创建一个新文件。如果相同的文件已经存在 且 没有指定For-Append参数,那么已经存在的文件就会被覆盖掉。

下面的例子中使用了Opend命令:
  1. Open 'My_File_1' as 1 For-Reading Record=80:Vary
  2. Open 'c:\temp\My_File_2' as 2 For-Reading Record=88:Fixed
  3. Open $File_1 as 3 For-Reading
  4. Open $File_2 as #k For-Writing Record=100
  5. Open $File_3 as 4 For-Append Record=70
  6. Open &A.File_Name as 5 For-Reading Record=120:Fixed_Nolf
  7. Let $File_4='c:\files\input\My_File_3'
    Open $File_4 as 6 For-Reading Record=150:Vary
    Status=#FileStatus
    If #FileStatus != 0
    Show 'Error Opening File: ' $File_4
    Else
    Show 'File ' $File_4 'Opened Successfully'
    End-If
第1行:打开了一个输入文件“My_File_1”,用于读取操作。文件名可以是文本,也可以保存在字符串变量或者列变量中。文件名可以是绝对路径,包括磁盘驱动名和目录,也可以只是一个文件名。如果不指定磁盘驱动名和目录,SQR默认使用当前目录。文件名旁边的数字1叫作文件号(常称为文件句柄),用于程序中其他input/output命令引用该文件。在Read、Write 和 Close命令中使用文件号操作文件,而不是使用文件名。文件号可以是任意 < 64000 的整数。该例中Record最大长度为80,意味着所有超过80字节的input record都将被忽略掉。因为此例中Record类型为Vary,所以文件中所有记录必须以一个行分隔符结束(依赖于具体的平台)。特别需要注意的是Record Type = Vary的文件不能包含二进制数据。

第2行: 'c:\temp\My_File_2' 文件的Record Type = Fixed,意味着文件中所有记录的长度都等于88。每个记录都以行分隔符结束。可以使用这种类型的文件读取二进制数据。需要注意的是Type = Fixed 的文件,其记录长度不包含行分隔符。

第3行:文件名保存在$File_1变量中。建议将文件名保存在变量中,而不是硬编码。

第4行:文件名保存在变量$File_2中,用于Writing操作。该文件的句柄(即文件号)保存在数字变量 #k 中。记录最大长度为100。当没有指定Record Type时,默认为Vary。

第5行:文件以Append方式打开。这种方式意味着所有的输出信息都会被放置到文件的末尾。如果文件不存在,就创建一个文件,且该文件的Record Type = Vary、Record Length = 70。

第6行:文件名保存在列变量&A.File_Name中,用于读取数据。文件类型指定为Fixed_Nolf,意味着文件中所有记录都是120字节且每条记录末尾都没有行分隔符。这种文件类型对于读或者写二进制数据来说非常有用。

第7行:通过#FileStatus检验Open命令是否成功执行。


2.关闭文件

SQR中的文件会一直处于打开状态,直到使用Close命令或者程序正常结束。

例如:
  1. Close 1
  2. Close #k
Close命令只有一个参数:文件句柄。


3.读取文件

如果文件是以For-Reading方式打开的,就可以读取该文件。Read命令将文件中的下一跳记录读取到Read命令指定的一个变量或者多个变量中。

Read Into

有几种方式可以读取文件中的一条记录,具体情况取决于程序需要。每条记录既可以读取到一个SQR字符串变量中,也可以读取到几个变量中。如下例:

Read 1 Into $Input_Record:80

该例将整条记录都读取到一个字符串变量$Input_Record中。在处理包含可变长度字段的记录时,这种方式特别有用,下面是解析该字符串的一些例子:

Unstring $Input_Record By ',' Into $Last_Name  $First_Name  $Address
Extract $First_Name  from  $Input_Record 0 20
Let  $Last_Name=Substr($Input_Record,1,20)

Read命令的另一种方式就是将记录直接读取到指定的字段中。当清楚每个字段的确切长度时,常使用这种方式:

Read 1 into $Last_Name:20 $First_Name:10 $Address:50

检查文件结尾

读取文件的时候,要经常检查是否满足End-Of-File条件。当不再有记录可读取的时候,SQR内部变量#end-file会被设置成1。在读取每条记录后,应该检查该变量。通常做法是将Read命令放进一个循环中,当探测到End-Of-File条件时,就从循环中跳出:
!**********************************
Begin-Procedure Read-File
!**********************************
While Not #end-file
    Read 1 Into $Record:80
                If #end-file
                Break
                End-If
    Do Process-Input-Record
End-While
!At this point all the records are read from the file
Close 1

End-Procedure

查看读取状态

想要从操作系统获取文件的读取状态,可以在Read 命令中指定一个数字变量,该变量的名称在Status参数中指定。如果读取成功,就返回0到该变量中,否则就会返回特定于系统的错误号。如下例:

!**********************************
Begin-Procedure Read-File
!**********************************
While Not #end-file
   Read 1 into $Record:80 Status=#Read_Stat
   If #end-file
      Break
   End-If
   If #Read_Stat <> 0
      Show 'Bad return from the Read command, errno='  #Read_Stat     ' Record # = ' #Rcds
   Else
      Add 1 to #Rcds
      Do Process-Input-Record
   End-If
End-While
!At this point all the records are read from the file
Close 1
End-Procedure

读取文本数据

当读取文本数据(任何字符串)时,应该指定变量名和程序要读取的字节数。记住:当读取记录时,末尾的空格会被删除掉。
所有的变量总体的长度必须 <= 读取的整条记录的长度

读取二进制数据

文件记录类型为Fixed或者Fixed_Nolf。二进制字段的长度可以是1、2、4字节。读取二进制数字时,必须将其放到数字变量中。二进制数字只包含整数,如果想要包含数字的小数部分,就将该数字转化成字符串变量。如下为读取二进制数字的一个简单例子:

Read 1 Into #Amount:2  #Hours:1

读取日期字段

如果日期字段是以SQR日期变量格式写到文件中的话,可以将该字段读取到日期变量或者字符串变量。日期变量必须属于以下格式之一:

  • SQR_DB_DATE_FORMAT环境变量指定的格式
  • 特定于数据的格式
  • 独立于数据的格式:'SYYYYMMDD[HH24[MI[SS[NNNNNN]]]]'

下例将日期字段读取到日期变量中:
Declare-Variable
     Date $Input_Date
End-Declare
!**********************************
Begin-Procedure Read-File
!**********************************
While Not #end-file
Read 1 Into $Input_Date:18  $Record
If #end-file
   Break
End-If
End-While
End-Procedure
….

当日期字段被读取到一个文本变量时,可以用strtodate()函数将该字符串文本转化成日期:

Declare-Variable
Date $Date1
End-Declare
!********************************* *
Begin-Procedure Read-File
!**********************************
While Not #end-file
Read 1 Into $String_Date:18 $Record
If #end-file
Break
End-If
Let $Date1 = strtodate($String_Date)
End-While
End-Procedure

4.写入文件

SQR使你能够将记录写入到文件,只要文件是以For-Writing模式或者For-Append模式打开就行。Write命令将命令中指定变量写入到文件。Write命令可以将单个的文本值、变量、列或者一列文本值、变量、列写入到文件中。可以指定文件句柄、source fields、source fields的长度以及保存Write命令状态的变量。

1 Write 1 From $Record:80 Status=#Write_Stat
2 Write #H From $Record_2
3 Write 2 From $Last_Name:20 ',' $First_Name:10 ',' &Address:50
4 Write 3 From #Amount:2 #Number:1
5 Write 4 From $Date:18

第1行:将字符串变量作为整条记录写入文件中。因为指定了记录长度,所以只会写字符串前80个字节。如果$Record长度 > 80字节,就会截断;如果 < 80字节,记录的剩余部分就会填充空格。如果成功写入文件,就                 将0 赋值给#Write_Stat变量。

第2行:由于没有指定记录长度,所以就是用变量$Record_2的当前长度。

第3行:将三个指定的字段写入到文件中。因为想要使字段以逗号分割,所以在字段中间加入了逗号。

第4行:将数字变量作为source fields。这种情况下,必须指定长度参数。SQR只允许1、2、4字节的二进制整数。

第5行:将日期变量写入到文件。写入到文件之前,SQR会使用SQR_DB_DATE_FORMAT(如果没有设置,就使用数据库的格式)将该日期变量会被转换成字符串。

如果  Open命令中指定的记录长度 < Write命令中指定的长度,就会出现错误;
如果  Open命令中指定的记录长度 > Write命令中指定的长度,就使用Write中指定的长度。
如果不指定记录中每个字段的长度,SQR就会将文件当作拥有可变长度的记录。
不要将NULL写入到ASCII文件中,反之亦然。因为SQR字符串是以NULL结尾的。

5.创建Flat文件

使用 input/output 命令

下面的例子找到有效的员工以及他们的电话号码,然后将这些数据输出到一个文件:

!TEST17A.SQR
! The E-Mail Interface program
!********************
Begin-Program
!********************
If $sqr-platform = 'WINDOWS-NT '
   Let $FileName='c:\appldir\Employee.dat'
Else ! UNIX
   Let $FileName='/tmp/appldir/Employee.dat'
End-If
Open $FileName as 1 For-Writing Record=100 Status=#OpenStat
If #OpenStat != 0
   Show 'Error Opening ' $FileName
Else
   Do Process_Employees
   Close 1
End-If
Display 'Total records exported: ' Noline
Display #Tot_Recs 999,999,999
End-Program


!*********************************************
Begin-Procedure Process_Employees
!*********************************************
Move 0 To #Tot_Recs


Begin-Select
A.Emplid
A.Deptid
B.Name
B.Phone
 Do Write-Output-Record
From PS_Job A, PS_Personal_Data B
Where A.Emplid=B.Emplid
And A.Empl_Rcd=0
And A.Empl_Status = 'A'
And A.EFFDT = (Select MAX(Effdt)
               From PS_Job
               Where Emplid = A.Emplid
               And Empl_Rcd = A.Empl_Rcd
               And Effdt <= Sysdate)
And A.Effseq = (Select MAX(Effseq)
                From Ps_Job
                Where Emplid = A.Emplid
                And Empl_Rcd = A.Empl_Rcd
                And Effdt = A.Effdt)
End-Select
End-Procedure


!**********************************************
Begin-Procedure Write-Output-Record
!**********************************************
Write 1 From
   &A.Emplid:11
   &A.Deptid:10
   &B.Name:30
   &B.Phone:10
Add 1 to #Tot_Recs
End-Procedure

上例中虽然没有在Open命令中指定Record = Fixed,但是产生的输出文件中的记录都是固定长度的。因为在输出记录的时候指定了每个变量确切的长度。记录总长度 = 所有变量长度的和。

创建逗号分隔的输出文件

可以将上面代码中的Write_Output_Record方法改成如下代码:

!************************************************
Begin-Procedure Write_Output_Record
!************************************************
Write 1 from
   &A.Emplid ','
   &A.Deptid ','
   &B.Name ','
   &B.Phone
  Add 1 To #Tot_Recs
End-Procedure

但是在结果中发现&B.Name的一些值包含了逗号,所以需要改用其他分隔符号。


6.使用Flat文件将数据导入到数据库









评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值