- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
I want to read a two-dimensional array. The array could be quite big, so I will rely on using a Do loop such as:
do i = 1, n_rows do j = 1, n_columns read(unit = 1, fmt = *, iostat = io) array(i,j) end do end do
What I discovered is that no matter how I configure the do loops, it insists on reading column no. 1 first. And when it reach the maximum row number (n_rows), io becomes -1 (end of file statement) and the rest of values becomes 0. It is probably some dumb thing I'm doing wrong, but can anyone please help?
Cheers,
Carl
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Carl,
Your data file has the data for each row on a single line. By default each READ statement in Fortran starts a new record = new line. Here are a couple of ways to read your data file.
Read a line at a time, like so.
do i = 1, n_rows read(1,*) (array(i,j), j=1, n_columns) end do
Read all the data in one go. This method will just read the next n_rows*n_column numbers in the file, then discard the rest of a partially read line.
read(1,*) ((array(i,j), j=1,n_columns), i=1,n_rows)
Here are the full programs
program io_2 implicit none integer n_rows, n_columns, i, j real(kind=8), allocatable :: array(:,:) open(unit=1,file='file.dat',status='old') read(1,*) n_rows, n_columns allocate(array(n_rows, n_columns)) do i = 1, n_rows read(1,*) (array(i,j), j=1, n_columns) end do write(*,*) array(1,1), array(1,n_columns) write(*,*) array(n_rows,1), array(n_rows,n_columns) end program
program io_3 implicit none integer n_rows, n_columns, i, j real(kind=8), allocatable :: array(:,:) open(unit=1,file='file.dat',status='old') read(1,*) n_rows, n_columns allocate(array(n_rows, n_columns)) read(1,*) ((array(i,j), j=1,n_columns), i=1,n_rows) write(*,*) array(1,1), array(1,n_columns) write(*,*) array(n_rows,1), array(n_rows,n_columns) end program
They generate identical output
$ ./io_2 1.0000000000000000 42.740000000000002 2016.0000000000000 28.890000000000001
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Carl,
Can you provide a self contained program and sample data file. As is we can't see: the types of the variables; how the file is opened; how the data is arranged in the input.
As written, each READ statement consumes one record (one line). It will read the first number on the line and discard the rest (if any). Your code works for me with the appropriate input file. If your data is in a different format your code will need to be modified to suit.
program io_1 implicit none integer n_rows, n_columns, i, j, io integer, allocatable :: array(:,:) open(unit=1,file='io_1.dat',status='old') read(1,*) n_rows, n_columns allocate(array(n_rows, n_columns)) do i = 1, n_rows do j = 1, n_columns read(unit=1,fmt=*,iostat=io) array(i,j) end do end do do i = 1, n_rows write(*,*) array(i,:) end do end program
with data file
2 2 1 2 3 4
generates
$ ./io_1 1 2 3 4
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi David,
I tried your approach, which is basically the same thing that I was already doing, and it did not work.
subroutine file(file_name) implicit none character(len=*), intent(in) :: file_name integer(2) :: n_rows, n_columns, i, j, io real(8), allocatable :: array(:,:) open(unit = 1, file = file_name, status = 'old') read(1,*) n_rows, n_columns allocate(array(n_rows, n_columns)) do i = 1, n_rows do j = 1, n_columns read(unit = 1, fmt = *, iostat = io) array(i,j) end do end do end subroutine
I have attached the file I'm trying to read. Hopefully you or someone else can figure it out.
Thanks,
Carl
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Carl,
Your data file has the data for each row on a single line. By default each READ statement in Fortran starts a new record = new line. Here are a couple of ways to read your data file.
Read a line at a time, like so.
do i = 1, n_rows read(1,*) (array(i,j), j=1, n_columns) end do
Read all the data in one go. This method will just read the next n_rows*n_column numbers in the file, then discard the rest of a partially read line.
read(1,*) ((array(i,j), j=1,n_columns), i=1,n_rows)
Here are the full programs
program io_2 implicit none integer n_rows, n_columns, i, j real(kind=8), allocatable :: array(:,:) open(unit=1,file='file.dat',status='old') read(1,*) n_rows, n_columns allocate(array(n_rows, n_columns)) do i = 1, n_rows read(1,*) (array(i,j), j=1, n_columns) end do write(*,*) array(1,1), array(1,n_columns) write(*,*) array(n_rows,1), array(n_rows,n_columns) end program
program io_3 implicit none integer n_rows, n_columns, i, j real(kind=8), allocatable :: array(:,:) open(unit=1,file='file.dat',status='old') read(1,*) n_rows, n_columns allocate(array(n_rows, n_columns)) read(1,*) ((array(i,j), j=1,n_columns), i=1,n_rows) write(*,*) array(1,1), array(1,n_columns) write(*,*) array(n_rows,1), array(n_rows,n_columns) end program
They generate identical output
$ ./io_2 1.0000000000000000 42.740000000000002 2016.0000000000000 28.890000000000001
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thank you so much :) That worked perfectly!
\Carl

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page