I have an ASCII file that looks like:
____________________________________________
Header1 ...
Header2 ...
Header3 ...
block(1)data1 block(1)data2 block(1)data3
block(1)data4 block(1)data5 block(1)data6
block(2)data1 block(2)data2 block(2)data3
block(2)data4 block(2)data5 block(2)data6
...
block(n)data1 block(n)data2 block(n)data3
block(n)data4 block(n)data5 block(n)data6
____________________________________________
I would like to convert it into an ASCII file that looks like:
____________________________________________
HeaderA ...
HeaderB ...
block(n)data1 block(n)data2 block(n)data3
block(n)data4 block(n)data5 block(n)data6
block(n-1)data1 block(n-1)data2 block(n-1)data3
block(n-1)data4 block(n-1)data5 block(n-1)data6
....
block(1)data1 block(1)data2 block(1)data3
block(1)data4 block(1)data5 block(1)data6
____________________________________________
Data are mainly real numbers, and size of the data set is way too big to use allocatable arrays. So I have somehow to read and write on the fly.
I could not find a way to read-or-write backward in a file.
Well, I sort of have an answer, but it didn't work, perhaps due to compiler bugs or my rudimentary understanding of file positioning in Fortran. My attempt was to open the input file with
access = 'stream'
andform = 'formatted'
. This way I could push the line positions onto a stack and pop them off so they come out in reverse order. Then, walking through the lines in reverse order I could write them into the ourput file.Here is my input file:
Now with
ifort
my file positions were printed out asNote that the first line is at the end of record 3 instead of the beginning of record 4. The output file was
With gfortran, the file positions printed out as
This time the first line is at the beginning of record 4 as I would expect. However, the output file had unfortunate contents
I had hoped for a more positive result. I can't tell whether my results are due to poor programming or compiler bugs, but I posted in case someone else could possibly get my pure Fortran solution to work.
If the data fits in memory, you can do it. I've tested it out, a file
with a file size of 1.2GB could be reversed by this little awk script:
in under 2 minutes.
If this is really not possible, you need to do what @high-performance-mark said and read it in in blocks that are manageable, reverse it in memory, then concatenate them together at the end. Here's my version:
I would not directly use Fortran, but more a sequence of Linux commands (or Cygwin / GNU utils on Windows). Fortran is possible as well (see second possibility).
An outline (based on OS commands):
wc
)head
) to fileresult file
tail
)awk
script joining the relevant linestac
on the resultawk
script splitting the linesresult file
Another idea would be (in a programming language):
ftell
).fseek
to the indicated position