Selective file copy: Difference between revisions
Content added Content deleted
(Go solution) |
(Added COBOL) |
||
Line 5: | 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>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>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''. |
<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}}== |
=={{header|Go}}== |