Professional Documents
Culture Documents
Working IFS 5.3. Reading Text Data From A Stream File
Working IFS 5.3. Reading Text Data From A Stream File
The big difference between reading lines and writing lines is that when you write
the data, you already know how long the line needs to be. But when you read,
you don't. You won't know how long it is until you've found the CRLF sequence
in the text!
Now, we could solve that by reading one byte from disk at a time, until one of
them turned out to be the new line sequence, but that would not run efficiently,
because disk hardware is designed to read from disk in larger chunks. So, what
we'll do is read a whole buffer of data, and then parse that data looking for our
new line sequence.
We'll save any characters in the buffer that occur after the new line, so that we
can use them as the start of our next line of text.
D readline PI 10I 0
D fd 10I 0 value
D text * value
D p_retstr S *
D len S 10I 0
c eval len = 0
c dow 1 = 1
c if rdpos>=rdlen
c eval rdpos = 0
c eval rdlen=read(fd:%addr(rdbuf):
%size(rdbuf))
c if rdlen < 1
c return -1
c endif
c endif
c if %subst(rdbuf:rdpos:1) = x'25'
c return len
c endif
c and len<>maxlen
c eval %subst(retstr:len:1) =
c %subst(rdbuf:rdpos:1)
c endif
c enddo
c return len
P E
Add that routine to the IFSTEXTR4 service program, and then add this code to
the prototypes in the IFSTEXT_H member:
D readline PR 10I 0
D fd 10I 0 value
D text * value
One more thing: Because we're writing a service program, and we want our code
to be as useful as possible, we're going to write binder source that tells the
CRTSRVPGM how other programs can bind to us.
If you haven't done this before, don't worry about it. It's really, really simple. It's
just a list of what gets exported. Here's the entire code of our binding source:
STRPGMEXP
EXPORT SYMBOL(WRITELINE)
EXPORT SYMBOL(READLINE)
ENDPGMEXP
See? Very simple. Put that code into a member called "IFSTEXTR4" in a source
file called QSRVSRC. Now let's compile it:
CRTRPGMOD IFSTEXTR4 SRCFILE(IFSEBOOK/QRPGLESRC) DBGVIEW(*LIST)
Finally, to make it easy to compile the programs that use this service program,
we'll create a binding directory. This only involves running two commands:
CRTBNDDIR IFSEBOOK/IFSTEXT TEXT('IFS Text binding directory')
* (From Chap 5)
* To compile:
D/copy IFSEBOOK/QRPGLESRC,IFSIO_H
D/copy IFSEBOOK/QRPGLESRC,ERRNO_H
D/copy IFSEBOOK/QRPGLESRC,IFSTEXT_H
D Cmd PR ExtPgm('QCMDEXC')
D fd S 10I 0
D line S 100A
D len S 10I 0
D msg S 52A
c exsr MakeFile
c exsr EditFile
c exsr ShowFile
C**************************************************************
C**************************************************************
C*------------------------
c eval fd = open('/ifstest/ch5_file.txt':
c O_TRUNC+O_CREAT+O_WRONLY:
c
S_IWUSR+S_IRUSR+S_IRGRP+S_IROTH)
c if fd < 0
c endif
c eval len = 0
c eval len = 0
c callp writeline(fd: %addr(line): len)
c eval len = 0
c callp close(fd)
C*------------------------
CSR endsr
C**************************************************************
C* Call the OS/400 text editor, and let the user change the
C* text around.
C**************************************************************
C*------------------------
c 'ch5_file.txt'')':
200)
C*------------------------
CSR endsr
C**************************************************************
C**************************************************************
C*------------------------
c eval fd = open('/ifstest/ch5_file.txt':
c O_RDONLY)
c if fd < 0
c endif
c Msg dsply
c enddo
c callp close(fd)
c dsply Msg
C*------------------------
CSR endsr
/DEFINE ERRNO_LOAD_PROCEDURE
/COPY IFSEBOOK/QRPGLESRC,ERRNO_H
Try it out by compiling it and running it. Add some text and/or remove some text
from the text file, and notice that the program will read it correctly.