Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Fortran 从未格式化文件读取字符串(可变记录长度)_Fortran_Binaryfiles - Fatal编程技术网

Fortran 从未格式化文件读取字符串(可变记录长度)

Fortran 从未格式化文件读取字符串(可变记录长度),fortran,binaryfiles,Fortran,Binaryfiles,我有一个未格式化的Fortran文件,其中包含不同长度的字符串,我用Fortran本身读取这些字符串时遇到困难 示例程序: 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)

我有一个未格式化的Fortran文件,其中包含不同长度的字符串,我用Fortran本身读取这些字符串时遇到困难

示例程序:

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
此操作失败(使用gfortran编译),原因是:

我可以通过减少读取长度和退格(
read\u string
subroutine)来尝试读取,但这看起来效率很低:

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

有没有更好的方法从未格式化文件中读取可变长度字符串?

我稍微修改了您的示例程序,以二进制格式读取文件。这适用于英特尔的编译器;gfortran不知道二进制格式,所以ymmv。 看看我的想法是从哪里来的

它的产量是

测试字符串
另一个较长的测试字符串

现在您已经知道了线的长度,trim()实际上不再需要了。只用

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

这还可以防止在数据中添加“较短的测试字符串”时出现问题。

简短的回答是不要使用未格式化的fortran。正如你所见,你需要了解结构。如果您有以这种方式编写的遗留文件,则可以打开直接访问或流,并解密所谓的未格式化格式。这可能比您已经制定的解决方案更痛苦。如果您真的想用这种方式写入文件,有两种方法可以将所有内容空白填充到固定长度,或者在每个字符串前面加一个整数记录,告知读取代码要读取的字符串的长度。@george不幸的是,我必须处理遗留文件(或由遗留代码编写的文件,必须向后兼容,因为有其他C代码读取它们)。但修改写入代码以填充所有字符串看起来是一个可能的解决方案。好吧,讽刺的是,您的C代码必须读取指定记录字节长度的“格式”,因此C“知道”字符串的长度。您可以研究C并考虑在FORTRAN中执行同样的操作(如我所说的,您需要打开直接访问或流)……玩了一点,直接Acess方法是非常痛苦的,因为您需要OT读取1字节记录(因为您的可变长度字符串)--如果您有一个具有流访问功能的f2003编译器,可能值得一试。
form=“binary”
早已被标准
access=“stream”
所取代,甚至在上面的评论中也提到了该标准。
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
write(6,*) line(1:recl_at_start)