从无格式文件中读取字符串(可变记录长度) [英] Reading strings from unformatted files (variable record length)

查看:479
本文介绍了从无格式文件中读取字符串(可变记录长度)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个未格式化的Fortran文件,其中包含不同长度的字符串,而且我在使用Fortran本身读取这些字符串时遇到问题。

示例程序

 程序测试
隐式无
字符(len = 200):: line

open(32,file =testfile,form =unformatted,action =write)
write(32)测试字符串
write(32)另一个更长的测试字符串
close(32)

open(33,file =testfile,form =unformatted,action =read)
read(33)line
write(6,*)trim(line)
read(33)line
write(6,*)trim(line)
close(33)

end程序测试

失败(用gfortran编译):

 在文件test.f90的第11行(单元= 33,file ='testfile')
Fortran运行时错误:未格式化的I / O末尾记录文件

我可以通过减少长度和退格来读取它的工作( REA d_string 子例程),但这看起来效率很高:

 程序测试
隐式无
字符(len = 200):: line

open(32,file =testfile,form =unformatted,action =write)
write(32) 一个测试字符串
write(32)另一个更长的测试字符串
close(32)

open(33,file =testfile,form =unformatted (6,*)trim(line)
call read_string(33,line)
write(6,*)trim(line)
call read_string(33,line)
write ,*)trim(line)
close(33)

包含

子程序read_string(u,字符串)
整数,意图(in): :u
character(len = *),intent(out):: string
integer :: i,error

do i = len(string),0,-1
read(u,iostat = error)string(:i)
if(error == 0)然后
string(i + 1 :) =''
exit
end if
backspace(u)
end do

end子程序read_string

结束程序测试

是否有更好的阅读方式?可变长度的字符串从无格式文件?

解决方案

我稍微修改了示例程序,读取 EM>。这适用于英特尔的编译器; gfortran不知道二进制格式,所以ymmv。
查看我在哪里获得了我的想法 Intel对记录类型的引用

test
implicit none
character(len = 200):: line
integer(4)recl_at_start,recl_at_end

open(32,file =testfile,form =unformatted,action =write)
write(32)测试字符串
write(32)另一个更长的测试字符串
close(32)

!需要初始化以填充空白
!因为trim()在填充零字符的行上不起作用
line =

open(33,file =testfile,form =binary,action =read )

read(33)recl_at_start
read(33)line(1:recl_at_start)
read(33)recl_at_end
write(6,*)trim(line )

read(33)recl_at_start
read(33)line(1:recl_at_start)
read(33)recl_at_end
write(6,*)trim(line )

关闭(33)

结束程序测试

它的输出是


测试字符串

另一个更长的测试字符串


现在你已经知道了行长了, trim()不再是必须的了。只需使用

  write(6,*)line(1:recl_at_start)

这样可以避免在向数据添加A short test string时出现问题。


I have an unformatted Fortran file, containing strings of different lengths, and I'm having trouble reading these strings with Fortran itself.

Sample program:

program test
implicit none
character(len=200) :: line

open(32,file="testfile",form="unformatted",action="write")
write(32) "A test string"
write(32) "Another longer test string"
close(32)

open(33,file="testfile",form="unformatted",action="read")
read(33) line
write(6,*) trim(line)
read(33) line
write(6,*) trim(line)
close(33)

end program test

This fails (compiled with gfortran) with:

At line 11 of file test.f90 (unit = 33, file = 'testfile')
Fortran runtime error: I/O past end of record on unformatted file

I could get it to work by trying the read with decreasing lengths and backspacing (read_string subroutine), but this looks highly inefficient:

program test
implicit none
character(len=200) :: line

open(32,file="testfile",form="unformatted",action="write")
write(32) "A test string"
write(32) "Another longer test string"
close(32)

open(33,file="testfile",form="unformatted",action="read")
call read_string(33,line)
write(6,*) trim(line)
call read_string(33,line)
write(6,*) trim(line)
close(33)

contains

subroutine read_string(u,string)
integer, intent(in) :: u
character(len=*), intent(out) :: string
integer :: i, error

do i=len(string),0,-1
  read(u,iostat=error) string(:i)
  if (error == 0) then
    string(i+1:) = ''
    exit
  end if
  backspace(u)
end do

end subroutine read_string

end program test

Is there a better way to read variable-length strings from unformatted files?

解决方案

I slightly reworked your sample program, reading the file in binary. This works for Intel's compiler; gfortran does not know the binary format, so ymmv. See where I got my ideas at Intel's reference on record types

program test
implicit none
character(len=200) :: line
integer(4) recl_at_start, recl_at_end

open(32,file="testfile",form="unformatted",action="write")
write(32) "A test string"
write(32) "Another longer test string"
close(32)

! initialization is required to fill the line with blanks
! because trim() does not work on line filled with zero characters
line = ""

open(33,file="testfile",form="binary",action="read")

read(33) recl_at_start
read(33) line(1:recl_at_start)
read(33) recl_at_end
write(6,*) trim(line)

read(33) recl_at_start
read(33) line(1:recl_at_start)
read(33) recl_at_end
write(6,*) trim(line)

close(33)

end program test

its output is

A test string
Another longer test string

Now that you know the line length, trim() is not really necessary anymore. Just use

write(6,*) line(1:recl_at_start)

This also prevents troubles when you add "A shorter test string" to the data.

这篇关于从无格式文件中读取字符串(可变记录长度)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆