Opening file for reading in COBOL - cobol

I'm using OpenCobolIDE 4.7.4 (it's based on GnuCOBOL) on Windows 10 and trying to compile this program opening a file for reading:
IDENTIFICATION DIVISION.
PROGRAM-ID. HELLO.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT STUDENT ASSIGN TO 'input.txt'
ORGANIZATION IS LINE SEQUENTIAL.
DATA DIVISION.
FILE SECTION.
FD STUDENT.
01 STUDENT-FILE.
05 STUDENT-ID PIC 9(5).
05 NAME PIC A(25).
WORKING-STORAGE SECTION.
01 WS-STUDENT.
05 WS-STUDENT-ID PIC 9(5).
05 WS-NAME PIC A(25).
01 WS-EOF PIC A(1).
PROCEDURE DIVISION.
OPEN INPUT STUDENT.
PERFORM UNTIL WS-EOF='Y'
READ STUDENT INTO WS-STUDENT
AT END MOVE 'Y' TO WS-EOF
NOT AT END DISPLAY WS-STUDENT
END-READ
END-PERFORM.
CLOSE STUDENT.
STOP RUN.
The input.txt is in the same directory as the source coude, yet I'm still getting the following error:
Main.cob:24: libcob: File does not exist (STATUS = 35) File : 'input.txt'
What am I doing wrong?

OCIDE has a setting for the output directory, the default is "bin" (relative to the source file). Effectively it just passes this setting to the compiler cobc source.cob -o bin\source.exe
You can change this behaviour in settings Menu Preferences -> Compiler:
Output directory
This option let you chose where to put the binaries, by default binaries will be placed into a bin folder next to the source file. You can define another relative or absolute directory if you want.
In any case you can set the actual name in the environment, check GC FAQ - How to map a file name to an external name.
As an alternative you can set the data directory with the environment var COB_FILE_PATH.
Both environment options can be set in settings Menu Preferences -> Run.

Most IDE for other languages happen to run the executable from another directory (where it is built for example).
A simple test is to write a test program, opening a file for writing.
You'll quickly see what happens.

Perhaps better will be to write the full path in the select clause.
select STUDENT ASSIGN TO '/xpto/folder1/input.txt'

Related

Reusing the file definition of one file for another with out opening /closing it

Reusing the file definition of file1 for another i.e file2 with out opening /closing file1.
I have a monthly file and my requirement is generate a daily file similar to monthly file.The record length and the File definition of both the files are same.
Can i make use of monthly file's FD to hold data and do some validation using monthly file data items for my Daily file and write my daily file later?
lot of validations are being done using monthly file's FD variables and I cannot do same validations using daily file's variables as i need to make changes/rewrite lot of code in many places in multiple programs.
Note: I am doing my daily file processing & generation after the monthly processing is over at the end .
Also ,we are using UNIX environment.
Please suggest me how can i achieve this if above mentioned method is not possible.
The record area for a file is not available until the file is opened. The SAME RECORD AREA clause may be used to provide an alias.
identification division.
program-id. srac.
environment division.
input-output section.
file-control.
select optional monthly-file assign "monthly.dat"
file status monthly-stat.
select daily-file assign "daily.dat"
file status daily-stat.
i-o-control.
same record area monthly-file daily-file.
data division.
file section.
fd monthly-file.
1 monthly-id pic 999.
fd daily-file.
1 daily-id pic 999.
working-storage section.
1 monthly-stat pic x(2).
1 daily-stat pic x(2).
procedure division.
open input monthly-file daily-file
display "monthly-stat:" space monthly-stat
display "daily-stat: " space daily-stat
read daily-file
display "monthly-id:" space monthly-id
if monthly-id < 10
add 100 to monthly-id
end-if
display "daily-id: " space daily-id
close monthly-file daily-file
stop run
.
monthly-stat: 05
daily-stat: 00
monthly-id: 001
daily-id: 101
In this example, the monthly and daily files have identical record description entries; but, the monthly file does not exist. Yet, one may use the data-names for the monthly file for validation, modification, or whatever.

Cobol: cannot find entry point of a text file

Hi i am learning cobol from tutorialpoints and every program from there works as i've tested them in OpenCobolIDE(some needed a little editing). Then i came across the File Handling chapter and in there the program had a lot of errors. I did manage to rewrite the program until it didn't show me any errors but it doesn't do anything.
Here's my code:
IDENTIFICATION DIVISION.
PROGRAM-ID. HELLO.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT STUDENT ASSIGN TO
'C:\Cobol\FIle Handling\input.txt'
ORGANIZATION IS INDEXED
ACCESS IS RANDOM
RECORD KEY IS STUDENT-ID
FILE STATUS IS FS.
DATA DIVISION.
FILE SECTION.
FD STUDENT.
01 STUDENT-FILE.
05 STUDENT-ID PIC 9(5).
05 NAME PIC A(25).
WORKING-STORAGE SECTION.
01 WS-STUDENT-FILE.
05 WS-STUDENT-ID PIC 9(5).
05 WS-NAME PIC A(25).
01 FS PIC 9(02).
PROCEDURE DIVISION.
OPEN I-O STUDENT.
MOVE 20005 TO STUDENT-ID.
READ STUDENT RECORD INTO WS-STUDENT-FILE
KEY IS STUDENT-ID
INVALID KEY DISPLAY 'Invalid Key'
NOT INVALID KEY DISPLAY WS-STUDENT-FILE
END-READ.
CLOSE STUDENT.
STOP RUN.
This is the text file:
20003 Mohtashim M.
20004 Nishant Malik
20005 Amitabh Bachhan
The result should be the text:
20005 Amitabh Bachhan
It's doing something: It's reading the file. But that's all; you didn't ask for it to display or do anything else beyond reading the record into memory. You might want to look at using the DISPLAY statement or maybe create another file to write the output to.
Might I make a couple of suggestions?
In modern COBOL, stylistically, you don't put a period after everything in the procedure division -- you only put it in where it is necessary. For example:
PROCEDURE DIVISION.
OPEN I-O STUDENT
MOVE 20005 TO STUDENT-ID
READ STUDENT RECORD INTO WS-STUDENT-FILE
KEY IS STUDENT-ID
INVALID KEY DISPLAY 'Invalid Key'
NOT INVALID KEY DISPLAY WS-STUDENT-FILE
END-READ
CLOSE STUDENT
STOP RUN
.
Although the compiler doesn't care about spaces and returns, if I were you, I'd try to indent my code a bit better (I like how I indented the above :-) ). It's up to you and a lot of people like to do it differently, but if you are consistent you can spot problems that might sneak through your code.
Edit: I didn't notice that you were reading with a key from a text file. So, either you need to:
read from a pre-built indexed file, or
read the file sequentially and search for what you want by comparing what you read for the student id you wanted.

Open an cobol index-sequential file with the file name in a variable

I use Microfocus Net Express 5.1 (Cobol).
When I want to open an index-sequential file I write
open input xyzfile
My question is: Is there somehow a possibility to put the name "xyzfile" in variable an write instead
move "xyzfile" to var-file
open input var-file
Thanks alot in advance
from environment division;
environment division.
input-output section.
file-control.
select ConfigFile
assign to wFile-folder
organization is line sequential
file status is wStatus.
from working-storage section;
working-storage section.
01 wFile-folder pic x(256).
01 wStatus pic x(2).
and under your procedure division;
move "c:\data\configuration.txt" to wFile-folder
open input ConfigFile
read ConfigFile record

Programs hangs when opening COBOL Indexed file

I've recently started a COBOL course and, because of my computer configuration (Windows 7 64 Bits and GNU/Linux 64Bits) I have to use Dosbox to compile and execute programs.
Everything is going well but, I'n finding some troubles when I try to open an Indexed file, either I-O or Ouput mode. I can compile and link but at execution time, dosbox get frozen.
My compiler version is MS-COBOL 5.0 and DosBox is 0.74 (last version).
Does anybody have had this issue? Can someone tell how to fix it.
My code is this one.
Thanks in advance.
IDENTIFICATION DIVISION.
PROGRAM-ID. AGENDA.
AUTHOR. JOSE MARIA RAMIREZ MIRA.
DATE-WRITTEN. 06/05/2014.
DATE-COMPILED. 06/05/2014.
ENVIRONMENT DIVISION.
CONFIGURATION SECTION.
SOURCE-COMPUTER. IBM-PC.
OBJECT-COMPUTER. IBM-PC.
SPECIAL-NAMES.
DECIMAL-POINT IS COMMA.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT AGENDA ASSIGN TO DISK "AGENDA.DAT"
ORGANIZATION IS INDEXED
ACCESS IS RANDOM
RECORD KEY IS AG-NICK
FILE STATUS IS AG-STATUS.
DATA DIVISION.
FILE SECTION.
FD AGENDA
RECORD CONTAINS 112 CHARACTERS
LABEL RECORD IS STANDARD
DATA RECORD IS AG-PERSONA.
01 AG-PERSONA.
03 AG-NICK PIC X(25).
03 AG-NOMBRE PIC X(25).
03 AG-APELLIDOS PIC X(50).
03 AG-TELEFONO PIC X(12).
WORKING-STORAGE SECTION.
77 AG-STATUS PIC 99.
88 EXITO VALUE 00.
88 CLAVE-DUPLICADA VALUE 22.
88 CLAVE-NO-ENCONTRADA VALUE 23.
88 SIN-ESPACIO-EN-DISCO VALUE 34.
88 FICHERO-NO-EXISTE VALUE 35.
88 EOF VALUE 10.
PROCEDURE DIVISION.
MAIN-PROCEDURE.
DISPLAY "PROCEDO A ABRIR EL ARCHIVO".
OPEN I-O AGENDA.
IF EXITO THEN
DISPLAY "EL ARCHIVO SE HA ABIERTO"
ELSE
EVALUATE TRUE
WHEN FICHERO-NO-EXISTE
DISPLAY "EL ARCHIVO NO EXISTE"
END-EVALUATE
END-IF.
CLOSE AGENDA.
STOP RUN.
END PROGRAM AGENDA.
Have you tried selecting the file using the OPTIONAL phrase. For example,
SELECT OPTIONAL AGENDA ASSIGN TO DISK "AGENDA.DAT"
ORGANIZATION IS INDEXED
ACCESS IS RANDOM
RECORD KEY IS AG-NICK
FILE STATUS IS AG-STATUS.
The OPTIONAL phrase must be specified for files opened for INPUT, I-O, or EXTEND that need not be present when the program runs.
Against this being the problem is your statement that the problem also occurs with OPEN OUTPUT and the program should in any case be producing some output but as others have remarked the version of COBOL is not well known.
By the way I plugged your program into the online COBOL at http://www.compileonline.com/compile_cobol_online.php
and it worked fine triggering the FICHERO-NO-EXISTE condition name.
But this does raise another point. In my Microfocus manual the file status code of 35 is given as being returned when an OPEN INPUT, I-O or EXTEND is attempted on a NON-OPTIONAL file that does not exist. A file status of 05 is returned if you have used the OPTIONAL phrase and the file does not exist at the time the OPEN is executed.
What is the absolute path to AGENDA.DAT?
Sometimes with legacy DOS programs you can't read/write files inside folders with spaces on its name. Say, if your current folder is C:\ms cobol\ , rename it to C:\mscobol\.
It's worth a try, if this is your case.
DOSBox was designed for gaming.
The problem could be DOSBox missing file and record locking.
DOSBox has more issues like internal file caching, a time bomb with multi-user enabled programs.
You could try vDos: http://sourceforge.net/projects/vdos/.
It is Windows only, but integrates better with it.

Is there a way to parameterize functions in COBOL?

I'm coding routines like:
READ-A.
READ FILE-A
AT END
MOVE 1 TO EOF-A
NOT AT END
ADD 1 TO CN-READ-A
END-READ.
F-READ-A. EXIT.
to read several files and I was wondering if there's a way to code a routine that is able to read the filename from a variable so I don't have to code the same thing for each file. Thanks!
One solution as said above is to use multiple programs or nested program, for which
I have included an example below, which is solution 1.
Another solution is to COBOL classes, which might not be to your liking but I like them, so I've included an example, which is solution 2.
Solution 1:
program-id. TestProgram.
working-storage section.
01 file-name pic x(128).
01 file-lines pic 9(9).
procedure division.
move 0 to file-lines
move "d:\rts_win32.txt" to file-name
call "program1" using file-name file-lines
display file-lines
stop run
end program TestProgram.
program-id. Program1.
file-control.
select file-a assign to myfile
organization is line sequential.
data division.
fd file-a.
01 file-a-line pic x(80).
working-storage section.
01 EOF-A pic 9 value 0.
linkage section.
01 lk-filename pic x(128).
01 CN-READ-A pic 9(9).
procedure division using lk-filename
CN-READ-A.
move lk-filename to myfile
open input file-a
perform READ-A until EOF-A equals 1
close file-a
goback.
READ-A.
READ FILE-A
AT END
MOVE 1 TO EOF-A
NOT AT END
ADD 1 TO CN-READ-A
END-READ.
F-READ-A.
EXIT.
end program Program1.
Solution 2
program-id. TestProgram.:
working-storage section.
01 file-counter type FileLineCounter.
procedure division.
set file-counter to new type FileLineCounter("d:\rts_win32.txt")
display file-counter::LineCount
stop run
end program TestProgram.
class-id FileLineCounter.
file-control.
select file-a assign to myfile
organization is line sequential.
data division.
fd file-a.
01 file-a-line pic x(80).
working-storage section.
01 cn-read-a binary-long property as "LineCount".
method-id New.
01 EOF-A pic 9 value 0.
procedure division using by value filename as string.
set myfile to filename
open input file-a
perform READ-A until EOF-A equals 1
close file-a
goback.
READ-A.
READ FILE-A
AT END
MOVE 1 TO EOF-A
NOT AT END
ADD 1 TO CN-READ-A
END-READ.
F-READ-A.
EXIT.
end method.
end class.
May not be "in the wild" yet with compiler support, but the current ISO Draft 20xx standard includes FUNCTION-ID in place of PROGRAM-ID. It adds a parameter friendly function call computing paradigm to COBOL.
Might not help today, but maybe in the near future. If I'm not mistaken, User Defined Functions are actually from the COBOL 2002 spec, but it seems compiler vendors are hit or miss on support for the feature.
FUNCTION-ID support is in closed trials for OpenCOBOL 2.0, but the timeline for the 2.0 release is undetermined and could be another year or more before it's made public.
The proper Cobol way to parameterize routines is via the nested subprogram.
You can do what you want, but it is dependant upon your compiler and environment, you can pass a file, or a file name, or a DDname.
What platform are you on?
Edit: On z/OS, you can change what FILE-A points to at runtime using putenv() to adjust the dataset name associated with the DDNAME that FILE-A uses.
See:
http://ibmmainframes.com/post-57281.html
http://cicswiki.org/cicswiki1/index.php?title=How_do_I_allocate_a_file_dynamically_using_COBOL%3F
You will need a OPEN-A and CLOSE-A paragraph as well between switching files.
It isn't exactly passing parameters to your read statement, but it lets you reuse your OPEN/READ/WRITE/CLOSE statements for different files. But only serially.
There was a way, under VS COBOL II, where you could pass an FD to a subprogram, that would look something like:
CALL MYREADPGM USING FILE-A
CALL MYREADPGM USING FILE-B
This possible with Enterprise Cobol but IIRC VisualAge does not support that.
I realize this is an old thread, but hopefully someone might find this useful in the future: IBM's Enterprise COBOL on z/OS 6.4 compiler supports user-defined functions (released May 2022). User-defined functions could be a useful alternative to the other suggestion for internal programs. In contrast to program calls, there are compile time checks for parameters to user-defined function invocations. Also, you can invoke the function in a lot of places where you couldn't call a program, like within a
n expression.
Here's an example based on passing a file name to a function. It might be possible to combine this with the PUTENV() suggestion above.
IDENTIFICATION DIVISION.
FUNCTION-ID. READ-FILE.
DATA DIVISION.
LINKAGE SECTION.
1 FILE-NAME PIC X(50).
1 RET PIC 9(9).
PROCEDURE DIVISION USING FILE-NAME RETURNING RET.
* DO STUFF WITH FILE-NAME
* ...
GOBACK
.
END FUNCTION READ-FILE.
IDENTIFICATION DIVISION.
PROGRAM-ID. MAINPROG.
DATA DIVISION.
WORKING-STORAGE SECTION.
1 READ-RESULT PIC 9(9).
PROCEDURE DIVISION.
COMPUTE READ-RESULT = FUNCTION READ-FILE('MYINPUTFILE')
GOBACK
.
END PROGRAM MAINPROG.
More examples can be found in the Programming Guide Chapter 32 Using user-defined functions.
https://www.ibm.com/support/pages/enterprise-cobol-zos-documentation-library#Table642
You could create a data file of filenames, treat each one as an individual record, and then read each file. In the "SELECT ...ASSIGN" you would need to use a working-storage variable for the filename and move the value from the 'file of filenames' into it.
As you are using VisualAge, I assume in UNIX, you might also be able to run the program from the shell (sh,ksh), with the filename as a parameter, and repeatedly run the program from the shell for each file name.

Resources