テキストファイルかバイナリファイルか、一括して読み込むか部分的に読み込むかで使用する API が変わってきます。

テキストファイル

一括してメモリに読み込み、一括して書き込む

TStringList を使います。

利点
扱いが非常に楽です
欠点
サイズの大きいテキストを読み込むとメモリを無駄に消費します。ログの出力などには向きません
var
 lines: TStringList;
 i: Integer;
begin
 lines := TStringList.Create;
 try
  // ファイルを読み込む
  lines.LoadFromFile('textfile.txt');

  // アルファベットをすべて大文字に変換
  for i := 0 to lines.Count-1 do
   lines[i] := UpperCase(lines[i]);

  // ファイルを書き込む
  lines.SaveToFile('textfile.txt');
 finally
  ines.Free;
 end;
end;

先頭から一行ずつ読み込み、一行ずつ書き込む

AssignFile, Reset, Rewrite, Readln, Writeln, CloseFile を使います。

利点
メモリの消費量が少ないです
欠点
データを読み捨てていくので、読み込んだ行以外にアクセスすることが出来ません
{$APPTYPE CONSOLE}
var
 f: Text;
 line: string;
begin
 AssignFile(f, 'c:\test.txt');
 Reset(f);
 try
  while not Eof(f) do
  begin
   // 一行読み込む
   Readln(f, line);

   line := Uppercase(line);

   // ファイル変数を省略すると
   // 標準出力へ出力します。
   Writeln(line);
  end;
 finally
  CloseFile(f);
 end;
end.

ログを出力する

既に存在するファイルの末尾にテキストを追加していく場合は、AssignFile, Append, Rewrite, Writeln を使います。

var
 f: TextFile;
begin
 {$i+}
 AssignFile(f, ChangeFileExt(ParamStr(0), '.log'));
 try
  Append(f);
 except
  on EInOutError do
   Rewrite(f);
 end;

 try
  Writeln(f, DateTimeToStr(Now), ': ログを追加');
 finally
  CloseFile(f);
 end;
end;

バイナリファイル

一括してメモリに読み込む

TMemoryStream を使います。

type
 TByteArray = array [0..MaxInt-1] of Byte;
 PByteArray = ^TByteArray;
var
 ms: TMemoryStream;
 p: PByteArray;
 i: Integer;
begin
 ms := TMemoryStream.Create;
 ms.LoadFromFile('file.dat');

 // 読み込んだバッファへのポインタを取得
 p := ms.Memory;

 // 各バイトを1増やす
 for i := 0 to ms.Size-1 do
  Inc(p^[i]);

 ms.SaveToFile('file.dat');
 ms.Free;
end;

先頭から順番に読み込む

TFileStream を使います。バイナリファイルを読み書きする最も一般的な方法です。

// ファイルをコピーする
var
 src, dest: TFileStream;
 buf: array[0..4095] of Byte;
 numread:
begin
 src := TFileStream.Create('src.txt', fmOpenRead);
 dest := TFileStream.Create('dest.txt', fmCreate);

 while True do
 begin
  numread := fs.Read(buf, SizeOf(buf));

  // すべて読み込んだら抜ける。
  if numread = 0 then
   break;

  dest.Write(buf, numread);
 end;
end;

ランダムアクセスする

TFileStreamのPosition プロパティ、Seek メソッドを使ってアクセスする場所を指定できます。

// ファイルの10バイト目を1増やす。
var
 fs: TFileStream;
 b: Byte;
begin
 fs := TFileStream.Create('file.dat', fmOpenReadWrite);

 fs.Position := 10;
 fs.Read(b, SizeOf(b));

 Inc(b);

 fs.Position := 10;
 fs.Write(b, SizeOf(b));

 fs.Free;
end;

その他

BlockRead / BlockWrite

古い関数です。あまり使うメリットはありません。

Win32API

CreateFile, ReadFile, WriteFile, CloseFileを使って読み書きします。非常に柔軟なアクセスが可能です。

ファイルマッピングオブジェクトを使用する

CreateFileMapping, MapViewOfFile を使用するとファイルをメモリ上の配列のように扱うことが出来ます。ファイル全域にランダムアクセス可能でしかもファイルをすべて読み込むことがないのでメモリ効率がいいです。

procedure TForm1.Button1Click(Sender: TObject);
var
 hFile: THandle;
 hFileMapping: THandle;
 p: Pointer;
 fileSize: DWORD;
begin
 fileSize := 100; // TODO:既にファイルが存在するならファイルサイズを取得する。

 hFile := CreateFile(
  'mapfile.txt',
  GENERIC_READ or GENERIC_WRITE,
  FILE_SHARE_READ,
  nil,
  OPEN_ALWAYS,
  FILE_ATTRIBUTE_NORMAL,
  0);
 Win32Check(hFile <> INVALID_HANDLE_VALUE);
 try
  hFileMapping := CreateFileMapping(
   hFile, nil, PAGE_READWRITE,
   0, fileSize,
   nil);
  Win32Check(hFileMapping <> 0);
  try
   p := MapViewOfFile(
    hFileMapping,
    FILE_MAP_WRITE,
    0, 0, 0); // ファイルサイズは指定しない。
   Win32Check(p <> nil);
   try
   // TODO:ポインタpの[0..fileSize-1]に対して読み書きする
   finally
    Win32Check(UnmapViewOfFile(p));
   end;
  finally
   Win32Check(CloseHandle(hFileMapping));
  end;
 finally
  Win32Check(CloseHandle(hFile));
 end;
end;

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2010-01-04 (月) 12:06:55 (245d)