標準ルーチンと入出力
Delphi 言語ガイド:インデックス への移動
このトピックでは、テキストとファイルの入出力について説明し、標準ライブラリ ルーチンを一覧にまとめます。 ここで挙げる手続きや関数の多くは System ユニットか SysInit ユニットで定義されており、この 2 つのユニットはすべてのアプリケーションで暗黙的に使われます。 コンパイラに組み込まれているけれども、System ユニットに含まれているかのように扱われるものもあります。
標準ルーチンの中には SysUtils などのユニットに含まれるものもあります。その場合、プログラム内で使用するには uses 句にそのユニットを含める必要があります。 ただし、System ユニットを uses 句に含めることはできません。また、System ユニットを変更したり明示的に再構築してはなりません。
メモ: 新しいプログラムの場合、System.Classes や System.SysUtils のユニットにある、ファイル管理クラスや関数を使用したい場合もあるでしょう。System.Classes.TStream とその子クラスが、現在は Delphi での汎用的なファイル処理で推奨されています(関連ルーチンについては、「ストリーム、リーダー、ライター」を参照してください)。テキスト ファイル処理については、TStreamReader、TStreamWriter の方が、Write や Writeln を呼び出すより推奨されています。 「API カテゴリ:インデックス」には、関連するルーチンやクラスのリストが掲載されています。
メモ: BlockRead や BlockWrite には、型指定のないパラメータがあり、それがメモリ破損の原因となる可能性があります。どちらのメソッドも、前もって Reset または Rewrite を呼び出すことで暗黙的にレコード サイズの設定が行われていることを前提としています。 ストリームを使用した方が、プログラミングの柔軟性が向上し、より豊富な機能を使用できます。
目次
ファイル入出力
次の表に入出力ルーチンをまとめます。
入出力手続き/関数
手続き/関数 | 説明 |
---|---|
既存のテキスト ファイルを追加モードで開きます。 | |
外部ファイルの名前をファイル変数に割り当てます。 | |
型なしファイルからレコードを読み取ります。 | |
型なしファイルにレコードを書き込みます。 | |
現在のディレクトリを変更します。 | |
開いているファイルを閉じます。 | |
ファイルの EOF(end-of-file)ステータスを返します。 | |
テキスト ファイルの行末ステータスを返します。 | |
外部ファイルを削除します。 | |
型付きファイルまたは型なしファイルの現在のファイルの位置を返します。 | |
ファイルの現在のサイズを返します。テキスト ファイルには使用できません。 | |
出力テキスト ファイルのバッファをフラッシュします。 | |
指定したドライブの現在のディレクトリを返します。 | |
直近に実行された入出力関数の状態を示す整数値を返します。 | |
サブディレクトリを作成します。 | |
ファイルから値を読み取って変数に格納します。 | |
Read の処理を行った後、テキスト ファイルの次の行の先頭に移動します。 | |
外部ファイルの名前を変更します。 | |
既存のファイルを開きます。 | |
新しいファイルを作成して開きます。 | |
空のサブディレクトリを削除します。 | |
型付きファイルまたは型なしファイルのファイルの現在の位置を、指定した要素に移動します。テキスト ファイルには使用できません。 | |
テキスト ファイルの EOF(end-of-file)ステータスを返します。 | |
テキスト ファイルの行末ステータスを返します。 | |
テキスト ファイルに入出力バッファを割り当てます。 | |
型付きファイルまたは型なしファイルのファイルの現在の位置以降を切り捨てます。 | |
値をファイルに書き込みます。 | |
Write と同じ処理を行った後、テキスト ファイルに行末マーカーを書き込みます。 |
ファイル変数とは、型がファイル型である変数のことです。 ファイルには、型付き、テキスト、型なしの 3 種類があります。 ファイル型を宣言する構文については File 型を参照してください。 ファイル型は Win32 プラットフォームでしか使用できません。
ファイル変数を使用するには、まず、AssignFile 手続きを呼び出して、ファイル変数を外部ファイルに関連付ける必要があります。 外部ファイルは、通常は名前の付いたディスク ファイルですが、キーボードやディスプレイなどのデバイスの場合もあります。 外部ファイルは、ファイルに書き込まれた情報を格納したり、ファイルから読み取った情報を提供したりします。
外部ファイルと関連付けた後で、ファイル変数を開いて入出力ができるように準備しなければなりません。 Reset 手続きを使用すると既存ファイルを開くことができ、Rewrite 手続きでは新しいファイルを作成して開くことができます。 Reset で開いたテキスト ファイルは読み取り専用であり、Rewrite および Append で開いたテキスト ファイルは書き込み専用です。 型付きファイルと型なしファイルは、Reset と Rewrite のどちらで開いたかには関係なく、常に読み取りと書き込みの両方が可能です。
ファイルはどれも要素を線状に並べたものであり、個々の要素はファイルの要素型(またはレコード型)です。 要素にはゼロから始まる番号が付けられます。
通常、ファイルに対しては順次アクセスが行われます。 つまり、標準手続き Read を使って要素を読み取ったり、標準手続き Write を使って要素を書き込んだりすると、現在のファイル ポインタの位置は次の番号のファイル要素に移動します。 型付きファイルおよび型なしファイルには、標準手続き Seek(指定した要素に現在のファイル ポインタの位置を移動する手続き)を使ってランダムにアクセスすることもできます。 標準関数の FilePos および FileSize を使用すると、現在のファイル ポインタの位置や現在のファイル サイズを知ることができます。
プログラムでファイルの処理が終了したら、標準手続き CloseFile を使ってファイルを閉じなければなりません。 ファイルを閉じると、対応する外部ファイルが更新されます。 ファイル変数は、その後、別の外部ファイルに関連付けることができます。
デフォルトでは、標準の入出力手続きや入出力関数を呼び出すと必ず自動的にエラー チェックが行われ、エラーが起きると例外が発生します(あるいは、例外処理が無効になっている場合にはプログラムが終了します)。 この自動チェックは、コンパイラ指令 {$I+} および {$I-} を使って有効または無効にすることができます。 入出力チェックが無効である、つまり {$I-} の状態で、手続きや関数の呼び出しをコンパイルした場合には、入出力エラーが起きても例外は発生しません。そのため、入出力操作の結果を確認するには、標準関数 IOResult を呼び出さなければなりません。
エラーに関心がない場合でも、エラーをクリアするには IOResult 関数を呼び出す必要があります。 エラーをクリアせず、現在の状態が {$I-} である場合には、IOResult エラーが残るため、次に入出力関数を呼び出したときに失敗します。
テキスト ファイル
このセクションでは、標準の Text 型のファイル変数を使った入出力について簡単に説明します。
テキスト ファイルを開くと、その外部ファイルは特殊な解釈をされます。 つまり、ファイルは行の形に整形された文字の連続であり、各行の末尾に行末マーカー(復帰文字。その後に改行文字が続くこともある)が付くと見なされます。 Text 型は file of Char 型とは異なります。
テキスト ファイル用に、Char 型ではない値を読み書きするための特別な Read および Write の形式が存在します。 Char 型でない値とそれに対応する文字表現とは、自動的に変換されます。 たとえば、Read(F, I) の I が Integer 型の変数である場合、一連の数字が読み取られ、10 進整数として解釈されて、I に格納されます。
標準のテキスト ファイル変数には、System.Input と System.Output の 2 つあります。標準ファイル変数 System.Input は、オペレーティング システムの標準入力(通常はキーボード)に関連付けられた読み取り専用ファイルです。 標準ファイル変数 System.Output は、オペレーティング システムの標準出力(通常はディスプレイ)に関連付けられた書き込み専用ファイルです。 アプリケーションの実行が始まる前に、System.Input と System.Output は自動的に開かれます。これは次のステートメントの実行に相当します:
AssignFile(Input, ); Reset(Input); AssignFile(Output, ); Rewrite(Output);
メモ: Win32 アプリケーションの場合、テキストの入出力はコンソール アプリケーションでしか利用できません。コンソール アプリケーションとは、[<プロジェクト> のプロジェクト オプション]ダイアログ ボックスの[リンク]ページで[コンソール アプリケーションを生成]オプションを True にするか、コマンドライン コンパイラ オプション -cc を指定してコンパイルしたアプリケーションのことです。 GUI アプリケーション(コンソール アプリケーションではないもの)で System.Input や System.Output を使って読み書きをしようとすると、I/O エラーが発生します。
テキスト ファイルを扱う標準入出力ルーチンの中には、ファイル変数を明示的にパラメータとして渡さなくてもよいものがあります。 ファイル パラメータを省略した場合、手続きまたは関数が入力用か出力用かに応じて、デフォルトで System.Input または System.Output が使われます。たとえば、Read(X) は Read(Input, X) に、Write(X) は Write(Output, X) に相当します。
テキスト ファイルを扱う入出力ルーチンの呼び出しでファイルを指定する場合には、まず、そのファイルを AssignFile を使って外部ファイルに関連付け、Reset、Rewrite、Append のいずれかを使って開いておかなければなりません。 Reset を使って開いたファイルを出力用の手続きや関数に渡すと、エラーが発生します。 Rewrite または Append を使って開いたファイルを入力用の手続きや関数に渡した場合にも、エラーが発生します。
型なしファイル
型なしファイルは、型や構造に関係なくディスク ファイルに直接アクセスするときに主に使用する、低レベルの入出力チャネルです。 型なしファイルは、file という単語だけを付けて宣言します。 例:
var DataFile: file;
型なしファイルの場合、Reset および Rewrite の手続きでは、データ転送に使用するレコード サイズを指定するパラメータを追加することができます。 歴史的経緯から、デフォルトのレコード サイズは 128 バイトになっています。 あらゆるファイルの正確なサイズを正しく反映できる値は、1 というレコード サイズのみです。 (レコード サイズが 1 の場合には、不完全なレコードは存在し得ません。)
Read および Write を除くと、型付きファイルの標準手続きおよび標準関数はすべて、型なしファイルにも使用できます。 Read と Write の代わりに BlockRead および BlockWrite という 2 つの手続きを使用すると、高速のデータ転送を行うことができます。
テキスト ファイル デバイス ドライバ
自分のプログラム用に独自にテキスト ファイル デバイス ドライバを定義することができます。 テキスト ファイル デバイス ドライバは、Delphi のファイル システムと何らかのデバイスとの間のインターフェイスを完全に実装する 4 つの関数の集合です。
デバイス ドライバを定義する 4 つの関数は、Open、InOut、Flush、Close です。 各関数の関数ヘッダーは次のようになっています。
function DeviceFunc(var F: TTextRec): Integer;
DeviceFunc は関数名(つまり Open、InOut、Flush、Close のいずれか)です。 デバイス インターフェイス関数の戻り値が、IOResult で返される値になります。 戻り値がゼロであれば操作は成功しています。
デバイス インターフェイス関数を特定のファイルに関連付けるために、Assign 手続きを独自に作成する必要があります。 Assign 手続きでは、4 つのデバイス インターフェイス関数のアドレスを、テキスト ファイル変数の 4 つの関数ポインタに代入しなければなりません。 さらに、fmClosed という魔法の定数を Mode フィールドに格納し、テキスト ファイル バッファのサイズを BufSize に格納し、テキスト ファイル バッファのポインタを BufPtr に格納し、Name 文字列をクリアしなければなりません。
たとえば、4 つのデバイス インターフェイス関数の名前が DevOpen、DevInOut、DevFlush、DevClose である場合、Assign 手続きは次のようになります。
procedure AssignDev(var F: Text); begin with TTextRec(F) do begin Mode := fmClosed; BufSize := SizeOf(Buffer); BufPtr := @Buffer; OpenFunc := @DevOpen; InOutFunc := @DevInOut; FlushFunc := @DevFlush; CloseFunc := @DevClose; CodePage := DefaultSystemCodePage; Name[0] := #0; end; end;
RTL によって使用されるデバイス インターフェイス関数については、CodePage フィールドが、DefaultSystemCodePage に設定されていなければなりません。これらのデバイス インターフェイス関数では、必要とされる独自の文字処理を実行しなければなりません。
デバイス インターフェイス関数では、ファイル レコードの UserData というフィールドを使って独自の情報を格納することができます。 本製品のファイル システムがこのフィールドを変更することはありません。
Open 関数
Open は、デバイスに関連付けられたテキスト ファイルを開くときに Reset、Rewrite、Append の各標準手続きから呼び出される関数です。 この関数に入る時点で、Mode フィールドには fmInput、fmOutput、fmInOut のいずれかが含まれ、Open 関数が Reset、Rewrite、Append のどれから呼び出されたかを示します。
Open 関数は、Mode の値に合わせて、ファイルを入力用または出力用に準備します。 Mode に fmInOut が指定されている場合(Open が Append から呼び出されたことを示します)には、Open の処理を終了する前にその値を fmOutput に変更しなければなりません。
Open は、他のデバイス インターフェイス関数より先に必ず呼び出されます。 そのため、AssignDev では、OpenFunc フィールドだけを初期化して、残りのベクタの初期化は Open に任せます。 Open では、Mode に合わせて入力用または出力用の関数のポインタを設定することができます。 こうすることで、InOut 関数、Flush 関数、CloseFile 手続きでは、現在のモードを判断する必要がなくなります。
InOut 関数
InOut 関数は、デバイスの入出力が必要になったときに、Read、Readln、Write、Writeln、Eof、Eoln、SeekEof、SeekEoln、CloseFile の各標準ルーチンから呼び出されます。
Mode が fmInput の場合、InOut 関数は、最大で BufSize 個の文字を BufPtr^ に読み込み、読み込んだ文字数を BufEnd に入れて返します。 さらに、BufPos にはゼロを格納します。 InOut 関数が入力要求の結果として BufEnd にゼロを入れて返した場合には、そのファイルの Eof は True になります。
Mode が fmOutput の場合、InOut 関数は、BufPtr^ から BufPos 個の文字を書き出し、BufPos にゼロを入れて返します。
Flush 関数
Flush 関数は、Read、Readln、Write、Writeln のそれぞれの処理の最後に呼び出されます。 テキスト ファイル バッファをフラッシュすることもできます。
Mode が fmInput の場合、Flush 関数は、BufPos と BufEnd にゼロを格納して、バッファ中に残った(読み取られていない)文字をフラッシュすることができます。 この機能が使われることはほとんどありません。
Mode が fmOutput の場合、Flush 関数は、バッファの内容を InOut 関数とまったく同じようにして書き出すことができます。そうすると、デバイスに書き込まれたテキストは即座にデバイスに表示されます。 Flush で何もしなければ、そのテキストは、バッファがいっぱいになるかファイルが閉じられるまで、デバイスに表示されません。
Close 関数
Close 関数は、デバイスに関連付けられたテキスト ファイルを閉じる際に CloseFile 標準手続きから呼び出されます。 (Reset、Rewrite、Append の各手続きでも、開こうとしているファイルが既に開かれている場合には、Close が呼び出されます。) Mode が fmOutput の場合、ファイル システムは、Close を呼び出す前に InOut 関数を呼び出して、すべての文字を確実にデバイスに書き出します。
NULL で終わる文字列の処理
Delphi 言語の拡張構文では、Read、Readln、Str、Val の標準手続きを、インデックスがゼロから始まる文字配列に適用したり、Write、Writeln、Val、AssignFile、Rename の標準手続きを、インデックスがゼロから始まる文字配列および文字ポインタに適用することができます。
NULL で終わる文字列の関数
NULL で終わる文字列を処理するために、次の関数が提供されています。
NULL で終わる文字列の関数
関数 | 説明 |
---|---|
指定したサイズの文字バッファをヒープ上に割り当てます。 | |
StrAlloc または StrNew を使って割り当てられた文字バッファのサイズを返します。 | |
2 つの文字列を連結します。 | |
2 つの文字列を比較します。 | |
文字列をコピーします。 | |
StrAlloc または StrNew を使って割り当てられた文字バッファを破棄します。 | |
文字列をコピーし、その文字列の末尾を指すポインタを返します。 | |
文字列の末尾を指すポインタを返します。 | |
1 つ以上の値を整形して文字列を作成します。 | |
大文字/小文字を区別せずに 2 つの文字列を比較します。 | |
2 つの文字列を連結します。ただし、指定した結果文字列の最大長を上限とします。 | |
指定した最大長まで 2 つの文字列を比較します。 | |
指定した最大長まで文字列をコピーします。 | |
文字列の長さを返します。 | |
1 つ以上の値を整形して文字列を作成します。ただし、指定した最大長を上限とします。 | |
指定した最大長まで、大文字/小文字を区別せずに 2 つの文字列を比較します。 | |
文字列を小文字に変換します。 | |
ひとまとまりの文字を 1 つの文字列から別の文字列に移動します。 | |
ヒープ上に文字列を割り当てます。 | |
Pascal 文字列を NULL で終わる文字列にコピーします。 | |
指定した最大長まで、Pascal 文字列を NULL で終わる文字列にコピーします。 | |
指定した部分文字列が文字列内で最初に出現する箇所を指すポインタを返します。 | |
指定した文字が文字列内で最後に出現する箇所を指すポインタを返します。 | |
指定した文字が文字列内で最初に出現する箇所を指すポインタを返します。 | |
文字列を大文字に変換します。 |
標準の文字列処理関数には、それぞれに対応するマルチバイト用の関数があり、そこでは文字のロケール固有の順序付けが実装されています。 マルチバイト関数の名前は Ansi で始まります。 たとえば、マルチバイト版の StrPos は AnsiStrPos になります。 マルチバイト文字がサポートされているかどうかは、オペレーティング システムや現在のロケールによって異なります。
ワイド文字列
System ユニットには、NULL で終わるワイド文字列をシングルバイト文字列やダブルバイト文字列に変換するための 3 つの関数、WideCharToString、WideCharLenToString、StringToWideChar が用意されています。
代入をしても文字列間の変換が行われます。 たとえば、次のコードはどちらも有効です。
MyAnsiString := MyWideString; MyWideString := MyAnsiString;
その他の標準ルーチン
製品ライブラリに含まれる、よく使われる手続きおよび関数を、次の表にまとめます。 これは標準ルーチンを完全に網羅したものではありません。
その他の標準ルーチン
手続き/関数 | 説明 |
---|---|
指定したオブジェクトを指すポインタを返します。 | |
メモリ ブロックを割り当てて、各バイトをゼロに初期化します。 | |
指定した数値の逆正接を計算します。 | |
渡した式の評価結果が True にならなければ例外を発生させます。 | |
ポインタ変数や手続き変数が nil(代入されていない)かどうかを検査します。 | |
標準のビープ音を鳴らします。 | |
for 文、while 文、repeat 文から制御を抜けさせます。 | |
指定したバイトを含む文字の、文字列内での位置を返します。 | |
指定した整数値に対応する文字を返します。 | |
ファイルを閉じます。 | |
2 つのメモリ イメージのバイナリ比較を実行します。 | |
大文字/小文字を区別して文字列を比較します。 | |
順序値によって文字列を比較します。大文字/小文字は区別しません。 | |
for 文、while 文、repeat 文の制御を次の反復に移します。 | |
文字列の部分文字列または動的配列の一部分を返します。 | |
角度のコサインを計算します。 | |
通貨型の変数を文字列に変換します。 | |
現在の日付を返します。 | |
TDateTime 型の変数を文字列に変換します。 | |
TDateTime 型の変数を文字列に変換します。 | |
順序変数または型付きポインタ変数の値を減少させます。 | |
動的に割り当てられた変数のメモリを解放します。 | |
現在の例外が発生したアドレスを返します。 | |
現在の手続きの実行を終了します。 | |
X の指数関数値を計算します。 | |
連続するバイト領域を指定した値で埋めます。 | |
動的に割り当てられた変数を初期化します。 | |
浮動小数点値を文字列に変換します。 | |
浮動小数点値を指定した形式の文字列に変換します。 | |
リソース化された書式文字列を使用して、整形済みの出力を返します。 | |
一連の配列から整形済みの文字列を組み立てます。 | |
書式文字列と一連の配列から文字列を組み立てます。 | |
日付と時刻の値を整形します。 | |
浮動小数点値を整形します。 | |
割り当てられたメモリを解放します。 | |
動的にメモリを割り当て、そのブロックのアドレスを指すポインタを返します。 | |
プログラムの異常終了を開始します。 | |
式の上位バイトを符号なしの値として返します。 | |
型や配列や文字列の範囲内の最大値を返します。 | |
順序変数または型付きポインタ変数の値を増加させます。 | |
動的に割り当てられた変数を初期化します。 | |
文字列中の指定した位置に部分文字列を挿入します。 | |
実数の整数部分を返します。 | |
整数を文字列に変換します。 | |
文字列または配列の長さを返します。 | |
式の下位バイトを符号なしの値として返します。 | |
型や配列や文字列の範囲内の最小値を返します。 | |
ASCII 文字列を小文字に変換します。 | |
整数配列内で最大の値を符号付きで返します。 | |
配列内で最大の値を符号付きで返します。 | |
整数配列内で最小の値を符号付きで返します。 | |
配列内で最小の値を符号付きで返します。 | |
動的変数を作成してメモリを割り当て、そのアドレスを指定したポインタに設定します。 | |
現在の日付と時刻を返します。 | |
順序型の式の順序整数値を返します。 | |
文字列に含まれる指定した部分文字列の最初のシングルバイト文字のインデックスを返します。 | |
順序値の前の値を返します。 | |
値をポインタに変換します。 | |
指定した範囲内で乱数を生成します。 | |
動的割り当て可能なメモリを再割り当てします。 | |
実数を最も近い整数に丸めた値を返します。 | |
文字列変数または動的配列変数の長さを設定します。 | |
指定した文字列の内容と長さを設定します。 | |
例外メッセージとそのアドレスを表示します。 | |
ラジアン単位で指定された角度の正弦を返します。 | |
変数または型が占めるバイト数を返します。 | |
配列の一部分を返します。 | |
数値の 2 乗を返します。 | |
数値の平方根を返します。 | |
整数や実数を文字列に変換します。 | |
文字列を Currency 値に変換します。 | |
文字列を日付形式(TDateTime)に変換します。 | |
文字列を TDateTime に変換します。 | |
浮動小数点値を文字列に変換します。 | |
整数を文字列に変換します。 | |
文字列を時刻形式(TDateTime)に変換します。 | |
ASCII 文字列を大文字に変換して返します。 | |
順序値の次の値を返します。 | |
配列の要素の総和を返します。 | |
現在の時刻を返します。 | |
TDateTime 型の変数を文字列に変換します。 | |
実数を切り捨てて整数にします。 | |
文字列の参照が 1 つだけであることを保証します。 (参照を 1 つにするために文字列をコピーする可能性があります。) | |
文字を大文字に変換します。 | |
文字列を大文字に変換して返します。 | |
バリアント配列を作成します。 | |
バリアント配列の次元数を返します。 | |
バリアント配列の 1 つの次元の上限を返します。 | |
バリアント配列をロックし、そのデータを指すポインタを返します。 | |
バリアント配列の 1 つの次元の下限を返します。 | |
1 次元のバリアント配列を作成し、要素に値を設定します。 | |
バリアント配列のサイズを変更します。 | |
渡したバリアント配列の参照を返します。 | |
バリアント配列のロックを解除します。 | |
指定した型にバリアントを変換します。 | |
指定した型にバリアントを変換し、結果を変数に格納します。 | |
バリアントをクリアします。 | |
バリアントをコピーします。 | |
バリアントを文字列に変換します。 | |
指定したバリアントの型コードを返します。 |