|
forums.silverfrost.com Welcome to the Silverfrost forums
|
View previous topic :: View next topic |
Author |
Message |
Zach
Joined: 13 Mar 2023 Posts: 85 Location: Groningen, Netherlands
|
Posted: Tue Mar 21, 2023 6:15 pm Post subject: Random file access |
|
|
I would like to know how to WRITE randomly readable records to a file, and how to READ randomly: i.e., specific records, back again, as required - in Fortran. I am unable to find a decent relevant, comprehensive, understandable reference on the Net. Please help! And please tell me: what do these forward unexplained slashes mean [re: fseek, lunit/1/, offset/2/, from/0/, n]?
Simple clear completely relevant examples would also be extremely helpful.
Zach (bewildered rooky) |
|
Back to top |
|
|
wahorger
Joined: 13 Oct 2014 Posts: 1225 Location: Morrison, CO, USA
|
Posted: Tue Mar 21, 2023 7:25 pm Post subject: |
|
|
If you are speaking of random accessing fixed length records, FTN does a fine job of doing just that. In short, you open the file and indicate it is a fixed length record direct access file whose record size is "n", issue reads/writes using a specific form of READ and WRITE, then CLOSE the file.
Here's a sample:
Code: |
OPEN(UNIT=10,FILE="my_direct_file",STATUS='NEW',
$ ACCESS='DIRECT',RECL=125,FORM="UNFORMATTED",
$ IOSTAT=ICHECK,ERR=2220)
write(10,rec=1)i,j,k,l,iarray(1:20)
read(10,rec=1)ii,jj,kk,ll,o_array(1:20)
close(unit=10)
|
The code opens a file unit (10). This can be a variable or a constant; your choice. The file is named "my_direct_file", it is 'NEW' (will be created, will cause an error if already existing), it is to be a 'DIRECT' access file (by record numbers) whose record length is 125 bytes and data is 'UNFORMATTED' (meaning format codes are not needed to read or write the data). For error checking, I use IOSTAT as an option (it will contain an error/status code to be placed in the variable ICHECK, and if an error is detected, program control will go to the label 2220 for handling.
I write the first record with the variables as indicated. So long as the length of the data (in bytes) is less than 125, the write is successful. If the write has less than 125 bytes, only those bytes actually written will be defined. Stated another way, the remainder of the record will be undefined.
I can then read this data into different variables.
Then, the unit is closed, buffers are flushed, and life continues.
To access the data, I'll need to open the file again. This time, I'd use a status of 'OLD' because the file should exist. The rest of the OPEN would remain the same.
There are several nuances in the parameters available for an OPEN statement. The documentation is thorough; that said, if you are a novice at this, you can ask for help here is something is not working as you thought it should.
One thing to remember: You cannot write a record to just any record position. You can write the NEXT logical record (as I did) or any PREVIOUSLY written record. You can't initially create a file and write REC=2, for example. Record 1 must first exist!
Hope this helps! |
|
Back to top |
|
|
Zach
Joined: 13 Mar 2023 Posts: 85 Location: Groningen, Netherlands
|
Posted: Wed Mar 22, 2023 5:20 pm Post subject: |
|
|
It is a joy to read your responses.
Re: my query regarding �Random Access� / reading and writing operations
I read that different parameters are optional when coding a direct access file: however some parameterss, if left out, cause no compiling error. I presume that leaving out an optional parameter disables the compiled code to respond, with the appropriate error message, in a particular error situation, when run. Thus complicating error solving. Is that so?
I have not yet experimanted with your example, because I have questions.
Re your example: in it you write �o-array(1:20)�. I see no explanation in my array tutorial for the meaning of (x:y) when declaring an array. Pardon my ignorace: could you please explain what it means? I see no �action� parameter in the example. So that issue will presumably be solved by either of the two last lines of your example. An array, after having been declared, can differ in length when actually used. Also the other parameters (i,j,k,l) could occupy different lengths. Can the fixed length of a direct file record cope with all that? Why is not formatting of the individual variables to be written, a requirement? |
|
Back to top |
|
|
wahorger
Joined: 13 Oct 2014 Posts: 1225 Location: Morrison, CO, USA
|
Posted: Wed Mar 22, 2023 9:31 pm Post subject: |
|
|
Zach,
First, the 1:20 syntax says "use array elements 1 through 20, inclusive". It's a way to reference a portion of the array without using implied DO loops.
Yes, some parameters are optional. That said, it is up to the programmer to use whatever is correct for the situation. For example, using:
Code: | write(10)array(1:20)
|
would imply that you are writing a sequential, unformatted file, while:
Code: | write(10,20000,rec=1)array(1:20)
|
would imply you are writing a direct access, formatted file. But if you have not opened the file appropriately, the error will only show up at run time. Never at compile time, because, after all, these are all valid syntactically.
BTW, o_array is not o-array. The underscore is a valid alphanumeric character in FTN95.
Regarding record lengths, the system cares not what an individual element's size is unless that element is too big to fit within your RECL= limit. It only cares about the aggregate length (the sum of ALL lengths) in the single I/O list. In my example, let's assume the lengths of i,j,k, and l are 1,2,4, and 8 bytes (all valid integer sizes), and o_array is dimensioned to 20 and is a single precision floating point value (4 bytes each). Thus, the record being written is 1+2+4+8+20*4 = 95 bytes. The remainder (30 bytes) is technically "undefined"; something will be written to the file to make a complete fixed length, direct access, record.
Writing formatted data consumes time, and (for most floating point numbers) may lose precision. So writing an unformatted file is the most efficient way to write the file so it can be read by a computer later. Requiring formatting (for humans to read) requires a great deal more space.
For example, consider a double precision floating point value. Your exponent could be 3 digits long with a sign (+/-) and a "D" then 15 to 17 digits in length with an additional decimal point and a sign, or a total of 3+1+1+17+1+1 = 24 bytes and may not be precisely represented, while the unformatted value takes 8 bytes and whose value is always exactly what it was to start with.
Ref: https://en.wikipedia.org/wiki/Double-precision_floating-point_format
FYI: It is the same in any language; storing and retrieving the binary, machine representation of a number is always better in terms of efficiency and accuracy.
Bill |
|
Back to top |
|
|
Zach
Joined: 13 Mar 2023 Posts: 85 Location: Groningen, Netherlands
|
Posted: Wed Mar 22, 2023 10:52 pm Post subject: |
|
|
Hi Bill,
I will have to digest what you wrote and experiment a bit. Thank you very much for it. In the past I have written in other languages, have managed a COBOL shop, created a conceptual design language, wrote and marketed applications in C sharp, and in comparison are finding Fortran *much* less clear cut.
Patrick. |
|
Back to top |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|