Home > Archive > Fortran > September 2005 > file reading problem
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
file reading problem
|
|
| Bart Vandewoestyne 2005-09-09, 6:59 pm |
| I feel silly... i must have been staring at this for too long but
i cannot see the problem... I am trying to read the first line of
a text file to do some processing on it... I'm doing something
like the following:
...
character(len=*), intent(in) :: pointset_file
...
integer(kind=i4b), parameter :: max_chars = 100
integer(kind=i4b) :: my_unit
character(len=max_chars) :: line
integer(kind=i4b) :: ios
...
call get_unit(my_unit)
open(unit=my_unit, file=pointset_file, iostat=ios, status="old", &
access="sequential", action="read")
if (ios == 0) then
write(unit=*, fmt="(A)") "ERROR: could not open file "//pointset_file
end if
read (unit=my_unit, fmt="(A)", iostat=ios) line
if (ios /= 0) then
print *, "ERROR"
end if
print *, "line = ", line
...
Opening the file goes without problems, but reading the first
line of the file and trying to put the content in `line' always
seems to give errors because `ios' is nonzero and the content of
`line' is not the first line of my file.
What am i overlooking here? I've been staring at this for too
long now...
Regards,
Bart
--
"Share what you know. Learn what you don't."
| |
| meek@skyway.usask.ca 2005-09-09, 6:59 pm |
| In a previous article, Bart Vandewoestyne <MyFirstName.MyLastName@telenet.be> wrote:
>I feel silly... i must have been staring at this for too long but
>i cannot see the problem... I am trying to read the first line of
>a text file to do some processing on it... I'm doing something
>like the following:
>
> ...
>
> character(len=*), intent(in) :: pointset_file
> ...
> integer(kind=i4b), parameter :: max_chars = 100
> integer(kind=i4b) :: my_unit
> character(len=max_chars) :: line
> integer(kind=i4b) :: ios
>
> ...
>
> call get_unit(my_unit)
> open(unit=my_unit, file=pointset_file, iostat=ios, status="old", &
> access="sequential", action="read")
> if (ios == 0) then
> write(unit=*, fmt="(A)") "ERROR: could not open file "//pointset_file
> end if
>
> read (unit=my_unit, fmt="(A)", iostat=ios) line
> if (ios /= 0) then
> print *, "ERROR"
> end if
> print *, "line = ", line
>
> ...
>
>
>Opening the file goes without problems, but reading the first
>line of the file and trying to put the content in `line' always
>seems to give errors because `ios' is nonzero and the content of
>`line' is not the first line of my file.
>
>What am i overlooking here? I've been staring at this for too
>long now...
>
>Regards,
>Bart
>
>--
> "Share what you know. Learn what you don't."
You need to print "error, ios=",ios
and look it up.
Chris
| |
| Dick Hendrickson 2005-09-09, 6:59 pm |
|
Bart Vandewoestyne wrote:
> I feel silly... i must have been staring at this for too long but
> i cannot see the problem... I am trying to read the first line of
> a text file to do some processing on it... I'm doing something
> like the following:
>
> ...
>
> character(len=*), intent(in) :: pointset_file
> ...
> integer(kind=i4b), parameter :: max_chars = 100
> integer(kind=i4b) :: my_unit
> character(len=max_chars) :: line
> integer(kind=i4b) :: ios
>
> ...
>
> call get_unit(my_unit)
> open(unit=my_unit, file=pointset_file, iostat=ios, status="old", &
> access="sequential", action="read")
> if (ios == 0) then
Maybe I'm misunderstanding you here, but ios will be zero if
there NO problems. Maybe you want ios /= 0 ?
Dick Hendrickson
> write(unit=*, fmt="(A)") "ERROR: could not open file "//pointset_file
> end if
>
> read (unit=my_unit, fmt="(A)", iostat=ios) line
> if (ios /= 0) then
> print *, "ERROR"
> end if
> print *, "line = ", line
>
> ...
>
>
> Opening the file goes without problems, but reading the first
> line of the file and trying to put the content in `line' always
> seems to give errors because `ios' is nonzero and the content of
> `line' is not the first line of my file.
>
> What am i overlooking here? I've been staring at this for too
> long now...
>
> Regards,
> Bart
>
| |
|
|
Bart Vandewoestyne schreef:
> I feel silly... i must have been staring at this for too long but
> i cannot see the problem... I am trying to read the first line of
> a text file to do some processing on it... I'm doing something
> like the following:
>
> ...
>
> character(len=*), intent(in) :: pointset_file
> ...
> integer(kind=i4b), parameter :: max_chars = 100
> integer(kind=i4b) :: my_unit
> character(len=max_chars) :: line
> integer(kind=i4b) :: ios
>
> ...
>
> call get_unit(my_unit)
> open(unit=my_unit, file=pointset_file, iostat=ios, status="old", &
> access="sequential", action="read")
> if (ios == 0) then
I don't see anything wrong , exept you want to test ios /= 0 probably.
Tried 3 different compilers. All OK.
[JvO]
> write(unit=*, fmt="(A)") "ERROR: could not open file "//pointset_file
> end if
>
> read (unit=my_unit, fmt="(A)", iostat=ios) line
> if (ios /= 0) then
> print *, "ERROR"
> end if
> print *, "line = ", line
>
> ...
>
>
> Opening the file goes without problems, but reading the first
> line of the file and trying to put the content in `line' always
> seems to give errors because `ios' is nonzero and the content of
> `line' is not the first line of my file.
>
> What am i overlooking here? I've been staring at this for too
> long now...
No further idea... :-(
| |
| Richard E Maine 2005-09-09, 6:59 pm |
| In article <1126280760.142274@seven.kulnet.kuleuven.ac.be>,
Bart Vandewoestyne <MyFirstName.MyLastName@telenet.be> wrote:
> open(unit=my_unit, file=pointset_file, iostat=ios, status="old", &
> access="sequential", action="read")
> if (ios == 0) then
> write(unit=*, fmt="(A)") "ERROR: could not open file "//pointset_file
> end if
Others pointed out the fact that you have == where you probably wanted
/=. That's probably a big part of your problem (then you need to look
into why the open is failing as the next step).
> seems to give errors because `ios' is nonzero and the content of
> `line' is not the first line of my file.
The contents of line aren't guaranteed to be anything meaningful
(technically, it is undefined) if the read failed, so that's not the
thing to focus on, but your mention of expecting it to be the first line
does prompt me to one observation in pedantic mode. This is *NOT* likely
to be your problem. Your other symptoms point elsewhere, and anyway I
haven't seen a compiler that actually acted like this in a long time,
but just FYI...
You are not guaranteed that the OPEN will open the file with a position
at the beginning of the file. Ok, in practice, current compilers all do
it as far as I know. But still, if you want the code to actually conform
to the standard instead of just happen to work on current compilers, you
need to either
1. Specify position='rewind' in the OPEN
or
2. Add a separate REWIND statement after the open.
Either will work. The choice is largely a matter of taste and
convenience. I usually find the position='rewind' option to be more
convenient than adding a separate statement.
--
Richard Maine | Good judgment comes from experience;
email: my first.last at org.domain | experience comes from bad judgment.
org: nasa, domain: gov | -- Mark Twain
| |
| Arjen Markus 2005-09-12, 3:56 am |
| That is what I see too:
You say that opening the file succeeds, but:
if ( ios == 0 ) write(*,*) 'Problem'
will only print the message when _nothing_ goes wrong!
Regards,
Arjen
| |
| Bart Vandewoestyne 2005-09-12, 6:58 pm |
| On 2005-09-09, Richard E Maine <nospam@see.signature> wrote:
>
> Others pointed out the fact that you have == where you probably wanted
> /=. That's probably a big part of your problem (then you need to look
> into why the open is failing as the next step).
Yes, that was indeed already one of my problems. Thanks to all
those who have spotted what I didn't spot! ;-)
> The contents of line aren't guaranteed to be anything meaningful
> (technically, it is undefined) if the read failed, so that's not the
> thing to focus on, but your mention of expecting it to be the first line
> does prompt me to one observation in pedantic mode. This is *NOT* likely
> to be your problem. Your other symptoms point elsewhere, and anyway I
> haven't seen a compiler that actually acted like this in a long time,
> but just FYI...
>
> You are not guaranteed that the OPEN will open the file with a position
> at the beginning of the file. Ok, in practice, current compilers all do
> it as far as I know. But still, if you want the code to actually conform
> to the standard instead of just happen to work on current compilers, you
> need to either
>
> 1. Specify position='rewind' in the OPEN
>
> or
>
> 2. Add a separate REWIND statement after the open.
>
> Either will work. The choice is largely a matter of taste and
> convenience. I usually find the position='rewind' option to be more
> convenient than adding a separate statement.
Specifying position="rewind" indeed solves my problem. Consider
the following data-file:
bartv@vonneumann:~/fortran$ cat test_read.txt
0.1 0.1 0.1
0.2 0.2 0.2
0.3 0.3 0.3
0.4 0.4 0.4
And consider the following program:
program example_read_file
character(len=*), parameter :: pointset_file = "test_read.txt"
integer, parameter :: max_chars = 100
character(len=max_chars) :: line
integer :: ios
open(unit=1, file=pointset_file, iostat=ios, status="old", &
access="sequential", action="read")
if (ios /= 0) then
write(unit=*, fmt="(A)") "ERROR: could not open file "//pointset_file
end if
read (unit=1, fmt="(A)", iostat=ios) line
if (ios /= 0) then
print *, "ERROR: could not read file "//pointset_file
end if
print *, "line read = ", line
end program example_read_file
Compiling it with the following options:
bartv@vonneumann:~/fortran$ make example_read_file
F -o example_read_file -g -gline -C=all example_read_file.f95
gives me an output of:
bartv@vonneumann:~/fortran$ ./example_read_file
ERROR: could not open file test_read.txt
line read = Bart's method found 78498 primes in 1.800000 seconds.
Note that the file cannot be opened, and the contents of line are some
junk left over from another thread ;-)
Adding the position="rewind" solves the problem:
bartv@vonneumann:~/fortran$ ./example_read_file
line read = 0.1 0.1 0.1
Page 179 of my F-book writes on the position="..." specifier:
"... It must be specified if the access method is sequential and must not
be specified if the access method is direct."
So I have two remarks on this:
1) This looks to me like something the F-compiler could detect at compile time
instead of detecting this via iostat at runtime. Why isn't this detected
at runtime? Walt? Any comments?
2) g95 in -std=F mode seems to accept the example, even without the
position="rewind" specifier. After reading page 179 of my book, this
seems wrong to me. I hope Andy is reading this so i don't have to send
another bug-report... saves me some time... ;-)
For the record, i have used these compiler-versions:
Fortran Company/NAG F compiler Release 20031017
G95 (GCC 4.0.1 (g95!) Sep 7 2005)
Regards,
Bart
--
"Share what you know. Learn what you don't."
| |
| Arjen Markus 2005-09-12, 6:58 pm |
| The line contained whatever was left in the memory at that point in
time, because a Fortran
program does not initialise its variables, unless explicitly instructed
via a DATA statement
and the like. The fact that it seemed somewhat useful is deplorable: it
meant you were put on
the wrong foot (if that is a proper English expression).
The compiler could easily detect it at compile-time - it is a simple
additional syntactical
rule (the Fortran standard allows you more leeway, but F is strict in a
number of places -
better it does this when compiling the source code).
Regards,
Arjen
| |
| Gordon Sande 2005-09-12, 6:58 pm |
|
<snip>
[color=darkred]
<snip>
In the days of IBM mainframes, IBM/360s or equivalents like Amdahls etc, I
recall a job stream in which I used a utility to read several records at
the front of a sequential file in one job step so that the Fortran program
in the following job step would pick up and correctly start reading part
way into the file. I have a dim recollection that it required an extra
optional parameter in the JCL to prevent OS/360 from starting the file
at its initial position. The extra fuss may have technically been related
keeping the old data set description around for the following step so that
the positioning would not be discarded. I think I have seen the same notion
described in Unix terms where one reuses file handles, or whatever.
So, far from being a failure of the system to start at the beginning of
a file it is a useful but obscure feature. Sometimes it requires a bit
of extra work to have it work (and sometimes one gets it by accident).
| |
| Jan Vorbrüggen 2005-09-12, 6:58 pm |
| > bartv@vonneumann:~/fortran$ ./example_read_file
> ERROR: could not open file test_read.txt
> line read = Bart's method found 78498 primes in 1.800000 seconds.
>
> Note that the file cannot be opened, and the contents of line are some
> junk left over from another thread ;-)
Such things should not happen, because that's a potential security leak.
What OS are you using?
Jan
| |
| Bart Vandewoestyne 2005-09-12, 6:58 pm |
| On 2005-09-12, Jan Vorbrüggen <jvorbrueggen-not@mediasec.de> wrote:
>
> Such things should not happen, because that's a potential security leak.
> What OS are you using?
A Debian GNU/Linux stable box with kernel:
bartv@XXXXXXXX:~$ uname -a
Linux XXXXXXXXXX 2.6.8-2-686-smp #1 SMP Thu May 19 17:27:55 JST
2005 i686 GNU/Linux
on an Intel(R) Pentium(R) 4 CPU 2.40GHz.
If there are other things or little test-programs you want me to
check or compile, please let me know.
Regards,
Bart
--
"Share what you know. Learn what you don't."
| |
| Richard E Maine 2005-09-12, 6:58 pm |
| In article <1126530122.805544@seven.kulnet.kuleuven.ac.be>,
Bart Vandewoestyne <MyFirstName.MyLastName@telenet.be> wrote:
> Page 179 of my F-book writes on the position="..." specifier:
>
> "... It must be specified if the access method is sequential and must not
> be specified if the access method is direct."
>
> So I have two remarks on this:
>
> 1) This looks to me like something the F-compiler could detect at compile
> time
> instead of detecting this via iostat at runtime. Why isn't this detected
> at runtime? Walt? Any comments?
I'm neither Walt nor an F expert, so I don't know about other
restrictions that might make things different in F. But in Fortran, this
is not compile-time checkable. Pretty much all of the character I/O
specifiers, including both access= and position= take character
expressions, with no requirement that they be initialization expressions
(that's basically the category of expressions known at compile time). It
is certainly quite common for access= and position= to be specified by
simple literals, but that isn't required (at least in Fortran).
P.S. Gordon Sande commented in another post to the thread that "far from
being a failure of the system to start at the beginning of a file it is
a useful but obscure feature". I didn't use words like "failure" because
I wasn't intending to pass any value judgments; I've also used systems
where it was useful. I was only explaining what the standard's
requirement was (and I had no idea that F had a stronger requirement).
--
Richard Maine | Good judgment comes from experience;
email: my first.last at org.domain | experience comes from bad judgment.
org: nasa, domain: gov | -- Mark Twain
| |
| glen herrmannsfeldt 2005-09-12, 6:58 pm |
| Richard E Maine wrote:
(snip)
> I'm neither Walt nor an F expert, so I don't know about other
> restrictions that might make things different in F. But in Fortran, this
> is not compile-time checkable. Pretty much all of the character I/O
> specifiers, including both access= and position= take character
> expressions, with no requirement that they be initialization expressions
> (that's basically the category of expressions known at compile time). It
> is certainly quite common for access= and position= to be specified by
> simple literals, but that isn't required (at least in Fortran).
I used to believe that, too. I have seen more and more C compilers
that will detect type mismatch on arguments to printf, where the
format string is a literal string constant. The compiler can't check
in the case of a variable, but constants, and mistakes, are common
enough to make it worthwhile to check.
I suppose, though, that I would agree that mistakes on access= are
still a reasonable run-time check. Just because it is possible to
check at compile time isn't enough reason to expect it.
-- glen
| |
| glen herrmannsfeldt 2005-09-12, 6:58 pm |
| Gordon Sande wrote:
> <snip>
[color=darkred]
> <snip>
> In the days of IBM mainframes, IBM/360s or equivalents like Amdahls etc, I
> recall a job stream in which I used a utility to read several records at
> the front of a sequential file in one job step so that the Fortran program
> in the following job step would pick up and correctly start reading part
> way into the file. I have a dim recollection that it required an extra
> optional parameter in the JCL to prevent OS/360 from starting the file
> at its initial position.
I know this works for writing, but I hadn't thought about it for
reading. The JCL parameter DISP tells what to do with the data set
before starting a job step, and what to do when the step is done.
DISP=(NEW,KEEP) says that it should be created, and it is a fatal error
if it does exist, and should not be deleted at the end.
DISP=OLD says that it must exist, a fatal error if it doesn't, and
will not be deleted at the end.
DISP=SHR allows non-exclusive access to existing data sets.
DISP=MOD the data set may or may not exist. If it does, it is opened
pointing at the end, so that data may be appended to an existing data
set. If it doesn't exist it is created.
If the second argument is PASS, commonly DISP=(MOD,PASS) the data
set is passed onto subsequent job steps. This is commonly used when
multiple steps write to the same data set, most often used by compilers
writing object programs. I have only ever used PASS for writing, but
it might be that the position is retained even for reading. As I
understand it this saves some overhead of closing and reopening the
data set between steps. Even more, for tapes it saves dismounting
and remounting the tape.
> The extra fuss may have technically been related
> keeping the old data set description around for the following step so that
> the positioning would not be discarded. I think I have seen the same notion
> described in Unix terms where one reuses file handles, or whatever.
> So, far from being a failure of the system to start at the beginning of
> a file it is a useful but obscure feature. Sometimes it requires a bit
> of extra work to have it work (and sometimes one gets it by accident).
Anyway, yes, for systems like MVS it is the JCL that determines the
position on open, possibly the OPEN statement will reposition it.
The OS/360 Fortran compilers didn't have OPEN, JCL specifies the
data set name, disposition, unit, volume, space to allocate,
record format, record length, and block size.
-- glen
|
|
|
|
|