回 帖 发 新 帖 刷新版面

主题:[讨论]关于fortran读取各行长度不一格式不一具体行数不知数据文件的思考

iwanfly网友曾在一段时间前发过贴探讨过这个问题
http://bbs.pfan.cn/post-312402.html

当时思路不是很清晰
现思考结果如下,虽然比较麻烦,但最终还是解决了读取数据的问题,前提是知道每行最大的数据个数,比如7个。
不知道论坛上的网友是否有更好的方法,不吝赐教。

测试数据如下:
12  89  77
12  999 878  777
398 789 765 98 765
78 89
12  89  77
12  999 878  777
398 789 765 98 765
。。。。
总共78144行。大概需要5,6秒时间把数据全部读进。

program main
implicit none
integer,allocatable :: int_array(:,:),temp_array(:,:)
integer :: count,length,step,i,ierr
character*256 :: str_one_record
open(100,file='data.txt')

count=0
step=100000
length=step

allocate(int_array(length,7))

int_array=0
do while(.not. eof(100))
    count=count+1
    
loop1:  do i=7,1,-1
          read(100,'(A)',advance='no',eor=168) str_one_record
168       read(str_one_record,*,end=999) int_array(count,1:i)  
          exit loop1
999       backspace 100
          int_array(count,1:i)=0  
        end do loop1
    
    if(mod(count,step)==0) then
        allocate(temp_array(length,7))
        temp_array=0
        temp_array=int_array
        deallocate(int_array)
        length=length+step
        allocate(int_array(length,7))
        int_array=0
        int_array(1:length-step,:)=temp_array
        deallocate(temp_array)
    end if
    
end do

allocate(temp_array(length,7))
temp_array=0
temp_array=int_array
deallocate(int_array)
allocate(int_array(count,7))
int_array=0
int_array(1:count,:)=temp_array(1:count,:)
deallocate(temp_array)

!下面处理int_array中数据


deallocate(int_array)
close(100)

pause
end program main


回复列表 (共15个回复)

沙发

shenjinggege相当具有钻研精神,强烈要求加入石头的群:2338021

板凳

[quote]shenjinggege相当具有钻研精神,强烈要求加入石头的群:2338021[/quote]
申请了

3 楼

Visual Fortran打开文件有另外的一种方法,不知道是不是FORTRAN通用的。
默认情况下打开的文本文件都是List,而设置了那个后,就可以一个一个地读(它不会自动到下一行的)

4 楼

我是用那个 GetDataN

首先用字符串读入,再调用这个函数,得到包含的数据个数。

再读取。

Integer Function GetDataN( cStr )
    Implicit None
    Character*(*) , Intent( IN ) :: cStr
    Integer :: k
    GetDataN = 0
    If((cStr(1:1)/=" ".and.cStr(1:1)/="     ").and. &
       (cStr(2:2)==" ".or.cStr(2:2)=="     ".or.cStr(2:3)==" ")) then
       GetDataN = GetDataN + 1
    End If
    do k = 2 , Len( Trim( cStr ) ) - 2
      If((cStr(k:k)/=" ".and.cStr(k:k)/="     ".and.cStr(k-1:k)/=" ").and. &
           (cStr(k+1:k+1)==" ".or.cStr(k+1:k+1)=="     ".or.cStr(k+1:k+2)==" ")) then
        GetDataN = GetDataN + 1
      End If
    end do
    GetDataN = GetDataN + 1
  End Function GetDataN

5 楼

臭石头雪球  网友给的算法,当空格不定时,是不是“歇菜”了呢?

6 楼

! ReadIrregularDataFile.f90
!
! written by Zeng Zhuo-Quan

! date: 2009 - 12 - 08


  subroutine DataNo(str, ND)
    implicit none
    character(len = *), intent(in):: str
    integer, intent(out):: ND
    
    ! *** *** *** *** *** immediate variable *** *** *** *** ***
    logical:: LFT
    character(len = 1):: ch
    integer:: iL   ! for loop
    character(len = len(str)):: cstr
    integer:: str_len
    
    cstr = adjustL( str )
    ND = 0
    str_len = len_trim(cstr)
    IF ( str_len > 0 ) THEN   
      LFT = .true.    
      Do iL = 1, str_len, 1
        ch = cstr(iL : iL)
        If ( (ch /= " ") .and. LFT ) Then
          ND = ND + 1
          LFT = .false.
        Else If ( (ch == " ") .and. (.not. LFT) ) Then
          LFT = .true.    
        End If   !
      End Do      
    END IF   ! str_len > 0
    
    return  
  end subroutine

7 楼

! ReadIrregularDataFile.f90
!
! written by Zeng Zhuo-Quan

! date: 2009 - 12 - 08


Module ReadIrregularDataFile

contains
  subroutine ReadString(str, IA, ND)
    implicit none
    character(len = *), intent(in):: str
    integer, intent(out):: IA(:)
    integer, intent(out):: ND
    
    ! *** *** *** *** *** immediate variable *** *** *** *** ***
    logical:: LFT
    character(len = 1):: ch
    integer:: iL   ! for loop
    character(len = len(str)):: cstr
    integer:: str_len
    integer:: bi(size(IA))   ! begin index
    integer:: ei(size(IA))   ! end index

    ND = 0   
    cstr = adjustL(str) 
    str_len = len_trim(cstr)
    if ( str_len == 0 ) return

    LFT = .true.    
    Do iL = 1, str_len, 1
      ch = cstr(iL : iL)
      If ( ch /= " " .and. LFT ) Then
        ND = ND + 1
        LFT = .false.
        bi(ND) = iL
      Else If ( (ch == " ") .and. (.not. LFT) ) Then
        LFT = .true.    
        ei(ND) = iL - 1
      End If   !
    End Do      
    ei(ND) = str_len 
    
    Do iL = 1, ND, 1
      read(cstr(bi(iL) : ei(iL)), *) IA(iL)
    End Do   ! iL   
    IA(ND + 1 : size(IA)) = 0
 
    return  
  end subroutine 
  
  subroutine DataNo(str, ND)
    implicit none
    character(len = *), intent(in):: str
    integer, intent(out):: ND
    
    ! *** *** *** *** *** immediate variable *** *** *** *** ***
    logical:: LFT
    character(len = 1):: ch
    integer:: iL   ! for loop
    character(len = len(str)):: cstr
    integer:: str_len
    
    cstr = adjustL( str )
    ND = 0
    str_len = len_trim(cstr)
    IF ( str_len > 0 ) THEN   
      LFT = .true.    
      Do iL = 1, str_len, 1
        ch = cstr(iL : iL)
        If ( (ch /= " ") .and. LFT ) Then
          ND = ND + 1
          LFT = .false.
        Else If ( (ch == " ") .and. (.not. LFT) ) Then
          LFT = .true.    
        End If   !
      End Do      
    END IF   ! str_len > 0
    
    return  
  end subroutine 


End Module



program main
  use ReadIrregularDataFile
  implicit none
  integer, parameter:: NC = 100
  integer, parameter:: NR = 10
  integer:: IA(NR)
  integer:: IB(NR, NC)
  integer:: iL   ! for loop
  character(len = 300):: str_in
  character(len = 30):: fmt_str
  integer:: ND   ! 
  
  str_in = "  312 43    034   578  986  72786      12365    587363"
  call ReadString(str_in, IA, ND)
  fmt_str = "(??I7)"
  write(fmt_str(2 : 3), "(I2)") NR  
  write(*, fmt_str) IA

  open(unit = 5, file = "In05.dat")
  Do iL = 1, NC, 1
    read(unit = 5, fmt = "(A300)", end = 100) str_in
    call ReadString(str_in, IB(:, iL), ND)
  End Do   ! iL
100  close(5)
  ND = iL - 1
  
  open(unit = 6, file = "Out06.dat")
  Do iL = 1, ND, 1
    write(6, fmt_str) IB(1 : 10, iL)
  End Do   ! iL
  close(6)
  
  open(unit = 5, file = "In05.dat")
  Do iL = 1, NC, 1
    read(unit = 5, fmt = "(A300)", end = 200) str_in
    call DataNo(str_in, ND)
    read(str_in, *) IB(1 : ND, iL) 
  End Do   ! iL
200  close(5)
  ND = iL - 1
  
  open(unit = 7, file = "Out07.dat")
  Do iL = 1, ND, 1
    write(7, fmt_str) IB(1 : 10, iL)
  End Do   ! iL
  close(7)
        
  stop 
end program main 



! In05.dat
51201 1981 1 2 1 1931 2031 
51202 1982 1 1 0                   
51203 1983 1 2 1 1930 2030     
51204 1984 1 2 1 1932 2032  
51205 1985 1 2 1 1935 2035     
51216 1986 1 3 0
51217 1987 1 3 0
51218 1988 12 31 1 1430 1620
52999 1989 1 1 1 1050 1100
53000 1990 1 2
  312 43    034   578  986  72786      12365    587363
  13312 43    034   1578  9861  727863      123657    587363    993
                                              123               457

8 楼

1 Institute of High Energy Physics, CAS, P.O. Box 918–4, Beijing 100049, China
2 College of Physical Sciences, Graduate University of Chinese Academy of Sciences, Beijing 100049, China

呵呵

9 楼

学习

10 楼

read(100,'(A)',advance='no',eor=168) str_one_record
168       read(str_one_record,*,end=999) int_array(count,1:i)
这两句advance 和 end 是什么作用,看不大明白,请教!

我来回复

您尚未登录,请登录后再回复。点此登录或注册