Fortran

Guide To Learn

Implementing the CSV reader subroutine

Having covered the detailed mechanics of allocating and deallocating arrays, including the built-in error handling, we finally arrive at implementing the CSV file reader subroutine, as shown in the following listing.

Listing 5.10 Reading stock price data from CSV files and storing them into arrays

subroutine read_stock(filename, time, open, high,&
                      low, close, adjclose, volume)
  ...
  integer :: fileunit
  integer :: n, nm
 
  nm = num_records(filename) - 1                         ❶
 
  if (allocated(time)) deallocate(time)                  ❷
  allocate(character(10) :: time(nm))                    ❷
  call alloc(open, nm)                                   ❸
  call alloc(high, nm)                                   ❸
  call alloc(low, nm)                                    ❸
  call alloc(close, nm)                                  ❸
  call alloc(adjclose, nm)                               ❸
  call alloc(volume, nm)                                 ❸
 
  open(newunit=fileunit, file=filename)                  ❹
  read(fileunit, fmt=*, end=1)                           ❺
  do n = 1, nm
    read(fileunit, fmt=*, end=1) time(n), open(n),&      ❻
      high(n), low(n), close(n), adjclose(n), volume(n)  ❻
  end do
  1 close(fileunit)                                      ❼
 
end subroutine read_stock

❶ Finds the number of records (lines) in a file

❷ Allocates the array of timestamps

❸ Allocates the stock price data arrays

❹ Opens the CSV file

❺ Skips the data header in the first line

❻ Reads the data line-by-line and stores them into arrays

❼ Closes the file when done

To find the length of the arrays before I allocate them, I inquire about the length of the CSV file using a custom function num_records, defined in src/mod_io.f 90. If you’re wondering what the number 1 means in the 1 close(fileunit), it’s just a line label that Fortran uses if and when it encounters an exception in the read(fileunit, fmt=*, end=1) statements. If you’re interested in how this function works, take a look inside src/mod_io.f 90. I won’t spend much time on the I/O-specific code here, as we just need it to move forward with the array analysis. We’ll explore I/O in more detail in chapter 6.

On every subroutine entry, the arrays timeopenhighlowcloseadjclose, and volume will be allocated with size nm. The subroutine alloc now seamlessly reallocates the arrays for us. Notice that we still use the explicit way of allocating and deallocating the array of timestamps. This is because we implemented the convenience subroutines alloc and free that work on real arrays. Because of Fortran’s strong typing discipline, we can’t just pass an array of strings to a subroutine that expects an array of reals. We’ll learn in chapter 9 how to write generic procedures that take arguments of different types. For now, explicitly allocating the array of timestamps will do. Furthermore, we also need to specify the string length when allocating the time array.

Having read the CSV files and loaded the stock price arrays with the data, we can move on to the actual analysis and fun with arrays.

Getting the number of lines in a text file

If you’re curious how the num_records function is implemented, take a look at src/mod_io.f90. This function opens a file and counts the number of lines by reading it line-by-line.

Implementing the CSV reader subroutine

Leave a Reply

Your email address will not be published. Required fields are marked *

Scroll to top