Opening and reading a file in Fortran - fortran

open(NEWUNIT=fId, file=trim(filename), iostat=ierr, action='READ')
if (ierr /= 0) return
read(fID,'(A)') dataArray
close(fId)
Does this code read the complete data in a file and save it in an array or it just reads a single line?

Consider
character(len=10) name(5)
read(*,'(A)') name
Having the whole array in the input stamement is treated the same as as specifying the array's elements in order:
read(*,'(A)') name(1), name(2), name(3), name(4), name(5)
The input statement will attempt to read five values, each according to the edit descriptor A. What happens as a result depends on various things.
Format reversion means that when one value is transferred the file is positioned on the next record (line). So, in the case here assuming the file has at least two lines, the first 10 "characters" of the first line are read and put into name(1). Then the first 10 "characters" of the second line are read and put into name(2). And so on for as long as lines remain.
Situations (assuming no errors come about):
there are as many lines as elements of the array: all lines are read in to the array (but only as much of a line as the character length of the variable);
there are more lines than there are elements: only the number of lines equal to the number of records are read;
there are more elements than there are lines: an end-of-file condition occurs and the array name becomes undefined.

Related

Read line from file with padding in Fortran

If I have a text file where lines contains some non-blank characters followed by spaces, how do I read those lines into a character variable without excess spaces?
character (len=1000) :: text
open (unit=20,file="foo.txt",action="read")
read (20,"(a)") text
will read the first 1000 characters of a line into variable text, which will be padded with spaces at the end if there are fewer than 1000 characters in the line. But if the line length is 100 you have 900 extraneous spaces, and the program does not "know" how long the line read actually was.
Fortran strings are blank-padded. There is simply no chance to distinguish any significant blank-padding in your strings with constant-length Fortran strings.
If every whitespace character is important, I suggest to treat the file as a stream-access file instead (formated or unformatted as needed), read individual characters to some array buffer and allocate a deferred-length string only after you know the length you actually need.
character (len=1000) :: text
integer :: s, ios
open (unit=20,file="foo.txt",action="read")
read (20,"(a)", size=s, advance='no', iostat=ios) text
After that last line, s contains the number of characters read, including trailing spaces, which I think is what you wanted.
Notes:
With a size tag, you must also have an advance tag set to 'no' otherwise you get a compilation error. Since the format is "(a)", the whole line is read so the next read statement will advance to the next line despite the 'no'. That's fine.
ios stores a negative integer when attempting to read past the end of the line. This will always happen if the line is shorter than length of text. That's fine.
When attempting to read past the end of the file, ios will store a different negative integer. What those two negative integers are is not set by the standard I think so you may have to experiment a bit. In my case, with the gfortran compiler, ios was -1 when attempting to read past the end of the file and -2 otherwise.

What is the most effective way to read the last line of a file in c++?

im trying to store a large list of prime numbers in a text file and if I end my program i need to be able to read the line of the file to see where I left off. I dont know how to read the last line with out reading every line of the file first.
I don't know either. Just write the last value into a separate file, and read that value to know where to resume.
You could use setg() to jump to the end of the file and do guesses how far a line is. If there's a newline between your point and the end of the file then you're in the next-to-last line and know what the last line is.
But Pete Beckers solution is a lot nicer, I'd go with that instead.
You can calculate the bytes of your numbers.
For example you have 5 number and you want to read last number.
1 integer is 4 byte. So you can move 4*4=16 Byte in file using fseek. After that you can read last line.
fseek (file , 16 , SEEK_SET);
SEEK_SET means begining of file.
Seek to the very end of the file, and just read backwards till you find the newline character which means you have found the the start of the last line
If you know the maximum length of line this will be easy.
Just go the the pointer that is the location of the end of file less this value.
Start reading lines from there and put them in a buffer. Clear buffer when the previous character was a new line
When you ran out of file the buffer will contain it.
If you do not know the maximum length you can always read the file backwards.

Fortran randomely writing data in file

How to write a text or dat file in FORTRAN like a 2D array of integers and each time to enter a value, if in any row there is no value just insert in the start but if some values exists insert to the end of values. This insertion of values can be random, i.e. may be line number 100 first then 80 then 101 then 2. The number of entries in each line is also different.
I also need to use this file at the end but I think that will be easy as need line by line information.
Edit (what he ment possibly) :: How to write a text file in Fortran, like a 2D array of integers, each time adding one value? If there is an empty row with no values, insert one at the beginning of a row, but if there are already some values in that row, append the new value to the end of the row.
Have no idea what he was getting at with those random values and line numbers.
If you want to make decisions based on the input, read the line into a string. Then examine the contents of the string and decide which case of input. If you have numbers that you want to read, use an "internal read" to read them from the string. This question has a code example: Reading comment lines correctly in an input file using Fortran 90

writing a single line of a file in C++ into two different arrays

suppose a text file has 11001100 11001101
and i open the text file and take the input from the file as pt[0]=11001100, pt[1]=11001101..
but if i take the input from file as in>>pt it wont put it in two different arrays which is obvious but it takes the whole line . Thus I have to take another for loop and traverse through the whole string and when I find a null character i start putting into the second array . But how can I do it without putting it into a variable and traversing .. I mean directly from the file itself ..
Read it one byte at a time (e.g. with fread()). Append each byte to pt[i], where i is incremented when a space is encountered.

How to read partial data from large text file in C++

I have a big text file with more then 200.000 lines, and I need to read just a few lines. For instance: line 10.000 to 20.000.
Important: I donĀ“t want to open and search the full file to extract theses lines because of performance issues.
Is this possible?
If the lines are fixed length, then it would be possible to seek to a specific byte position and load just the lines you want. If lines are variable length, the only way to find the lines you're looking for is to parse the file and count the number of end-of-line markers. If the file changes infrequently, you might be able to get sufficient performance by performing this parsing once and then keeping an index of the byte positions of each line to speed future accesses (perhaps writing that index to disk so it doesn't need to be done every time your program is run).
You will have to search through the file to count the newlines, unless you know that all lines are the same length (in which case you could seek to the offset = line_number * line_size_in_bytes, where line_number counts from zero and line_size_in_bytes includes all characters in the line).
If the lines are variable / unknown length then while reading through it once you could index the beginning offset of each line so that subsequent reads could seek to the start of a given line.
If these lines are all the same length you could compute an offset for a given line and read just those bytes.
If the lines are varying length then you really have to read the entire file to count how many lines there are. Line terminating characters are just arbitrary bytes in the file.
If the line are fixed length then you just compute the offset, no problem.
If they're not (i.e. a regular CSV file) then you'll need to go through the file, either to build an index or to just read the lines you need. To make the file reading a little faster a good idea would be to use memory mapped files (see the implementation that's part of the Boost iostreams: http://www.boost.org/doc/libs/1_39_0/libs/iostreams/doc/classes/mapped_file.html).
As others noted, if you do not have the lines of fixed width, it is impossible to do without building the index. However, if you are in control of the format of the file, you can get a ~O(log(size)) instead of O(size) performance in finding the start line, if you manage to store number of the line itself on each line, i.e. to have the file contents look something like this:
1: val1, val2, val3
2: val4
3: val5, val6
4: val7, val8, val9, val10
With this format of the file, you can quickly find the needed line by binary search: start with seeking into the middle of the file. Read till the next newline. Then read the line, and parse the number. If the number is bigger than the target, then you need to repeat the algorithm on the first half of the file, if it is smaller than the target line number, then you need to repeat it on the second half of the file.
You'd need to be careful about the corner cases (e.g.: your "beginning" of the range and "end" of the range are on the same line, etc.), but for me this approach worked excellently in the past for parsing the logfiles which had the date in it (and I needed to find the lines that are between the certain timestamps).
Of course, this still does not beat the performance of the explicitly built index or the fixed-size records.