Read and write tab-delimited text data

2019-09-16 12:34发布

I have an excel output in the tab-delimited format:

temperature H2O  CO2     N2      NH3     
10  2.71539E+12 44374931376 7410673406  2570.560804
20  2.34216E+12 38494172272 6429230649  3148.699673
30  2.04242E+12 33759520581 5639029060  3856.866413
40  1.75491E+12 29172949817 4882467457  4724.305292
.
.
.

I need to convert these numbers to FORMAT(1X,F7.0,2X,1P4E11.3) readable for another code. This is what I've come up with:

 program fixformat

  real temp, neuts(4)
  integer i,j
  character header

  open(11,file='./unformatted.txt',status='old')
  open(12,file='./formatted.txt',status='unknown')

  read(11,*) header
  write(12,*) header

  do i = 1, 200
    read(11,*) temp, (neuts(j),j=1,4)
    write(12,23) temp, (neuts(j),j=1,4)
  end do

23    FORMAT(1X,F7.0,2X,1P4E11.3)
  close(11)
  close(12)

  return
 end

I keep getting this error:

Fortran runtime error: Bad real number in item 1 of list input

Is there any other way to convert the data to that format?

2条回答
我命由我不由天
2楼-- · 2019-09-16 13:30

To read tab delimited data, I'd use a simple algorithm like the one below. NOTE: This is assuming that there is no tab character in any of your fields.

        integer :: error_code, delim_index, line_index
        character*500 :: data_line, field_data_string
        double precision :: dp_value

        Open(Unit=1001,File="C:\\MY\\PATH\\Data.txt")

DO
   Read(UNIT=1001,End=106, FMT='(A)' ) data_line
   line_length = LEN(TRIM(data_line))
   delim_index = SCAN(data_line, achar(9) )
   line_index = 0
   DO WHILE ( delim_index .NE. 0 )
       line_index = line_index + delim_index
       IF (delim_index .EQ. 1 ) THEN ! found a NULL (no value), so skip
           GOTO 101
       END IF
       field_data_string = data_line( (line_index-delim_index+1) : line_index   )
       READ( field_data_string, FMT=*, ERR=100) dp_value
       PRINT *, "Is a double precision ", dp_value
       GOTO 101
       100 Continue
       PRINT *, "Not a double precision"
       101 Continue
        IF ( (line_index+1) .GT. line_length ) THEN
           GOTO 104 ! found end of line prematurely
        END IF
       delim_index = SCAN( data_line( line_index + 1 : ), achar(9) )
   END DO
   field_data_string = data_line( line_index + 1 :  )
   READ( field_data_string, FMT=*, ERR=102) dp_value
   PRINT *, "Is a double precision ", dp_value
   GOTO 103
   102 Continue
   PRINT *, "Not a double precision"
   103 Continue
    PRINT *, "Is a double precision ", dp_value
   104 Continue
END DO

            104 Continue
                PRINT *, "Error opening file"
            105 Continue
                Close(1001)
查看更多
Deceive 欺骗
3楼-- · 2019-09-16 13:32

You need a character string, not a single character for the header

character(80)  header

other than that you program works for me. Make sure you have the right number of lines in your loop

Do i=1,200

Adjust 200 to the real number of your data lines.

If for some reason you still cannot read even a single line, you can also use the format:

read(11,'(f2.0,4(1x,f11.0))') temp, (neuts(j),j=1,4)

because the tab is just a character you can easily skip.

Notes:

Unformatted and formatted means something completely different in Fortran. Unformatted is what you may know as "binary".

Use some indentation and blank lines for your programs to make them readable.

There is no reason to explicitly use status=unknown. Just don't put anything there. In your case status=replace may be more appropriate.

The FORMAT statement is quite obsolete, in modern Fortran we use format strings:

write(12,'(1X,F7.0,2X,1P4E11.3)') temp, (neuts(j),j=1,4)

There is absolutely no reason for your return before the end. Returns is for early return from a procedure. Some put stop before the end program, but it is superfluous.

查看更多
登录 后发表回答