Focal Point
[SOLVED] Fixed length records in text file

This topic can be found at:
https://forums.informationbuilders.com/eve/forums/a/tpc/f/7971057331/m/7547092995

February 24, 2011, 05:03 PM
vaidyasundar
[SOLVED] Fixed length records in text file
I have variable length records but when I write to txt file I want to write as fixed length records padding with spaces and I have to use -WRITE command.

Sample code:

-SET &LINE1 = 'This is Line 1';
-SET &LINE2 = 'This Line 2';
-RUN
APP FI TESTFILE DISK BASEAPP/test.txt (APPEND LRECL 200 RECFM F
-RUN
-WRITE TESTFILE &LINE1
-WRITE TESTFILE &LINE2
-RUN

This code gives me fixed length records but when I see result file I see both records are written in the same line whereas I need as separate lines and each line with 200 characters padded with spaces. I do not want to use TABLE FILE and I dont have to use mas files.
Any help will be appreciated. Thanks for your help.

using WFv7.6.10

This message has been edited. Last edited by: Kerry,


WebFOCUS 7.6.10
UNIX, WINDOWS
PDF, HTML, Text
February 25, 2011, 06:27 AM
Alan B
Had this problem last year. This, very untidy approach, was all I could come up with to get it to work.

-SET &LINE1 = 'This is Line 1';
-SET &LINE2 = 'This Line 2';
-RUN
APP FI TESTFILE DISK baseapp/test.txt (LRECL 200 RECFM F
-RUN
-WRITE TESTFILE &LINE1
APP FI TESTFILE DISK baseapp/test.txt (APPEND LRECL 0
-RUN
-WRITE TESTFILE 
APP FI TESTFILE DISK baseapp/test.txt (APPEND LRECL 200 RECFM F
-RUN
-WRITE TESTFILE &LINE2
-RUN



Alan.
WF 7.705/8.007
February 25, 2011, 08:41 AM
jgelona
See if using the NOCLOSE option on the -WRITE. In the following, I built a SAVE file that is 220 characters. I need the last 200 characters of each row for my final output file.

 FILEDEF FMFCNEW DISK &FNCDIR..fmfcext.new ( LRECL 200 RECFM V
-RUN
-LOOP
-READ SAVE NOCLOSE &X.A20. &DATAREC.A200.
-IF &IORETURN NE 0 THEN GOTO EXITLOOP;
-WRITE FMFCNEW NOCLOSE &DATAREC
-GOTO LOOP
-*
-EXITLOOP
-CLOSE *


In this case there is an end of record character in position 200 to insure each row is 200 characters long.


In FOCUS since 1985. Prod WF 8.0.08 (z90/Suse Linux) DB (Oracle 11g), Self Serv, Report Caster, WebServer Intel/Linux.
February 25, 2011, 11:46 AM
vaidyasundar
Sorry Alan, I did not like your approach of using APP FI command for every write command. If I have to write 100 lines then think about it. Also, the length of lines are not consistent, so sorry.

Sorry jgelona, your solution also will not solve my problem since I dont have SAVE file and I don't need to create one as well.

I am expecting that there should be a straight forward way of doing it.


WebFOCUS 7.6.10
UNIX, WINDOWS
PDF, HTML, Text
February 27, 2011, 04:19 PM
Waz
Here is one way I can think of doing this.

-SET &LINE1 = 'This is Line 1';
-SET &LINE2 = 'This Line 2';
-SET &CRLF  = HEXBYT(13,'A1') | HEXBYT(10,'A1') ;
-RUN
APP FI TEST200 DISK BASEAPP/test.txt (LRECL 200 RECFM F
-RUN
-WRITE TEST200 &LINE1

APP FI TEST202 DISK BASEAPP/test.txt (APPEND LRECL 202 RECFM F
-RUN
-WRITE TEST202 &CRLF&LINE2

-RUN


If this is run on something other tha windoes, then it will have to change.


Waz...

Prod:WebFOCUS 7.6.10/8.1.04Upgrade:WebFOCUS 8.2.07OS:LinuxOutputs:HTML, PDF, Excel, PPT
In Focus since 1984
Pity the lost knowledge of an old programmer!

February 28, 2011, 02:57 PM
jgelona
vaidyasundar, my solution will work just fine. Get creative and use some brain cells. The key to my solution is to use NOCLOSE with -WRITE. It does not require a SAVE file.

 APP FI TESTFILE DISK baseapp/test.txt ( LRECL 200 RECFM V APPEND
-RUN
-SET &LINECNT=0;
-SET &BL50='                                                  ';
-SET &BL200=&BL50 | &BL50 | &BL50 | &BL50;
-REPEAT ENDLOOP 100 TIMES
-SET &LINECNT=&LINECNT+1;
-SET &LINE='This is Line ' | &LINECNT | &BL200;
-SET &LINE=OVRLAY(&LINE,200,'X',1,200,'A200');
-SET &LINE=SUBSTR(&LINE.LENGTH,&LINE,1,200,200,'A200');
-WRITE TESTFILE NOCLOSE &LINE
-ENDLOOP



In FOCUS since 1985. Prod WF 8.0.08 (z90/Suse Linux) DB (Oracle 11g), Self Serv, Report Caster, WebServer Intel/Linux.
February 28, 2011, 03:41 PM
jgelona
While you don't want to use TABLE/TABLEF you might consider using them with a MACGYVER file.
Here's the fex:
 APP HOLD baseapp
 TABLE FILE MACGYVER
 PRINT COMPUTE LINE/A200='This is line ' | EDIT(COUNTER);
 WHERE COUNTER LE 100
    ON TABLE SET HOLDLIST PRINTONLY
    ON TABLE SAVE AS TESTFILE
 END


One cannot get much more straight forward than that.

Here's the master and code to build the MacGyver file. We keep them in the baseapp folder. We have dozens of jobs that use the MacGyver file.:

FILE=MACGYVER,SUFFIX=FOC
SEGNAME=MAC1,SEGTYPE=S1
  FIELD=BLANK  ,     ,A1,INDEX=I,$
SEGNAME=MAC2,SEGTYPE=S1,PARENT=MAC1
  FIELD=COUNTER,ORDER,I4,$


-* File loadmac.fex
-*
-* Build MACGYVER.FOC
-*
-DEFAULT &HOWMANY=366;
 CREATE FILE MACGYVER
 MODIFY FILE MACGYVER
 COMPUTE CTR/I9=;
 FIXFORM &HOWMANY(CTR/4 X-4)
 COMPUTE
   BLANK=' ';
   COUNTER=IF COUNTER EQ 0 THEN CTR ELSE COUNTER+1;
 MATCH BLANK
    ON MATCH CONTINUE
    ON NOMATCH INCLUDE
 MATCH COUNTER
    ON MATCH CONTINUE
    ON NOMATCH INCLUDE
 DATA
1
 END
-RUN



In FOCUS since 1985. Prod WF 8.0.08 (z90/Suse Linux) DB (Oracle 11g), Self Serv, Report Caster, WebServer Intel/Linux.
February 28, 2011, 06:30 PM
vaidyasundar
jgelona, again sorry that I don't see your solution meet my expectation.
To get your suggested solution, All your code can be shortened to one line like SUBSTR(&LINE.LENGTH,&LINE,1,&LINE.LENGTH,199,'A199')|X;
However, you do not understand the problem; your solution is printing the unwanted character X at position 200. This means you are asking me to change the requirement instead of providing good solution.
I knew already that TABLE FILE will work but I wanted to make it work with -WRITE command, because TABLE FILE will have I/O hit every time and it will be expensive operation for my requirement.


WebFOCUS 7.6.10
UNIX, WINDOWS
PDF, HTML, Text
March 01, 2011, 09:41 AM
Francis Mariani
A little less rudeness will go a long way.


Francis


Give me code, or give me retirement. In FOCUS since 1991

Production: WF 7.7.05M, Dev Studio, BID, MRE, WebSphere, DB2 / Test: WF 8.1.05M, App Studio, BI Portal, Report Caster, jQuery, HighCharts, Apache Tomcat, MS SQL Server
March 01, 2011, 01:24 PM
jgelona
vaidyasundar, you do not seem to understand what I am saying.

To use the -WRITE command you will need to use the NOCLOSE option.

With RECFM=F, you will not get the CRLF (Windows) or LF (Unix) to terminate a line so you will have to add it.

This works on a Linux Reporting Server.
 APP FI TESTFILE DISK baseapp/test.txt ( LRECL 201 RECFM F
-RUN
-SET &LINECNT=0;
-SET &LF=HEXBYT(10,'A1');
-REPEAT ENDLOOP 100 TIMES
-SET &LINECNT=&LINECNT+1;
-SET &LINE='This is Line ' | &LINECNT;
-SET &LINE=SUBSTR(&LINE.LENGTH,&LINE,1,&LINE.LENGTH,200,'A200') | '&LF.EVAL';
-WRITE TESTFILE NOCLOSE &LINE
-ENDLOOP



In FOCUS since 1985. Prod WF 8.0.08 (z90/Suse Linux) DB (Oracle 11g), Self Serv, Report Caster, WebServer Intel/Linux.
March 01, 2011, 03:42 PM
vaidyasundar
Thank you jgelona. Appreciate your responses. Your last solution is much better than earlier answers and I got similar answer from Waz too. I still don't understand why you are pressing on NOCLOSE option. I don't see any difference in output with or without NOCLOSE. and specification also says, Unless you specify the NOCLOSE option, an opened file is closed upon termination of the procedure with -RUN, -EXIT, or -QUIT. so we are okay.

Actually I wanted a solution for the following problem.

1. Write a header record(1 record) - must
2. Write detail records(multiple records from database table) -optional
3. Write a footer record(1 record) - must

All the records length should be fixed length of 200 characters padded with trailing spaces.
The final output file should be a text file.

So, based on your reply, I got the following solution working fine for the above requirements:

APP FI TESTFILE DISK baseapp/test.txt (LRECL 201 RECFM F
-RUN
-SET &LF=HEXBYT(10,'A1');
-SET &LINE='Header Record, CAR TABLE RUN ON: '|&YYMD;
-SET &LINE=SUBSTR(&LINE.LENGTH,&LINE,1,&LINE.LENGTH,200,'A200')| '&LF.EVAL';
-WRITE TESTFILE NOCLOSE &LINE

APP FI TESTFILE DISK baseapp/test.txt (APPEND LRECL 200 RECFM V
-RUN

TABLE FILE CAR
PRINT
COMPUTE XD_REC/A200 = COUNTRY | CAR | MODEL;
ON TABLE SET HOLDLIST PRINTONLY
ON TABLE SAVE AS TESTFILE FORMAT ALPHA
END

APP FI TESTFILE DISK baseapp/test.txt (APPEND LRECL 201 RECFM F
-RUN

-SET &LINE='Footer Record, CAR TABLE REC COUNT: '|&LINES;
-SET &LINE=SUBSTR(&LINE.LENGTH,&LINE,1,&LINE.LENGTH,200,'A200') | '&LF.EVAL';
-WRITE TESTFILE NOCLOSE &LINE


If you see any problem or any other easy way of doing it, please let me know.
Thank you jgelona and everyone so much for your help. Spl. thanks to jgelona for spending time with this problem.

Vaidya
March 02, 2011, 11:29 AM
jgelona
I thought you weren't going to use TABLE. The problem with this method is that if you change to a Windows or Mainframe Reporting Server, you have to change the code since the line terminator is CRLF in Windows and there isn't one on the Mainframe.

Seeing what you have done, I would have done it like this since this will give the desired results no matter what the report server platform is.

APP FI TESTFILE DISK baseapp/test.txt (LRECL 200 RECFM V
TABLE FILE CAR
PRINT COUNTRY NOPRINT
COMPUTE XD_REC/A200 = 'Header Record, CAR TABLE RUN ON: &YYMD';
IF RECORDLIMIT EQ 1
ON TABLE SET HOLDLIST PRINTONLY
ON TABLE SAVE AS TESTFILE
END
APP FI TESTFILE DISK baseapp/test.txt (APPEND LRECL 200 RECFM V
TABLE FILE CAR
PRINT 
COMPUTE XD_REC/A200 = COUNTRY | CAR | MODEL; 
ON TABLE SET HOLDLIST PRINTONLY
ON TABLE SAVE AS TESTFILE
END
-RUN
-SET &CARLINES=&LINES;
TABLE FILE CAR
PRINT COUNTRY NOPRINT
COMPUTE XD_REC/A200 = 'Footer Record, CAR TABLE REC COUNT: &CARLINES';
IF RECORDLIMIT EQ 1
ON TABLE SET HOLDLIST PRINTONLY
ON TABLE SAVE AS TESTFILE
END
-RUN



In FOCUS since 1985. Prod WF 8.0.08 (z90/Suse Linux) DB (Oracle 11g), Self Serv, Report Caster, WebServer Intel/Linux.
March 02, 2011, 11:48 AM
vaidyasundar
quote:
APP FI TESTFILE DISK baseapp/test.txt (LRECL 200 RECFM V
TABLE FILE CAR
PRINT COUNTRY NOPRINT
COMPUTE XD_REC/A200 = 'Header Record, CAR TABLE RUN ON: &YYMD';
IF RECORDLIMIT EQ 1
ON TABLE SET HOLDLIST PRINTONLY
ON TABLE SAVE AS TESTFILE
END


Thank you jgelona again. I first tried exactly the same way how you did here. But, then I thought, in this way, we are hitting database or file system unnecessarily for header and trailor records and it would impact performance because I need to create 10 different files like this within a batch process and each file will have several thousands of rows and performance is the key factor for us.

Thanks
vaidya
March 03, 2011, 09:23 AM
jgelona
My guess is that if you timed it, there would be no measureable difference in performance. If you use a file (like the CAR file) that lives on the Reporting Server, then you are not hitting any database and there is no network traffic


In FOCUS since 1985. Prod WF 8.0.08 (z90/Suse Linux) DB (Oracle 11g), Self Serv, Report Caster, WebServer Intel/Linux.
March 03, 2011, 11:31 AM
vaidyasundar
Good point John. But, For now, I have convinced my user that there will be a dot(.) character at the end of header and trailer records so that I can simply use SUBSTR(&LINE.LENGTH,&LINE,1,&LINE.LENGTH,200,'A200')|. with just one time file allocation with RECFM V. If they don't agree then I will consider the other options you provided.

Thank you so much John for working with me on this issue. I have learnt many techniques. I appreciate your help.

Thanks
vaidya


WebFOCUS 7.6.10
UNIX, WINDOWS
PDF, HTML, Text