Fortran/入出力文

出典: フリー教科書『ウィキブックス(Wikibooks)』

Fortranや他の言語では、何をどこに、どのように出力または入力するかを指定することがしばしば役立ちます。Fortranには、これらの目的に役立つ多くのコマンドやフォーマット仕様があります。次のセクションでは、I/O操作(opencloseinquirerewindbackspaceendfileflushprintreadwritenamelist)とI/Oフォーマット(format)を考慮します。Fortran 2008では、ユーザー定義のルーチンを使用して、他の派生型を含む派生型を出力するための基本的な機能を拡張する能力が大きな追加されています。

これらのコマンドは、直列、直接、または非同期アクセスでフォーマットされたおよびフォーマットされていないファイルを読み取り、書き込むための非常に強力なセットを形成します。実際、オプションは最初はややこしく見えるかもしれません。ただし、基本的な操作は非常にシンプルですが、ほぼどんなファイルでも読み取りまたは書き込みできるパワーと柔軟性で裏付けられています。

ただし、ここで言及する価値があることは、Fortranが言語定義の観点から単純で直接的に行えないことです。Fortranは、URLで定義されたファイルにアクセスすることはできません。ファイルはローカルで利用可能であるか、マップされたネットワークドライブまたは同等の場所にある必要があります。同様に、FortranはXMLをネイティブでサポートしておらず、ただしXMLは単純なASCIIテキストなので簡単に読み取れますが、パースはプログラマに委ねられます! Fortran言語はコンピュータグラフィックスについて何も知りません。言語定義の描画コマンドは見つけることはできません。Fortranは喜んでjpgファイルを開き、読み取りますが、ファイルを画像として表示する言語定義の方法はありません。適切な外部ライブラリを使用する必要があります。最後に、Fortranには言語定義のマウス操作やタッチスクリーンジェスチャーはありません。

I/O操作[編集]

はじめに[編集]

現代のFortranには、I/O操作の豊富な語彙があります。これらの操作は、一般的に画面とキーボード、外部ファイル、および内部ファイルで使用できます。最近のFortranのバージョンでは、これらのコマンドの構文が合理化されていますが、ほとんどの元の構文は後方互換性のために保持されています。I/O操作は、誤りが起こりやすく、Fortranは現在、エラーの識別と処理のための統一されたメカニズムをサポートしています。

簡単なI/O操作[編集]

Print[編集]

これは古典的な "Hello World" 操作ですが、本番コードではほとんど使用されません。printは、フォーマットされた出力操作のうちの1つであり、writeステートメントよりもはるかにシンプルです。 printステートメントの主な目的は、画面(標準出力ユニット)に出力することであり、ファイル出力のオプションはありません。一般的な形式は次のとおりです:

print fmt, list

fmtlistの両方はオプションであり、fmtは明示的またはリスト指向(*で示される)であり、オプションでname=value形式を取ることができます。リストは、リテラルまたは組み込み型の変数のカンマ区切りのリストです。以下にいくつかの例を示します:

program hello
    implicit none
    integer :: i

    ! List-directed fmt
    print *, "Hello World"
    do i = 1, 10
        ! An explicit fmt and a two element list
        print '(A,I0)', "Hello ", i
    end do
    ! Name=value for fmt
    print fmt='(A)', 'Goodbye'
end program hello

printは、iostatおよびiomsg節をサポートしていない唯一のI/O操作であることに注意してください。この理由だけで、一時的な出力やデバッグ以外では新しいコードで使用しないでください。 printにはユーザー定義の型を出力するための明示的なメカニズムがないため、本番コードで使用しない理由がもう1つあります

I/Oチャンネルとファイル[編集]

上記のprintの例では、printステートメントは自動的に標準出力デバイス(コンピュータ画面とも呼ばれる)に事前接続されています。ただし、一般に、Fortranではコードを外部ファイルに接続するために2段階のプロセスが必要です。まず、ファイルをFortranチャンネルに接続する必要があります(手動で正の整数または自動的に負の値が割り当てられます): openコマンド、次に、このチャンネルに接続されたファイルにreadおよびwriteできます。ファイルが開かれていないチャンネルにreadおよびwrite操作を行うと、エラーが発生します。該当するチャンネルが開かれるまで、関連するチャンネルのバッファリングはありません。I/O操作が完了したら、ファイルとFortranチャンネルの接続をcloseできます。Fortranプログラムがチャンネルをファイルに閉じる前に終了すると、Fortranは通常、データの重大な損失なしにチャンネルを閉じます。

Fortranチャンネルの利用可能性の状態は、一形式のinquireコマンドを介して確認できます。inquireコマンドは、ファイルがFortranチャンネルに接続される前に、ファイルの存在およびその他のプロパティを判別するためにも使用できます。

Fortranの内部ファイルへのI/Oは、事前接続プロセスを必要としません。Fortranキーボードからの入力および画面への出力は、特別なチャンネル (*) に自動的に事前接続されます。コンパイラベンダーは、これらの標準I/Oデバイスにチャンネル番号を割り当てることができ、ユーザーは、インストラクションモジュールiso_fortran_envを介して使用されたチャンネル番号を判断できます。

Open[編集]

これは外部ファイルとFortranチャンネルの間の接続を確立するために必要なコマンドです。 openコマンドは、新しいファイルの作成または既存のファイルへの接続に使用できます。一度開いたファイルへの以降のI/Oは、このチャンネル番号を介して行われます。 openコマンドには、ファイルがすでに存在するかどうか、入力専用であるか、出力専用であるか、または両方であるかを確認するオプションがあります。 openコマンドでファイルの予想される形式を指定し、エラーをトラップできます。コマンドの完全な構文はかなり複雑に見えるかもしれませんが、一般的には、openへの1回の呼び出しは、すべての利用可能なオプションの小さなサブセットのみを使用します。

openコマンドは、外部ファイルが通常カードイメージであったときに起源を持ちました。 openは現在、ファイルへの接続を固定形式、非同期、バイナリストリーム、およびこれらの多数の組み合わせで指定できることを示すことができます。I/Oは、コーディングエラーの主要な源泉であり、重要なデータが読み取られる場所では、正しい処理を確認するために再度書き込まれるべきです。

Fortranチャンネル番号の値は、Fortranプログラムの1つのイメージ内でグローバルなスコープを持ちます。整数変数がチャンネルを開くために使用され、その変数のスコープが非常に限られている場合でも、実際のチャンネル番号は事実上どこでも使用できます。これは設計時に考慮する必要があります。なぜなら、1つのモジュールが、チャンネル10を開くことができ、別のモジュールがチャンネル10を使用せずにチャンネル10を閉じることができるからです。したがって、大規模なプログラムでは、ファイルI/O操作を制御するために単一のモジュールが使用されることがよくあり、明確で明白な「オープン - 読み取り/書き込み - クローズ」チェーンを維持できます。

最後に、通常のFortranと同様に、新しいコードで使用しないでくださいが、遺産目的で保持されているオプションと節があります。

Open コマンドの構文[編集]

open ([unit=]u[, olist])

[]内のセクションはオプションであり、olistはオプションのリストであり、カンマで区切られています。上記のuはスカラー整数式または同等であり、newunitオプションが指定されていない限り必須です。 (不運なことに、1つのopenステートメントで複数のファイルを開くことはできません)。技術的には、uは外部ファイルユニット番号と呼ばれますが、チャンネル番号は略称です。

共通オプション[編集]

newunit=nu、nuはデフォルトの整数変数です。これにより、プロセッサはチャンネル番号を選択し、適切なチャネル番号が現在使用中の任意のユニット番号と競合しないように、(-1ではない)負の値が選択されます。これはすべての新しいコードで使用されるべき形式です。

iostat=ios、iosはデフォルトの整数変数で、openステートメントでエラーが検出されない場合は0に設定されます。エラーが発生した場合、返される値は正に設定され、正確な値はベンダーに依存します。技術的にはオプションですが、すべてのopenコマンドでこのオプションが使用されることを強くお勧めします。このオプションが存在しない場合(およびerr=オプションが存在しない場合、以下参照)、プログラムはエラーが発生すると停止します。このオプションの存在は、プログラマーに値を確認してプログラムを適切に動作させる責任を与えます。

iomsg=iom、iomはデフォルトのキャラクター変数のスカラーです。再度、技術的にはオプションですが、すべての新しいコードでopenコマンドにこのオプションを強くお勧めします。メッセージの長さはエラーとベンダーに依存し、いくつかのトライアンドエラーが必要になる場合があります。

file=fln、flnはデフォルトの文字変数、リテラル、または式であり、外部ファイルの名前を指定します。ファイル名は完全修飾パスまたはローカルファイル名にすることができます。パスがネットワークドライブ上のファイルを指す場合、ドライブは事前に接続されている必要があり、この接続を行う言語定義された方法はありません。 (ただし、 execute_command_lineにいつでも戻ることができます)

status=stn、stnもデフォルトの文字変数、リテラル、または式であり、 'old'、 'new'、 'replace'、 'scratch'、または 'unknown'のいずれかに評価される必要があります。 'old'はファイルが存在することを要求し、通常、openステートメントの目的がファイルの読み取りを許可するために使用されます。 'new'および 'replace'は、上記で説明したfile=オプションの存在を要求し、 'new'はファイルが存在しないことを要求し、 'replace'はファイルがすでに存在していても、存在する場合は上書きされます。 'scratch'は特別であり、file=オプションを使用してはいけず、作成されるファイルはcloseコマンドの後のサブセクエントの実行中に保持できません。 'scratch'は、大容量データ構造の一時的な保管場所として、ハードディスクや類似の大容量ストレージに通常使用されます。 'unknown'が指定された場合、これはstatus=オプションの不正な使用を示します。

access=acn、acnはデフォルトの文字変数、リテラル、または式であり、 'sequential'または 'direct'のいずれかである必要があります。これは、I/Oの方法を指定します。 'sequential'は、通常、1つのレコードが前に読み込まれたファイルに対して使用され、 'direct'は、通常、ランダムなアクセスが許可されるファイルに対して使用されます。これにより、後者のファイルはrecordlengthオプションまたはファイルの構造に従って固定レコード長である必要があります。

form=frmn、frmnもデフォルトの文字変数、リテラル、または式であり、 'formatted'または 'unformatted'のいずれかである必要があります。これは、読み書きの形式を指定します。 'formatted'は、読み取りや書き込みが特定のフォーマット指定子に従って行われることを意味し、 'unformatted'は、バイナリストリームが単純なバイトレベルでのみ処理されることを意味します。

Openの簡単な例[編集]

program opena
    implicit none
    integer :: nout !channel number
    integer :: my_iostat !integer scalar to catch error status
    character (len=256) :: my_iomsg !Default-kind character variable to catch error msg

    open (newunit=nout, file="local.dat", iostat=my_iostat, iomsg=my_iomsg)
    if (my_iostat /= 0) then
        write (*,*) 'Failed to open local.dat, iomsg='//trim(my_iomsg)
        stop
    end if
    write (nout,*) 
end program

あまり一般的ではないオプション[編集]

access=acl ここで acl は、'sequential'、'direct'、'stream' のいずれかで評価される文字式、変数、またはリテラルです。既に存在しているファイルを開く場合、この値は許可された値に対応していなければなりません。この値は通常、ファイルが作成されたときに与えられた値です。新しいファイルを開くときのデフォルトは 'sequential' です。'stream' アクセスは Fortran 2008 の新機能で、C のバイナリストリームファイルとの互換性があります。ストリーム」アクセスのもう一つの重要な機能は、ファイルを書き込み用に配置し、ファイルの残りの部分を変更することなくファイルの一部を上書きできることです。フォーマットされたストリームファイルの場合、 new_line(nl)関数は、関連する改行文字を文字変数 nl に返します。

recl=rcl ここで rcl は正の値に評価されなければならない整数式、変数またはリテラルである。ファイルが直接アクセスのために開かれる場合、この「オプション」は必須であり、 各レコードの長さを指定しなければならない。シーケンシャルファイルの場合はオプションで、レコードの最大長を指定するために使用できます。すでに存在するファイルの場合、rclの値はファイルの作成に使用された値と一致しなければならない。どのような場合でも、rclの値は、基礎となるオペレーティングシステムで許可されていなければならない。

form=frm frmは、'formatted' または 'unformatted' と評価される文字式、変数またはリテラルである。デフォルトでは、'sequential' アクセスの場合は 'formatted' 、'direct' アクセスの場合は 'unformatted' となるため、このオプションは省略できることが多い。

blank=blk ここで、blkは文字式、変数、またはリテラルであり、フォーマットされたi/oのみで 'null' または 'zero' の値を提供する。以下のbnおよびbzフォーマットを参照。

position=psn ここでpsnは、 'asis'、 'rewind' または 'append' として評価される文字式、変数またはリテラルであり、アクセス方法がシーケンシャルの場合にのみ適用される。初期値は 'asis' です。開くとき、新しいファイルは常に初期位置に配置されますが、既存のファイルの場合、ユーザーは現在の位置をどこに配置するかを選択することができます。

delim=

pad=

避けるべきオプション[編集]

世の中には多くのレガシーコードがありますが、このセクションでは、まだ有効ではあるものの置き換えを検討すべきであり新しいコードでは絶対に使用してはならない機能について説明します。

err=eno enoはリテラルの整数のラベル番号です。open文の処理でエラーが発生した場合、プログラムはラベル番号 eno の文に制御を移します。err=オプションがあると、エラーが発生した場合にプログラムが続行されました。このオプションは、現在では iostat=iomsg= で置き換えるべきです。(err=iostat=の両方を指定することは有効ですが、どちらもないとopen文の処理でエラーが発生した場合にプログラムが停止してしまいます)。

unit=nu ここで、nuはデフォルトの整数式、変数、リテラル値で、正の値でなければならず、既に使用されているどの単位とも一致してはならない。このオプションがオプションのリストの最初に置かれている場合、unit= は省略できます。これは非常に広く使われていましたが、現在ではnewunit=に置き換えられるべきです。非常に古いコードでは、nuは固定値であり、プログラマは同時に使用されている他のチャンネルと衝突しないようにしなければなりませんでした。最近では、inquireステートメントは、まだ使用されていないユニット番号を選択するために使用することができますが、これは後続のopenステートメントが既に使用されている固定値を使用しようとすることを防ぐことができませんでした。これが、newunitオプションだけが、チャンネル番号に負の値を指定することができる理由です。

Read文[編集]

read文は、指定された形式の入力から、変数を読み出す文である。たとえば、以下のようになります。

program reada
    implicit none
    integer :: a

    read (*,*) a
end program

このコードは、a用の整数メモリ領域を確保し、デフォルトの入力からデフォルトのフォーマットで値を読み込み、それをaに格納します。(*,*)の最初の*は、値がどこから読み込まれるかを意味する。2番目の*は、ユーザーが数値を読み取る際に必要なフォーマットを指定します。まず、利用可能なフォーマット文字列について説明します。Fortranでは多くのフォーマット文字列が用意されており、画面上での数値や文字列の表示方法を指定することができます。固定小数点のリアルの場合 Fw.d; wは数値に割り当てられたスペースの総数、dは小数点以下の桁数です。小数点以下の位置は常に1つの位置を占めます。たとえば、以下のようになります。

program reada
    inplicit none
    real :: a

    read (*,'(F5.2)') a
end program

I/Oフォーマット(例:'(F5.2)')の詳細は以下の通りです。

Write[編集]

Inquire文[編集]

inquire文には2つの基本的な形があります。「inquire by unit」と「inquire by file」で、どちらも非常に便利で、知っておく価値があります。inquire by length "と呼ばれるより曖昧な形式もありますが、 これは、必要なレコード長を決定するために、潜在的な出力のフォーマットされていない レコード長をチェックしたり、すでに定義されたレコード長を持つファイルが 与えられた出力に対応できるかどうかをチェックするのに便利です。

Inquire by unit[編集]

Inquire by file[編集]

Inquire by length[編集]

inquireコマンドのやや曖昧なバージョンは、 与えられた形式の出力を含むために必要な、フォーマットされていない レコードの長さを取得するために使用され、ユーザは必要なレコードの 長さを確認したり指定したりすることができます。

Inquire errors[編集]

Close文[編集]

closeコマンドは、ファイルとFortranチャンネルの間の接続を解除します。その過程で、ファイルがどのように開かれたかに応じて、ファイルは保存されたり、破棄されたりします。closeコマンドの一般的な形式は以下の通りです。

close ([unit=]u, [, olist])

ここで、uはクローズするチャンネルの番号として評価されるデフォルトの整数式、変数、リテラル値で、unit=はオプションです。オプション・リストで使用できるオプションは以下のとおりです。

iostat=ios iosはデフォルトの整数変数で、closeコマンドが正しく実行された場合には値0を返します。エラーが発生した場合には、戻り値は正の値となり、後述のiomsgオプションによってエラーを説明するメッセージが提供される。

err=eno ここでenoはリテラルの整数のラベル番号です。close文の処理でエラーが発生した場合、プログラムはラベル番号enoの文に制御を移します。err=オプションがあると、エラーが発生した場合にプログラムが続行されていました。このオプションは、現在では iostat=iomsg= で置き換えるべきである。(err=iostat=の両方を指定することは合法ですが、どちらも指定しないとopen文の処理でエラーが発生した場合にプログラムが停止してしまいます)。

iomsg=iom ここで、iomは、デフォルトの種類のスカラ文字変数です。繰り返しになりますが、技術的にはオプションですが、新しいコードのすべてのcloseコマンドには、このオプションを強く推奨します。メッセージの長さはエラーやベンダーに依存するので、試行錯誤が必要かもしれません。

status=st

Close に関するエラー[編集]

直感的ではないかもしれませんが、Fortranはすでに閉じられているチャネルをCLOSEしようとすることをエラーとはみなしません。inquireopenのように、 closeが報告するエラーは、事実上のオペレーティングシステム・エラーです。例えば、既に閉じられているチャネル上で status="delete" を持つ close は、特にファイルがもはや存在しない場合にはエラーとなります。同様に、Fortranでは、'scratch' として作成されたファイルをstatus="keep"でクローズするとエラーになります。これらの制限は、iostat(およびiomsg)句が、ユーザが必要に応じて緩やかな終了をプログラムするために使用されることを前提としており、closeコマンドのパフォーマンスに関する完全なレポートを得るためではありません。

I/O フォーマット[編集]

リスト指向のフォーマット[編集]

明示的なフォーマットについては後述しますが、「言語の中の言語」というものが存在することはすぐにわかりますので、Fortranではショートカット、つまり言語で定義されたフォーマットの推測を行います。このデフォルトフォーマットは、入力用のカンマ区切り変数(CSV)プロセッサに非常に近いことがわかります。リスト指向のI/Oはfmt=*節で指定しますが、fmt節はオプションで、単に*で置き換えることができます。

明示的なフォーマット[編集]

Fortranには、I/O操作のフォーマットを制御するための、豊富だが非常に簡潔な言語があります。フォーマット・コマンドは明示的なfortmat文の中に置くことができ、また、関連するREADまたはWRITE文の節の中に文字通り置くことも、character変数に格納することもできます。