Just a quick little programming snippet today. When preparing data files, it’s often useful to include headers and comments in them, especially in the more complicated ones. Most data applications that you might be loading data into, such as maybe Python or MATLAB, have plenty of ability to filter out those comments, but what if you’re using a much lower level language, such as Fortran? I had that problem just today where I wanted a super elegant way of adding comments and blank lines into my data file to keep it readable, but without confusing during my READ loop. So, I went scouring through the web and got inspired by the second comment on this forum thread. I’ve altered it a little bit, so here’s my final snippet:
character(len=128) :: filename, ch_dummy integer :: iostat integer :: idx1, idx2, idxcom open(unit=1, file=trim(filename)) do read(1, *, iostat=iostat) ch_dummy if ( iostat < 0 ) exit idx1 = index( ch_dummy, '#' ) idx2 = index( ch_dummy, '!' ) idxcom = max( idx1, idx2 ) if ( idxcom .gt. 0 ) then ch_dummy(idxcom:) = '' ! Blank what is past the comment endif if ( trim(ch_dummy) .eq. '' ) cycle ! Do whatevert you need to here. Count rows, read in data. Knock yourself out. ;) end do
It’s not terribly complicated, but I’ll just take you through it. First off, lines 1-3 give you the variable declarations to make this little beasty work. The strings filename and ch_dummy are used for containing the name of the file to load and a line buffer respectively and can be as long as you need them to. Just edit len=n with n being the number of characters you want it to contains. Then, we open a file for reading on line 5 before entering a do loop to do things with it. First, we read the entire line into the ch_dummy, checking the I/O status code as we do it. We rely on this to drop out of the loop when we reach the end of the file. Next we use the index function to check and see if he characters that start our comment are in the current buffer. We find out which one has the greater index and if one of the indices is non-zero, it means we have a hit. The really cool bit comes now. If the character is at the start of the line, we just blank out the line, but if the character is later in the line, it only removes what’s past it and leaves whatever comes before it in tact. Then on line 17 we check and see if the line is empty. If so, we just skip onto the next one. This is really neat because it means that both blank and formerly commented lines are skipped by this one line of code. If however there are characters on that line, we pass on through to whatever code you want to perform on them.
This is by no means perfect, but I’ve been looking for a catch all for this little problem for a while, and this is the closest I’ve ever come to it. I hope this little snippet is useful and saves you a little digging, and credit to Ken from that link for coming up with the bulk of this technique.