Jump to content

Selective file copy: Difference between revisions

Added COBOL
(Go solution)
(Added COBOL)
Line 5:
<br>Here, a file is not 'just' a sequence of bytes or lines but a sequence of ''recods'' (structured data). The structure is usually described by declarations contained in an ''INCLUDE'' file (PL/I) or ''COPY BOOK'' (COBOL).
<br>The ''by name'' assignment is a little extra available in PL/I.
<br>Data conversions may be necessary (as shown here for data element ''c'' in the Go listing).
 
=={{header|COBOL}}==
Seeing as this task mentioned COBOL, here is a sample, but there is no JSON
involved, just a simple data record layout and a MOVE CORRESPONDING.
 
{{works with|GnuCOBOL}}
 
This is GnuCOBOL on a GNU/Linux system, so let's start with a text file, field A
through D, 5 bytes each, 21 character lines, counting the newline, converted
into a more COBOLish fixed length form of 20 bytes per record with no newlines.
 
<pre>
prompt$ cat selective-input-file.txt
A B 0001+D
AA BB 0002+DD
AAA BBB 0003+DDD
AAAA BBBB 0004-DDDD
AAAAABBBBB0005-DDDDD
 
prompt$ $ dd if=selective-input-file.txt of=selective-input-file cbs=20 conv=block
0+1 records in
0+1 records out
100 bytes (100 B) copied, 0.000451344 s, 222 kB/s
</pre>
 
There are no newlines in the SEQUENTIAL access file now; just 5, 20 byte
records. The numeric field-c is explained below.
 
'''copy books'''
In the selective-copy.cob example, instead of some COPY directives with input
and output record layout copy books, an inline REPLACE directive is used
instead, to keep the source file encapsulated. The data between the "=="
markers after the REPLACE BY phrase would normally be saved in a separate file,
and read in during compile with '''COPY filename'''. Those copy books could
then be used by any source module that would need the record layout. In this
example, the :INPUT-RECORD: and :OUTPUT-RECORD: pseudo-text markers are where
the COPY directives would be placed.
 
Far more complicated record hierarchies can be created with COBOL data level
groupings than the one demonstrated here. Every larger level number becomes a
group to all the ''higher in the hierarchy'' lower valued level numbers. Each
new level can be treated as entire groups of fields, or separately down at the
highest numbered elementary items. Levels from 01 to 49 can be used to create
data record layouts, with subscripted repeats (arrays) allowed at almost all
levels. In this example only levels 01, and 05 are used.
 
<lang COBOL>
01 ws-input-record.
:INPUT-RECORD:
</lang> will become
 
<lang COBOL>
01 ws-input-record.
05 field-a pic x(5).
05 field-b pic x(5).
05 field-c pic s9(5).
05 field-d pic x(5).
</lang> after the REPLACE preprocessor directive is finished.
 
And finally, the example selective-copy.cob
<lang COBOL>
*> Tectonics:
*> cobc -xj selective-copy.cob
*> cobc -xjd -DSHOWING selective-copy.cob
*> ***************************************************************
identification division.
program-id. selective-copy.
 
environment division.
configuration section.
repository.
function all intrinsic.
 
input-output section.
file-control.
select input-file
assign to input-filename
organization is sequential
status is input-status.
 
select output-file
assign to output-filename
organization is sequential
status is output-status.
 
*> emulate a COPY book, with an inline REPLACE
 
REPLACE ==:INPUT-RECORD:== BY
==
05 field-a pic x(5).
05 field-b pic x(5).
05 field-c pic s9(4) sign is trailing separate.
05 field-d pic x(5).
==
 
==:OUTPUT-RECORD:== BY
==
05 field-a pic x(5).
05 field-c pic ----9.
05 field-x pic x(5).
==.
 
data division.
file section.
fd input-file.
01 fd-input-record.
:INPUT-RECORD:
 
fd output-file.
01 fd-output-record.
:OUTPUT-RECORD:
 
working-storage section.
01 input-filename.
05 filler value "selective-input-file".
01 input-status pic xx.
88 ok-input values '00' thru '09'.
88 eof-input value '10'.
01 ws-input-record.
:INPUT-RECORD:
 
01 output-filename.
05 filler value "selective-output-file".
01 output-status pic xx.
88 ok-output values '00' thru '09'.
88 eof-output value '10'.
01 ws-output-record.
:OUTPUT-RECORD:
 
77 file-action pic x(11).
 
77 math pic s9(5).
 
*> ***************************************************************
procedure division.
main-routine.
perform open-files
 
perform read-input-file
perform until eof-input
>>IF SHOWING IS DEFINED
display "input :" ws-input-record ":"
>>END-IF
move corresponding ws-input-record to ws-output-record
move "XXXXX" to field-x in ws-output-record
perform write-output-record
perform read-input-file
end-perform
perform close-files
goback.
*> ***************************************************************
open-files.
open input input-file
move "open input" to file-action
perform check-input-file
 
open output output-file
move "open output" to file-action
perform check-output-file
.
 
*> **********************
read-input-file.
read input-file into ws-input-record
move "reading" to file-action
perform check-input-with-eof
.
 
*> **********************
write-output-record.
write fd-output-record from ws-output-record
move "writing" to file-action
perform check-output-file
>>IF SHOWING IS DEFINED
display "output :" ws-output-record ":"
>>END-IF
.
 
*> **********************
close-files.
close input-file output-file
perform check-input-with-eof
perform check-output-file
.
 
*> **********************
check-input-file.
if not ok-input then
perform input-file-error
end-if
.
 
*> **********************
check-input-with-eof.
if not ok-input and not eof-input then
perform input-file-error
end-if
.
 
*> **********************
input-file-error.
display "error " file-action space input-filename
space input-status upon syserr
move 1 to return-code
goback
.
 
*> **********************
check-output-file.
if not ok-output then
display "error " file-action space output-filename
space output-status upon syserr
move 1 to return-code
goback
end-if
.
 
end program selective-copy.</lang>
 
The output file has no newlines, so normal '''cat''' type commands are not of
much use, so we turn to the '''dd''' command again, this time with an
''unblock'' conversion.
 
{{out}}
<pre>
prompt$ cobc -xj selective-copy.cob
prompt$ dd if=selective-output-file cbs=15 conv=unblock
A 1XXXXX
AA 2XXXXX
AAA 3XXXXX
AAAA -4XXXXX
AAAAA -5XXXXX
0+1 records in
0+1 records out
80 bytes (80 B) copied, 0.000173387 s, 461 kB/s
</pre>
 
80 bytes output, 5 records of 15 bytes each, with a newline added to each of
the 5 records. The '''dd''' option ''status=none'' will turn off the
statistics report, making the output more '''cat''' like, just showing the
records as lines of data on standard out.
 
Another wrinkle, is the numeric values in field-c. Normally COBOL will store
USAGE DISPLAY numerics using one byte per digit, with an ''overpunch'' for the
sign of a value, when saving to or reading from disk or memory. A sign bit is
or'ed into one of the digits, either first or last, depending on platform and
compile time options. This can be overridden in source code with SIGN IS
LEADING (or TRAILING) SEPARATE. It was set to TRAILING SEPARATE in this
example. Making for a 4 digit number with a sign field, for the 5 character
field.
 
The output record then converts this field-c input form to a more human
friendly NUMERIC-EDITED format. This version of field-c is no longer NUMERIC
in a disk/memory sense, as the spaces in the field are not numerical values.
Spaces are not digits in COBOL raw form, and are not assumed to be zeroes.
''Financial institutions seem to like it that way''.
 
An alternative would be COMPUTATIONAL (or USAGE BINARY) storage format, in
which case the values would not look like text at all. Just as would happen
when C saves an '''int''' value directly to disk or memory. During terminal
output, with a DISPLAY statement, the numbers look like text, but the memory
representation would be computational bit patterns.
 
=={{header|Go}}==
Anonymous user
Cookies help us deliver our services. By using our services, you agree to our use of cookies.