2016-07-04 10 views
1

ファイルを書き込むFortran 90プログラムを使用しています。このファイルの最初の行は、残りのファイルの行数を示すはずです。このファイルは、ある基準が満たされ、それを事前に決定することができないときにプログラムによって書き込まれる。基本的には、走行終了後の総ライン数はわかります。Fortranを使用してファイルを上書きする

私は次のようにそれをしたい:

1)は、ファイルを開いて、いくつかのテキストは、言う「こんにちは

2との最初の行を書く)として、ファイル内の行を書きます希望の数とカウンタ行の数を維持します。

3)実行が何度だけファイルを閉じる前になると、カウンターとの最初の行の文字列(「こんにちは」)を交換してください。

問題は手順3です。最初の行を置き換える方法がわかりません。

もう1つのオプションは、2つのファイルに書き込むことです。まず、上記のようなファイルをカウンタなしで作成します。実行が終了したら、ファイルを閉じて別のファイルに書き込んでください。今回は、カウンタの値を知っています。

私は最初のアプローチを進める方法があると思います。誰かがこれで私を助けてくれますか?

答えて

2

行の長さが変わる可能性があるため、順次アクセスファイルに戻るのは難しいです。そして、1行の長さを変えれば、すべてのものを後ろに動かさなければなりません。

私は、行数を数えながら出力をスクラッチファイルに書き出すことをお勧めします。その後、終了したら、スクラッチファイルを巻き戻し、出力ファイルに行数を書き込み、スクラッチファイルの内容をその出力ファイルにコピーします。

ここに私がやったことだ:

program var_file 
    implicit none 
    character(len=*), parameter :: filename = 'delme.dat' 
    integer :: n, io_stat 
    character(len=300) :: line 

    open(unit=200, status='SCRATCH', action="READWRITE") 

    n = 0 

    do 
     read(*, '(A)') line 
     if (len_trim(line) == 0) exit ! Empty line -> finished 
     n = n + 1 
     write(200, '(A)') trim(line) 
    end do 

    rewind(200) 

    open(unit=100, file=filename, status="unknown", action="write") 
    write(100, '(I0)') n 

    do 
     read(200, '(A)', iostat=io_stat) line 
     if (io_stat /= 0) exit 
     write(100, '(A)') trim(line) 
    end do 

    close(200) 
    close(100) 

end program var_file 
+0

はあなたの詳細な回答やプログラムをありがとうございました。これは私のバックアップ計画でした。あなたはファイルを書き換えるためのコードを書いて私の時間を節約しました。 :) –

+0

これは私がそれをやる方法です。私は私が知らないより良いものがないという保証はしません。 – chw21

3

Fortranは、ファイルアクセスの三つの形式をサポート - DIRECT、STREAM(F2003 +)とSEQUENTIALを。 DIRECTアクセスとSTREAMアクセスの両方のサポートがファイルの以前の部分を書き換えることができ、SEQUENTIALアクセスは行われません(以前のレコードへの書き換えは、書き換えられたレコードでファイルを切り捨てます)。

直接アクセスでは、ファイル内のすべてのレコードの長さが同じです。ステートメントに関連レコード番号を指定するだけで、任意の入出力レコードで任意のレコードにアクセスすることができます。ただし、ダイレクトアクセスファイルの一般的なディスクフォーマットでは、ファイルの考え方が「行」と一致しないことがあります。

フォーマットされたストリームアクセスでは、ファイル内の現在の位置をINQUIREステートメントを使用して取得し、その後の入出力ステートメントはPOS指定子を使用してその位置でデータ転送を開始できます。フォーマットされたストリームアクセスファイルの典型的なディスクフォーマットは、通常、人々がラインを持つテキストファイルに期待するものと一致します。

ストリームアクセスが必要な場合があります。両方のアプローチの例を以下に示します。

直接アクセス:

PROGRAM direct 
    IMPLICIT NONE 

    INTEGER :: unit 
    REAL :: r 
    INTEGER :: line 

    OPEN(NEWUNIT=unit, & 
     FILE='direct.txt', & 
     STATUS='REPLACE', & 
     ACCESS='DIRECT', & 
     RECL=15, &  ! The fixed record length. 
     FORM='FORMATTED') 

    CALL RANDOM_SEED() 

    ! No need to write records in order - we just leave off 
    ! writing the first record until the end. 

    line = 0 
    DO 
    CALL RANDOM_NUMBER(r) 
    IF (r < 0.05) EXIT 

    line = line + 1 
    PRINT "('Writing line ',I0)", line 
    ! All the "data" records are offset by one, to allow the 
    ! first record to record the line count. 
    WRITE (unit, "('line ',I10)", REC=line+1) line 
    END DO 

    ! Now update the first record with the number of following "lines". 
    WRITE (unit, "(I10)", REC=1) line 

    CLOSE(unit) 
END PROGRAM direct 

ストリーム・アクセス:

PROGRAM stream 
    IMPLICIT NONE 

    INTEGER :: unit 
    REAL :: r 
    INTEGER :: line 
    INTEGER :: pos 

    OPEN(NEWUNIT=unit, & 
     FILE='stream.txt', & 
     STATUS='REPLACE', & 
     ACCESS='STREAM', & 
     POSITION='REWIND', & 
     FORM='FORMATTED') 

    CALL RANDOM_SEED() 

    ! Remember where we are. In this case, the position 
    ! is the first file storage unit in the file, but 
    ! it doesn't have to be. 
    INQUIRE(unit, POS=pos) 

    ! Leave some space in the file for later overwriting 
    ! with the number of lines. We'll stick the number 
    ! zero in there for now. 
    WRITE (unit, "(I10)") 0 

    ! Write out the varying number of lines. 
    line = 0 
    DO 
    CALL RANDOM_NUMBER(r) 
    IF (r < 0.05) EXIT 

    line = line + 1 
    PRINT "('Writing line ',I0)", line 
    WRITE (unit, "('line ',I10)") line 
    END DO 

    ! Now update the space at the start with the number of following "lines". 
    WRITE (unit, "(I10)", POS=pos) line 

    CLOSE(unit) 
END PROGRAM stream 
+0

ありがとうございました。 「ストリーム」のオプションは、私が行かなければならない方法です。どうやら、私のコンパイラはAccess = streamをサポートしていません。 –

+1

Fortran 90タグが見つかりませんでした。 StreamはFortran 2003の機能です。 – IanH

+0

最新のFortranコンパイラの多くは、2003年に「STREAM」を含めてサポートしています。このような場合にはうまくいきませんが、これは貴重な答えです。しかし、2003年に準拠したコンパイラでしか動作しないことを、回答自体に明確にすることをお勧めします。 – chw21

関連する問題