Fortran プログラミングガイド | ![]() ![]() ![]() ![]() ![]() |
第 2 章
Fortran 入出力
この章では、Sun Fortran コンパイラが提供する入出力機能を説明します。
Fortran プログラムからファイルに探査する
プログラムとデバイスまたはファイルとの間でデータの転送は、Fortran 論理ユニットを通じて行います。論理ユニットは、入出力文において、論理ユニット番号で識別されます。論理ユニット番号は、0 から 4 バイト整数の最大値まで (2,147,483,647) です。
文字 * が論理ユニット識別子として現れることがあります。アスタリスクは、
READ
文に現れたときは標準入力ファイル、WRITE
文またはFortran 論理ユニットは、
OPEN
文を通じて、特定の名前付きファイルに関連付けることができます。また、割り当て済みユニットは、プログラムの実行開始時に自動的に特定のファイルに関連付けられます。名前付きファイルに探査する
OPEN
文のFILE=
指定子は、実行時に、名前付き物理ファイルへの論理ユニットの関連付けを行います。ファイルはあらかじめ存在しているものでもかまいません。また、プログラムの実行時に作成することもできます。OPEN
文に関する詳細は、『FORTRAN 77 言語リファレンス』を参照してください。
OPEN
文のFILE=
指定子は、簡単なファイル名 (FILE='myfile.out'
) を指定することも、絶対ディレクトリパスか相対ディレクトリパスを前に付けたファイル名
(FILE='../Amber/Qproj/myfile.out'
) を指定することもできます。また、指定子は、文字定数、変数、文字式のどれでもかまいません。ライブラリルーチンを使用して、コマンド行引数と環境変数を文字変数としてプログラムに渡し、
OPEN
文でファイル名として使用できます。詳細は、getarg
(3F) とgetenv
(3F) のマニュアルページを参照してください。これらのライブラリルーチンとその他の有用なライブラリルーチンについては、『Fortran ライブラリ・リファレンス』でも解説しています。次の例 (
GetFilNam.f
) は、入力された名前から絶対パスファイル名を作成する 1 つの方法を示しています。このプログラムは、ライブラリルーチンのGETENV
、LNBLNK
、GETCWD
を使用して、$HOME
環境変数の値を取り出し、文字列中の最後の非空白を見つけ、現在の作業用ディレクトリを決定するものです。
GetFilNam.f
のコンパイルと実行の結果は、次のようになります。
demo%pwd
/home/users/auser/subdirdemo%f77 -silent -o getfil GetFilNam.f
demo%getfil
anyfile
/home/users/auser/subdir/anyfiledemo%名前を指定しないでファイルを開く
OPEN
文には名前を指定する必要はありません。実行時システムがいくつかの規約に従い、ファイル名を補います。一時ファイルとして開く場合
OPEN
文でSTATUS='SCRATCH'
を指定すると、システムはtmp.F
AAAxnnnnn という形式の名前でファイルを開きます。nnnnn は現在のプロセス ID で置き換えられ、AAA は 3 文字の文字列、x は英字を示します。AAA と x によってファイル名が一意になります。このファイルは、(f77
で)CLOSE
文にSTATUS='KEEP'
が指定されていない限り、プログラムの終了、またはCLOSE
文の実行で削除されます。すでに開いている場合
すでにプログラムによってファイルが開かれている場合、その後の
OPEN
文にファイルの論理ユニット番号と変更するパラメータだけを指定して、ファイルの特性 (たとえば、BLANK
とFORM
) を変更できます。あらかじめ接続されたユニット
プログラムの実行開始時、3 つのユニット番号が自動的に特定の標準入出力ファイルに関連付けられます。あらかじめ接続されるユニットは、標準入力、標準出力、標準エラーです。
- 標準入力は論理ユニット 5 (Fortran 90 ユニット100 も接続)
- 標準出力は論理ユニット 6 (Fortran 90 ユニット101 も接続)
- 標準エラーは論理ユニット 0 (Fortran 90 ユニット102 も接続)
通常、標準入力は、ワークステーションのキーボードから入力を受け取ります。標準出力と標準エラーは、ワークステーションの画面に出力を表示します。
その他の場合、つまり、
OPEN
文に論理ユニット番号を指定し、「FILE =
名前」を指定しない場合、ファイルはfort.
n という形式の名前で開かれます。n は論理ユニット番号です。
OPEN
文を使用せずにファイルを開くデフォルトの規約が想定できる場合、
OPEN
文は使用しなくてもかまいません (任意です)。論理ユニットへの最初の操作がOPEN
またはINQUIRE
以外の入出力文である場合、ファイルfort.
n が参照されます。n は論理ユニット番号です (特別な意味を持つ、0、5、6 を除きます) 。これらのファイルは、プログラムの実行の前に存在する必要はありません。ファイルへの最初の操作が
OPEN
文またはINQUIRE
文でない場合、ファイルは作成されます。例: 次のコード中の
WRITE
文がユニット 25 に発行される最初の入出力文である場合、ファイルfort.25
が作成されます。
demo%cat TestUnit.f
IU=25WRITE( IU, '(I4)' ) IUENDdemo%このプログラムは、ファイル
fort.25
を開いて、そのファイルに書式付き記録を 1 つ書き込みます。
demo%f77 -silent -o testunit TestUnit.f
demo%testunit
demo%cat fort.25
25demo%ファイル名をプログラムに渡す
ファイルシステムは、Fortran プログラム中の論理ユニット番号を自動的に物理ファイルに関連付けるための機能をもっていません。
しかし、Fortran プログラムにファイル名を渡す方法はいくつかあります。
実行時引数と
GETARG
を経由するライブラリルーチン
getarg
(3F) を使用して、実行時にコマンド行引数を文字変数に読み込むことができます。引数はファイル名として解釈され、OPEN
文のFILE=
指定子で使用されます。
環境変数と
GETENV
を経由する同様に、ライブラリルーチン
getenv
(3F) を使用して、実行時に環境変数の値を文字変数に読み込むことができます。この値はファイル名として解釈されます。
getarg
またはgetenv
を使用するときには、前後の空白に気をつけなければなりません。(FORTRAN 77 プログラムはライブラリ関数LNBLNK
を、Fortran 95 プログラムは組み込み関数TRIM
を使用できます。) この章のはじめにある例のFULLNAME
関数行を用いれば、相対パス名を利用できるようにもプログラムできます。
f77:
IOINIT
を使用して論理ユニットをあらかじめ接続するまた、
f77
においては、ライブラリルーチンIOINIT
を使用して、実行時に論理ユニットを特定のファイルに接続することもできます。IOINIT
は、ユーザーが指定した形式の名前を環境から検索し、対応する論理ユニットを、書式付き順番入出力用に開きます。名前は、一般形式の PREFIXnn でなければなりません。ここで、PREFIX はIOINIT
への呼び出しで指定するもので、nn は開く論理ユニットです。ユニット番号が 1 桁の場合は、先頭に「0」を付けなければなりません。詳細はIOINIT
(3F) のマニュアルページを参照してください。IOINIT
機能はf95
には実装されていません。例: 現在のディレクトリにある物理ファイル
test.inp
とtest.out
に論理ユニット 1 と 2 を関連付けます。
demo$ TST01=ini1.inpdemo$ TST02=ini1.outdemo$export TST01 TST02
demo% setenv TST01 ini1.inpdemo% setenv TST02 ini1.out
ini1.f
プログラムがユニット1
を読み、ユニット2
に書き込みます。
環境変数と
ioinit
を使用して、ini1.f
はini1.inp
を読み取り、ini1.out
に書き込みます。
demo% cat ini1.inp12 3.14159012 6demo%f77 -silent -o tstinit ini1.f
demo% tstinitdemo% cat ini1.out12 3.14159 6demo%
IOINIT
は、このような形式でほとんどのプログラムで利用できます。ただし、このルーチンはユーザーが作成する同様のルーチンの例として利用できるよう、特に Fortran で書かれています。このプログラムのコピーは、FORTRAN 77 パッケージインストールの一部であるファイル/opt/SUNWspro/<
release>/src/ioinit.f
から入手できます。ただし <release> はソフトウェアのリリースごとに異なります (詳細についてはシステム管理者に問い合わせてください)。コマンド行における入出力のリダイレクトとパイプ
物理ファイルをプログラムの論理ユニット番号と関連付けるもう 1 つの方法は、あらかじめ接続された標準入出力ファイルをリダイレクトまたはパイプする方法です。リダイレクトやパイプは、実行時の実行コマンド上で行われます。
この方法において、標準入力 (ユニット 5) を読み取り、標準出力 (ユニット 6) か標準エラー (ユニット 0) に書き込むプログラムは、リダイレクトによって (コマンド行上で
<、>、>>、>&、|、|&、2>、2>&1
を使用することによって)、他の名前付きファイルを読み取ったり、書き込んだりできます。
コマンド行におけるリダイレクトとパイプに関する詳細は、
csh
、ksh
、 およびsh
のマニュアルページを参照してください。
f77: VAX/VMS
論理ファイル名VMS FORTRAN から FORTRAN 77 に移植する場合は、
INCLUDE
文の VMS 形式の論理ファイル名は UNIX のパス名にマップされます。環境変数のLOGICALNAMEMAPPING
が、論理名と UNIX のパス名の間のマッピングを定義します。環境変数のLOGICALNAMEMAPPING
が設定され-vax、
-xl、
または-xld
コンパイラオプションが使用されていると、コンパイラはINCLUDE
文にある VMS の論理ファイル名を解釈します。コンパイラは、次の構文を使用して、環境変数に文字列を設定します。
"lname1=path1; lname2=path2; ... "ここで、lname は論理名で、各 path はディレクトリの (末尾の「/」を除く) パス名です。この文字列を構文解析する場合は、空白文字はすべて無視されます。
INCLUDE
文にあるファイル名から/list
または/nolist
は取り除かれます。ファイル名の論理名は、VMS ファイル名の中の最初のコロン (:) で区切られます。コンパイラは、次の形式のファイル名をその次にある書式に変換します。
lname1:file
path1/file論理名では、大文字と小文字が区別されます。
LOGICALNAMEMAPPING
で指定されていない論理名がINCLUDE
文にあると、ファイル名は変更されずにそのまま使用されます。直接探査入出力
直接探査入出力、つまりランダム入出力を使用すると、記録番号によってファイルに直接探査できます。記録番号は、記録が書き込まれたときに割り当てられます。順番入出力とは異なり、直接探査出力記録は、どのような順番でも読み取り、あるいは書き込みできます。しかし、直接探査ファイルでは、すべての記録が同じ固定長でなければなりません。直接探査ファイルは、そのファイルの
OPEN
文のACCESS='DIRECT'
指定子によって宣言されます。直接探査ファイル中の論理記録は、
OPEN
文のRECL=
指定子によって指定されたバイト長をもつ文字列です。READ
文とWRITE
文で、定義された記録サイズより大きな論理記録を指定してはなりません (記録サイズはバイト単位で指定されます)。論理記録のほうが短い場合は差し支えありません。書式なし直接探査書き込みでは、記録中の書き込まれていない部分は不定となります。書式付き直接探査書き込みでは、書き込まれていない記録は空白で埋められます。直接探査の
READ
文とWRITE
文には、REC=
n 引数が追加されており、読み取りや書き込みを行う記録番号を指定するようになっています。
OPEN( 2, FILE='data.db', ACCESS='DIRECT', RECL=200,& FORM='UNFORMATTED', ERR=90 )READ( 2, REC=13, ERR=30 ) X, Yこのプログラムでは、ファイルを直接探査、書式なし入出力、200 バイトの固定記録長で開いた後で、13 番目の記録を
X
とY
に読み込みます。
OPEN( 2, FILE='inven.db', ACCESS='DIRECT', RECL=200,& FORM='FORMATTED', ERR=90 )READ( 2, FMT='(I10,F10.3)', REC=13, ERR=30 ) X, Yこのプログラムでは、ファイルを直接探査、書式付き入出力、200 バイトの固定記録長で開いた後で、13 番目の記録を読み取り、それを (
I10
,F10.3
) の書式に従って変換します。書式付きファイルの場合、書き込まれる記録のサイズは、
FORMAT
文によって決定されます。上記の例では、FORMAT
文は記録を 20 文字 (またはバイト) に定義しています。並び上のデータの量がFORMAT
文で指定された記録長より大きい場合、1 つの書式付き書き込みで複数の記録を書き込むことができます。このような場合、各後続の記録には、連続する記録番号が割り当てられます。
OPEN( 21, ACCESS='DIRECT', RECL=200, FORM='FORMATTED')WRITE(21,'(10F10.3)',REC=11) (X(J),J=1,100)直接探査装置 21 への書き込みによって、10 の要素からなる 10 の記録が作成されます。なぜなら、記録ごとに 10 要素であると書式で指定しているからです。これらの記録には、11 から 20 までの番号が割り当てられます。
バイナリ I/O
Sun Workshop Fortran 95 と Fortran 77 では OPEN 文の機能が拡張されて「バイナリ」の I/O ファイルを宣言できるようになりました。
ファイルを開くときに
FORM'= BINARY'
と指定すると、レコード長がファイルに組み込まれないことを除いて、FORM='UNFORMATTED'
と大体同じ結果になります。このデータがなければ、1 レコードの開始点と終了点を知らせる方法がありません。そのため、後退する場所を知らせることができないので、FORM='BINARY'
ファイルに対してBACKSPACE
を実行できません。'BINARY'
ファイルに対してREAD
を実行すると、入力リストの変数を設定するために必要な量のデータが読み込まれます。
WRITE
文。データはバイナリでファイルに書き込まれ、出力リストで指定された量のバイトが転送されます。READ
文。入力リストの変数にデータが読み込まれ、リストで必要なだけのバイトが転送されます。ファイルにはレコードマークがないので、「レコードの終端」エラーは検出されません。検出されるエラーは、「ファイルの終端」または異常システムエラーだけです。INQUIRE
文。ファイルにINQUIRE
を実行するときにFORM='BINARY'
と指定すると、次の結果が返されます。- FORM="BINARY"
ACCESS="SEQUENTIAL"
DIRECT="NO"
FORMATTED="NO"
UNFORMATTED="YES"
RECL= AND NEXTREC= は未定義です。BACKSPACE
文。許可されていません。エラーが返されます。ENDFILE
文。通常とおり、現在の場所でファイルを切り捨てます。REWIND
文。通常とおり、ファイルの位置をデータの先頭に変更します。内部ファイル
内部ファイルは、変数、部分列、配列、配列要素、構造化記録の欄のような、
CHARACTER
型のオブジェクトです。内部ファイルからのREAD
の場合は、文字列の定数であってもかまいません。内部ファイルにおける入出力は、データをある文字実体から他のデータ実体に転送し、変換することによって、書式付きREAD
とWRITE
文をシミュレートします。ファイルの入出力は実行されません。
WRITE
文では、装置番号の代わりに、データを受け取る文字実体の名前が現れます。READ
文では、装置番号の代わりに、文字実体のソースの名前が現れます。- ファイル中の 1 つの記録は、定数、変数、部分列のいずれかの実体から構成されます。
- 配列実体の場合、個々の配列要素が 1 つの記録に対応します。
f77:
f77
は直接探査入出力を内部ファイルにも拡張しています。(ANSI 規格では、内部ファイルには順番書式付き入出力しか許可されていません。これは、外部ファイルに対する直接探査入出力と似ていますが、ファイルにある記録数を変更できない点が異なります。この場合、記録は、文字列の配列の 1 つの要素です。- 順番探査の
READ
またはWRITE
文は、内部ファイルの先頭から処理を始めます。例 : 内部ファイルから書式付きで順番に読み取ります (1 記録のみ)。
demo%cat intern1.f
CHARACTER X*80READ( *, '(A)' ) XREAD( X, '(I3,I4)' ) N1, N2 ! 内部ファイル X を読み取るWRITE( *, * ) N1, N2ENDdemo%f77 -silent -o tstintern intern1.f
demo%tstintern
12 99
12 99demo%例 : 内部ファイルから書式付きで順番に読み取ります (3 記録)。
例 : 内部ファイルから直接探査で読み取ります (1 記録) (
f77
のみ)。
f77
: テープ入出力のみ通常、ほとんどの Fortran の入出力はディスクファイルに対して行われます。しかし、
OPEN
文を経由して論理ユニット番号を物理的にマウントされたテープドライブに関連付けることによって、テープに直接入出力できます。磁気テープに入出力する場合、Fortran の入出力文よりも、
TOPEN()
ルーチンを使用するほうが効果的です。
TOPEN
ルーチンを使用する非標準のテープ入出力パッケージ (
topen
(3F) のマニュアルページを参照) を使用して、テープドライブと、Fortran の文字変数として宣言されたバッファの間でブロックを転送できます。その次に、内部入出力を使用して、このバッファを満たしたり空にしたりすることができます。ただし、この機能は他の Fortran 入出力との統合性はなく、テープの論理ユニットの独自のセットを持っています。詳細は、マニュアルページを参照してください。テープに対する Fortran の書式付き入出力
Fortran の入出力文では、磁気テープ上にある書式付きの順番ファイルに対して透過な探査ができるようになっています。書式付きの記録長には制限がなく、また、記録が複数のテープブロックにわたってもかまいません。
テープに対する Fortran の書式なし入出力
Fortran の入出力文は、磁気テープと接続して書式なし探査を行うにはあまり適していません。書式なし記録では、記録長 (オーバーヘッドとして 8 文字を加算) はバッファサイズを超えることはできません。
この制限のため、入出力システムは複数の物理テープブロックにわたる記録の書き込みを行いませんが、必要に応じて短いブロックの書き込みは行います。書式なし記録のこの形式は、テープに対しては不適切でも保持されるので、ファイルをディスクとテープ間で自由にコピーできます。
記録が複数のブロックに渡れないという制限はテープの読み取りには適用されないため、特別な配慮をせずにファイルをテープからディスクにコピーできます。
テープファイルの形式
Fortran のデータファイルはテープ上では、最後にファイル終了記録がある、連続するデータ記録という形式で書き込まれます。データはブロックにグループ化されており、最大長はファイルを開くときに決定されます。記録は、ディスクファイルの記録と同じ形式になります。書式付き記録の最後には改行文字があり、また書式なし記録の前後には文字カウントがあります。一般的には、Fortran の記録とテープブロックの間には何も関係がありません。つまり、記録は複数のブロックにわたることができ、ブロックは複数の記録の一部を含むことができます。
唯一の例外は、Fortran は複数のブロックにわたる書式なし記録を書き込まないことです。このため、書式なし記録の最大長は、ブロック長より 8 文字小さくなります。
dd
変換ユーティリティFortran のファイル終了記録は、テープマークに直接マップされます。したがって、Fortran ファイルは、テープシステムファイルと同じ形式になります。しかし、テープ上の Fortran ファイルの形式は、UNIX の他の部分で使用されている形式と同じであるため、Fortran プログラムは、テープから 80 カラムのカードイメージを読み取ることができません。既存の Fortran プログラムと、それを使用して読もうとする既存のデータテープがある場合には、
dd
(1) ユーティリティを使用してテープを変換し、改行文字の追加と終端の空白文字の消去を行う必要があります。例 :
mt0
上のテープを変換し、それを実行可能ファイルのftnprg
にパイプします。
demo% dd if=/dev/rmt0 ibs=20b cbs=80 conv=unblock | ftnprg
getc
ライブラリルーチン
dd
を使用せずに、getc
(3F) ライブラリルーチンを呼び出して、テープから文字を読み取ることができます。読み取った文字を文字変数に格納し、内部入出力を使用して書式付きデータを転送します。TOPEN
(3F) のマニュアルページも参照してください。ファイルの終了
READ
文の実行中にファイル終了記録に行き当たると、ファイル終了条件に到達したことになります。標準規格では、ファイルはファイル終了記録の後に位置付けられることになっています。これは、実際にはテープの読み取りヘッドが、テープ上の次のファイルの開始位置に留まることを意味しています。したがって、テープ上の次のファイルの読み取りを続けることができるように思えますが、これは厳密には正しくありません。『ANSI FORTRAN 77 Language Standard』にはカバーされていません。また規格では、
BACKSPACE
文かREWIND
文を使用してファイルの位置付けのやり直しを行うことができると規定しています。これは、ファイルの終端に到達した後、ファイル終了記録を超えて巻き戻しを行い、さらにファイルを操作できるということです。たとえば、 終わりに記録を書き足す、ファイルを巻き戻す、ファイルを再度読み取る、または書き込むなどのファイル操作が可能です。マルチファイルテープ
テープファイルを開くときに使用する名前によって、記録密度や、テープを開いたり閉じたりするときに自動的にテープの巻き戻しを行うかなど、接続に関するいくつかの性質が決まります。
マルチファイルテープ上のファイルに探査する場合には、
mt
(1) ユーティリティを使用して適切なファイルにテープを位置付け、それからそのファイルを/dev/nrmt0
のような自動巻き戻しをしない磁気テープとして開きます。この名前でテープを使用すると、閉じるときの位置付けのやり直しも行われません。プログラムがファイルの終わりまで読み取りを行うと、次に開いたときに、テープ上の次のファイルに探査できるようになります。以後のプログラムはすべて、最後の探査位置 (なるべくファイルの先頭かファイル終了記録を通り過ぎた位置) からテープを探査できます。プログラムが何らかの異常で途中終了した場合、テープは予測できない場所に位置付けられている可能性があります。SunOS
mt
(1) コマンドを使用して、テープを適切な場所に位置付けし直します。Fortran 95 の入出力について
Sun WorkShop 6 FORTRAN 77 と Fortran 95 の入出力には互換性があります。
f77
とf95
のコンパイルが混在する実行ファイルは、プログラムのf77
およびf95
部分のどちらからも同じ装置に対して入出力を行えます。ただし、Fortran 95 には次のような新しい機能が追加されています。
- 次のように
ADVANCED='NO'
を指定すると、停留入出力が可能になります。
write(* `(a)',ADVANCE='NO')'Enter sie'read(*,*) n- NAMELIST 入力機能
f95
では、入力するときにグループ名の前に$
や&
を付けることができます。&
は Fortran 95 の標準規格で唯一認められている書式で、NAMELIST
書き込みの出力で使用されます。f95
では、グループの最終データ項目がCHARACTER
(つまり、$
は入力データとして扱われる) でないかぎり、$
は入力グループの終了を示す記号です。f95
では、NAMELIST
入力をレコードの最初の桁から開始することができます。ENCODE
とDECODE
がf77
と同様にf95
で認識、実装されています。
サン・マイクロシステムズ株式会社 Copyright information. All rights reserved. |
ホーム | 目次 | 前ページへ | 次ページへ | 索引 |