Reading variable length characters from file

Is there a way to read variable length characters from file in Fortran.
One solution is to declare a big character and trim it accordingly like

character(len = 100) :: a

open(unit = 10, file = 'data.txt', status = "old" )
read(10,*) a
a = trim(a)

Is there any other way ?

The line a = trim(a) does not do anything useful. Blanks are removed from the right end of the variable a, but the assignment adds blanks to pad up the variable to its declared length.

You write about “variable length characters”, and I find that a bit confusing, because the common word “character” is not the same as a Fortran variable of type character. At first, I thought that you were writing about UTF-8 characters.

If you expand on what you are planning to do, i.e., how you want to process input lines of text after reading them, some suggestions could become available. Perhaps, you may find variables of type character(len=:), allocatable appropriate.

But before reading them, I have to allocate anyway !
Let us say I am reading:


But for another run they can be varyiing. Like


How can I accommodate both cases ?

For sequential access, an I/O connection has a maximum record length, so you can use it.


READ (UNIT=10,FMT=*,IOSTAT=iostat) str

You can specify a maximum record length when you OPEN a formatted I/O connection (with the same RECL specifier). If you don’t specify, you get a compiler default.

The bad news is that compilers do wildly different things for this default

1. nagfor 7.0: default record length is 65536
2. ifort 2021.1.2:                      132
3. gfortran 11.2.0:                     2147483647
4. cray fortran 12.0.3                  32767
5. nvfortran 21.9:                      0 (can't be set with OPEN anyway, broken)
6. aocc 3.1.0:                          0 (can't be set with OPEN anyway, broken)

Thanks it worked !

Sorry, I do not understand why you think that a file containing ‘beam’ and ‘column’ is different in structure from another file containing ‘dispbeam’ and ‘longcolumn’. Both files contain a word on each line. The words are of varying lengths. The first file contains words that are 4 and then 5 characters. The second, 8 and 10. The two files are structurally similar.

In general, you will not know when writing your program what the lengths of the lines in the data files are going to be. You have to decide in advance the maximum length of the lines in data files, document that limit and, if feasible, write your program to detect lines that are longer than that limit and fail gracefully.

If you have not previously read this article, you may find it worth your time.


This works for unformatted data as well:

character(len=:), allocatable :: buffer
integer :: fu, n, rc

open (access='stream', action='read', file='myfile.txt', &
      form='unformatted', iostat=rc, newunit=fu)
if (rc /= 0) stop 'Error: opening file failed'

inquire (fu, size=n)
allocate (character(len=n) :: buffer)
read (fu, iostat=rc) buffer
close (fu)

There are other ways as well. Depending exactly on what you are going to do with the string and how much data you are going to read some solutions are better than others. An example of reading a line of arbitrary length is also in the Fortran Wiki readline,

1 Like

Thanks for the link !
In fact I was searching for it in the entire discourse - but unable to get it.

Yes. But if we want to write a program which has it’s own commands - then we have to have some flexibility. Something like a file parser.
Now depends on whether the command is “beam” or “dispbeam” different functions and subroutines are invoked.
Hope you understand !

If the readline example was along the lines of what you were thinking, especially if you are an fpm user you might want to see getline(3f) and read_line(3f) in

as well as the Fortran wiki. Note that the getline(3f) routine is very similar, but it points out to made sure the input file has the PAD attribute set (which is typical, but not guaranteed to be on unless explicitly specified) when using the technique used in readline.

1 Like