Hello.
I'm trying to write variable length records to a SEQUENTIAL file. I don't want the trailing spaces to be removed. I add on two chars at the end of each record type and populate them with CRLF. My results are not what I expected. The output file appears to have binary characters and the rows are not the length of the value in WS-RECORD-LENGTH. My FD statement is:
FD MY-FILE
RECORDING MODE IS V
RECORD IS VARYING IN SIZE FROM 191 TO 370 CHARACTERS DEPENDING ON WS-RECORD-SIZE.
01 MY-RECORD.
05 MY-DATA PIC X(370)
In Working Storage
01 WS-TYPE1. (record length191)
05
05 WS-CRLF1 PIC X(2).
01 WS-TYPE2. (record length 370)
05
05 WS-CRLF2 PIC X(2).
Here's the code to populate the record.
MOVE SPACES TO WS-TYPE1.
MOVE blah blah
MOVE WS-RECORD-DELIMITER TO WS-CRLF1. (has hex values of CRLF)
MOVE 191 TO WS-RECORD-SIZE. (PIC 9(004) COMP)
MOVE WS-TYPE1 TO MY-RECORD.
WRITE MY-RECORD.
Any suggestions will be greatly appreciated
I am assuming that Net Express is the product that you are using, is that correct?
If you define the file as SEQUENTIAL and it has variable length records then it will have a binary header in the file and each record will contain a length field.
I think that what you are looking for is a LINE SEQUENTIAL file where the CRLF character will automatically be appended to the end of each variable length record.
There is a file handler configuration option named STRIPSPACE that would have to be set to OFF in order to keep spaces at the end of the record up to the length of the record specified.
Create a configuration file called extfh.cfg and set the environment variable EXTFH to point to it.
If this is Net Express then you can set this directly in the project properties under IDE.
the file should contain:
[XFH-DEFAULT]
STRIPSPACE=OFF
The following test program will do what you want.
It is a modified version of your example:
id division.
program-id. testvarying.
environment division.
input-output section.
select my-file assign to "myfile.txt"
organization is line sequential
file status is file-status.
data division.
file section.
FD MY-FILE
RECORDING MODE IS V
RECORD IS VARYING IN SIZE FROM 10 TO 20 CHARACTERS
DEPENDING ON WS-RECORD-SIZE.
01 MY-RECORD.
05 MY-DATA PIC X(20).
working-storage section.
01 ws-record-size pic 9(3).
01 WS-TYPE1.
05 data1 pic x(10).
01 WS-TYPE2.
05 data2 pic x(20).
01 file-status pic x(2).
procedure division.
open output my-file
MOVE SPACES TO WS-TYPE1.
MOVE "11111" to data1
MOVE 10 TO WS-RECORD-SIZE.
MOVE WS-TYPE1 TO MY-RECORD.
WRITE MY-RECORD.
MOVE SPACES TO WS-TYPE2.
MOVE "222" to data2
MOVE 20 TO WS-RECORD-SIZE.
MOVE WS-TYPE2 TO MY-RECORD.
WRITE MY-RECORD.
close my-file.
Hello.
I'm trying to write variable length records to a SEQUENTIAL file. I don't want the trailing spaces to be removed. I add on two chars at the end of each record type and populate them with CRLF. My results are not what I expected. The output file appears to have binary characters and the rows are not the length of the value in WS-RECORD-LENGTH. My FD statement is:
FD MY-FILE
RECORDING MODE IS V
RECORD IS VARYING IN SIZE FROM 191 TO 370 CHARACTERS DEPENDING ON WS-RECORD-SIZE.
01 MY-RECORD.
05 MY-DATA PIC X(370)
In Working Storage
01 WS-TYPE1. (record length191)
05
05 WS-CRLF1 PIC X(2).
01 WS-TYPE2. (record length 370)
05
05 WS-CRLF2 PIC X(2).
Here's the code to populate the record.
MOVE SPACES TO WS-TYPE1.
MOVE blah blah
MOVE WS-RECORD-DELIMITER TO WS-CRLF1. (has hex values of CRLF)
MOVE 191 TO WS-RECORD-SIZE. (PIC 9(004) COMP)
MOVE WS-TYPE1 TO MY-RECORD.
WRITE MY-RECORD.
Any suggestions will be greatly appreciated
Thanks Chris for your prompt and detailed (and very informative) reply. Yes, I'm using Net Express 5.1.
My concern in using the configuration option STRIPSPACE in the extfh.cfg file as this would apply to all files defined as Line Sequential. This will not work for me as sometimes we require the spaces to be suppressed and other times we don't.
In Net Express, in the Project menu, the Properties option is greyed out.
==================================================================================================================
Thank you Chris and Dan for your answers to my question. I'm new to this forum and could not see where to answer your individual posts. The only thing I saw that allowed me to respond was the edit icon on my previous post!
Chris, is there any way to use the file name tag in the EXTFH.CFG with a derived file name? My problem is that the output text file that's created has a file name that consists partly of the current date (e.g. ABCDEFG_CCYYMMDD.txt).
Dan, the text file(s) created is sent to several different client sites and I have no idea what programs are processing them. Thank you so much for the detailed explanation. What I'm trying to accomplish is use one SELECT statement for a file that is to be used to generate three different output text files. I open and close the file three times so that works well. File one created has records that are 100 chars long, file two records are 200 chars long and file three records are 300 chars long. Previously I used the ORGANIZATION LINE SEQUENTIAL mode and that worked fine since the users did not complain about the variable length records (spaces at the end being truncated). However, a new client has requested that the records be fixed length.
Since I need to get the change out the door quickly I landed up with three SELECT statements but would really like to be able to work it the original way I planned to. The individual file name in the EXTFH.CFG seems to be the way to go but I need to be able to use a file name that's created on the fly.
#VariableLengthRecords
Hello.
I'm trying to write variable length records to a SEQUENTIAL file. I don't want the trailing spaces to be removed. I add on two chars at the end of each record type and populate them with CRLF. My results are not what I expected. The output file appears to have binary characters and the rows are not the length of the value in WS-RECORD-LENGTH. My FD statement is:
FD MY-FILE
RECORDING MODE IS V
RECORD IS VARYING IN SIZE FROM 191 TO 370 CHARACTERS DEPENDING ON WS-RECORD-SIZE.
01 MY-RECORD.
05 MY-DATA PIC X(370)
In Working Storage
01 WS-TYPE1. (record length191)
05
05 WS-CRLF1 PIC X(2).
01 WS-TYPE2. (record length 370)
05
05 WS-CRLF2 PIC X(2).
Here's the code to populate the record.
MOVE SPACES TO WS-TYPE1.
MOVE blah blah
MOVE WS-RECORD-DELIMITER TO WS-CRLF1. (has hex values of CRLF)
MOVE 191 TO WS-RECORD-SIZE. (PIC 9(004) COMP)
MOVE WS-TYPE1 TO MY-RECORD.
WRITE MY-RECORD.
Any suggestions will be greatly appreciated
The STRIPSPACE=OFF can be applied to a specific file by placing a file name tag in the extfh.cfg.
[XFH-DEFAULT]
BASENAME=ON
[MYFILE.TXT]
STRIPSPACE=OFF
If the properties option is greyed out it means that you don't have a project loaded so you must just be loading your source code directly in the IDE. I would highly recommend using a project file as it gives you a much better way of organizing your source and exectable builds. See the documentation here under Getting Started-->Using Net Express.
If you are not using a project then you can also set the EXTFH environment variable at the system level under Control Panel-->System->Advanced-->Environment Variables set EXTFH under System variables.
Hello.
I'm trying to write variable length records to a SEQUENTIAL file. I don't want the trailing spaces to be removed. I add on two chars at the end of each record type and populate them with CRLF. My results are not what I expected. The output file appears to have binary characters and the rows are not the length of the value in WS-RECORD-LENGTH. My FD statement is:
FD MY-FILE
RECORDING MODE IS V
RECORD IS VARYING IN SIZE FROM 191 TO 370 CHARACTERS DEPENDING ON WS-RECORD-SIZE.
01 MY-RECORD.
05 MY-DATA PIC X(370)
In Working Storage
01 WS-TYPE1. (record length191)
05
05 WS-CRLF1 PIC X(2).
01 WS-TYPE2. (record length 370)
05
05 WS-CRLF2 PIC X(2).
Here's the code to populate the record.
MOVE SPACES TO WS-TYPE1.
MOVE blah blah
MOVE WS-RECORD-DELIMITER TO WS-CRLF1. (has hex values of CRLF)
MOVE 191 TO WS-RECORD-SIZE. (PIC 9(004) COMP)
MOVE WS-TYPE1 TO MY-RECORD.
WRITE MY-RECORD.
Any suggestions will be greatly appreciated
The section of the documentation that describes this is Programming > File handling > Reference > File structures. There are two general categories: File With Headers and Files Without headers.
If you declare a sequential file as RECORDING MODE V, then you are declaring a Variable Format Record Sequential File. If you write data to such a file, then use a hex editor to examine the file on disk, you will see it will include an overall file header, plus a header in front of each record. The headers are part of the internal representation, and are invisible to a COBOL program that declares the file as Variable Format Record Sequential File. You needn't declare a WS-RECORD-SIZE PIC 9(004) COMP and you needn't write a CRLF record terminator, instead the record size is held internally in each record header, and this is handled behind the scenes.
Why did you get the idea to include a WS-RECORD-SIZE and add an extra two bytes in the record description and put CRLF in them before writing each record? This is usually not necessary if COBOL programs will be the only software reading or interpreting the file. Do you also need non-COBOL software to be able to read and interpret the file?
Perhaps what you really want is a File Without Headers. The first type of sequential file without headers is a Line Sequential file. This is declared ORGANIZATION LINE SEQUENTIAL, without the RECORDING MODE clause. The representation on disk does not include headers. Each record is terminated by a CRLF (on Windows) or just an LF (on UNIX). You needn't declare extra bytes in the record definition for the record terminator characters because they get added automatically.
By default trailing spaces are stripped before each record in Line Sequential file is written, but you can control this using the STRIPSPACE file handler configuration option.
Line Sequential Files are not designed to represent binary data. The fields in the record description should all be USAGE DISPLAY. This is because a binary field might accidentally contain the bit pattern matching a CR or an LF, which would be misinterpreted as a record delimiter. If you must represent binary data within a Line Sequential File, you can specify the INSERTNULL file handler configuration option, which will insert a NULL i.e. x"00" character before each non-printing character to "escape" it. When the file is read back, the file handler strips these NULLs and preserves the non-printing characters.
Another type of sequential file without headers is a Record Sequential file. This is declared ORGANIZATION RECORD SEQUENTIAL, without the RECORDING MODE clause. It has no headers and also no record delimiters. Every record has the same length, so no headers are needed. Under such conditions, you could declare an extra two bytes in the record description and put CRLF in them before writing each record. In this way, the file would appear to non-COBOL software as a text file, delimited in the usual Windows way with CRLF. Record sequential files can successfully represent binary data because there is no chance any of the data will be misinterpreted as being a record delimiter, since there are no headers or delimiters to begin with.
These are your options. Which one seems to best fit your needs?
Hello.
I'm trying to write variable length records to a SEQUENTIAL file. I don't want the trailing spaces to be removed. I add on two chars at the end of each record type and populate them with CRLF. My results are not what I expected. The output file appears to have binary characters and the rows are not the length of the value in WS-RECORD-LENGTH. My FD statement is:
FD MY-FILE
RECORDING MODE IS V
RECORD IS VARYING IN SIZE FROM 191 TO 370 CHARACTERS DEPENDING ON WS-RECORD-SIZE.
01 MY-RECORD.
05 MY-DATA PIC X(370)
In Working Storage
01 WS-TYPE1. (record length191)
05
05 WS-CRLF1 PIC X(2).
01 WS-TYPE2. (record length 370)
05
05 WS-CRLF2 PIC X(2).
Here's the code to populate the record.
MOVE SPACES TO WS-TYPE1.
MOVE blah blah
MOVE WS-RECORD-DELIMITER TO WS-CRLF1. (has hex values of CRLF)
MOVE 191 TO WS-RECORD-SIZE. (PIC 9(004) COMP)
MOVE WS-TYPE1 TO MY-RECORD.
WRITE MY-RECORD.
Any suggestions will be greatly appreciated
Thanks Chris for the example.
Is there any way to use the file name tag in the EXTFH.CFG with a derived file name? My problem is that the output text file that's created has a file name that consists partly of the current date (e.g. ABCDEFG_CCYYMMDD.txt).
Hello.
I'm trying to write variable length records to a SEQUENTIAL file. I don't want the trailing spaces to be removed. I add on two chars at the end of each record type and populate them with CRLF. My results are not what I expected. The output file appears to have binary characters and the rows are not the length of the value in WS-RECORD-LENGTH. My FD statement is:
FD MY-FILE
RECORDING MODE IS V
RECORD IS VARYING IN SIZE FROM 191 TO 370 CHARACTERS DEPENDING ON WS-RECORD-SIZE.
01 MY-RECORD.
05 MY-DATA PIC X(370)
In Working Storage
01 WS-TYPE1. (record length191)
05
05 WS-CRLF1 PIC X(2).
01 WS-TYPE2. (record length 370)
05
05 WS-CRLF2 PIC X(2).
Here's the code to populate the record.
MOVE SPACES TO WS-TYPE1.
MOVE blah blah
MOVE WS-RECORD-DELIMITER TO WS-CRLF1. (has hex values of CRLF)
MOVE 191 TO WS-RECORD-SIZE. (PIC 9(004) COMP)
MOVE WS-TYPE1 TO MY-RECORD.
WRITE MY-RECORD.
Any suggestions will be greatly appreciated
Thanks Dan for the great explanation.
The text file(s) created is sent to several different client sites and I have no idea what programs are processing them. What I'm trying to accomplish is use one SELECT statement for a file that is to be used to generate three different output text files. I open and close the file three times so that works well. File one created has records that are 100 chars long, file two records are 200 chars long and file three records are 300 chars long. Previously I used the ORGANIZATION LINE SEQUENTIAL mode and that worked fine since the users did not complain about the variable length records (spaces at the end being truncated). However, a new client has requested that the records be fixed length.
Since I need to get the change out the door quickly I landed up with three SELECT statements but would really like to be able to work it the original way I planned to. The individual file name in the EXTFH.CFG seems to be the way to go but I need to be able to use a file name that's created on the fly.
Hello.
I'm trying to write variable length records to a SEQUENTIAL file. I don't want the trailing spaces to be removed. I add on two chars at the end of each record type and populate them with CRLF. My results are not what I expected. The output file appears to have binary characters and the rows are not the length of the value in WS-RECORD-LENGTH. My FD statement is:
FD MY-FILE
RECORDING MODE IS V
RECORD IS VARYING IN SIZE FROM 191 TO 370 CHARACTERS DEPENDING ON WS-RECORD-SIZE.
01 MY-RECORD.
05 MY-DATA PIC X(370)
In Working Storage
01 WS-TYPE1. (record length191)
05
05 WS-CRLF1 PIC X(2).
01 WS-TYPE2. (record length 370)
05
05 WS-CRLF2 PIC X(2).
Here's the code to populate the record.
MOVE SPACES TO WS-TYPE1.
MOVE blah blah
MOVE WS-RECORD-DELIMITER TO WS-CRLF1. (has hex values of CRLF)
MOVE 191 TO WS-RECORD-SIZE. (PIC 9(004) COMP)
MOVE WS-TYPE1 TO MY-RECORD.
WRITE MY-RECORD.
Any suggestions will be greatly appreciated
You can do this on the fly file naming if you assign the file to an environment variable and then set the variable from within the program.
select my-file assign to external myvariable
organization is line sequential
file status is file-status.
display "MYVARIABLE" upon environment-name
display "newfile.txt" upon environment-value
open output my-file
In the extfh.cfg file you would specify the following:
[XFH-DEFAULT]
BASENAME=ON
[INTERNAL:myvariable]
STRIPSPACE=OFF
So whatever MYVARIABLE is set to when the file is opened will be used as the name of the file and the stripspace=off will take effect.
Hello.
I'm trying to write variable length records to a SEQUENTIAL file. I don't want the trailing spaces to be removed. I add on two chars at the end of each record type and populate them with CRLF. My results are not what I expected. The output file appears to have binary characters and the rows are not the length of the value in WS-RECORD-LENGTH. My FD statement is:
FD MY-FILE
RECORDING MODE IS V
RECORD IS VARYING IN SIZE FROM 191 TO 370 CHARACTERS DEPENDING ON WS-RECORD-SIZE.
01 MY-RECORD.
05 MY-DATA PIC X(370)
In Working Storage
01 WS-TYPE1. (record length191)
05
05 WS-CRLF1 PIC X(2).
01 WS-TYPE2. (record length 370)
05
05 WS-CRLF2 PIC X(2).
Here's the code to populate the record.
MOVE SPACES TO WS-TYPE1.
MOVE blah blah
MOVE WS-RECORD-DELIMITER TO WS-CRLF1. (has hex values of CRLF)
MOVE 191 TO WS-RECORD-SIZE. (PIC 9(004) COMP)
MOVE WS-TYPE1 TO MY-RECORD.
WRITE MY-RECORD.
Any suggestions will be greatly appreciated
Awesome!! That's what I was looking for. Thank you.