Fileクラスに用意されているメソッドを使うことにより、ファイル名を指定するだけでファイルからの読み込みができ、またファイル名と書き込む内容を指定するだけでファイルへの書き込みを簡単に行うことができます。 Fileクラスでは、ファイル内容の読み書きを行う次のようなメソッドが用意されています。

ファイル内容の読み込みを行うためのメソッド
目的 メソッド 解説
テキストファイルの内容をすべて読み込みたい
(単一の文字列として読み込む)
File.ReadAllText 解説へ
テキストファイルの内容を行単位で読み込みたい
(1行ごとに分割した配列または列挙子として読み込む)
File.ReadAllLines
File.ReadLines
解説へ
バイナリファイルの内容をすべて読み込みたい
(バイト配列として読み込む)
File.ReadAllBytes 解説へ
ファイル内容の書き込みを行うためのメソッド
目的 メソッド 解説
テキストファイルとして書き込みたい
(文字列の内容を書き込む)
File.WriteAllText 解説へ
テキストファイルに行単位で書き込みたい
(1行ごとの内容を含む配列またはコレクションを書き込む)
File.WriteAllLines 解説へ
バイナリファイルとして書き込みたい
(バイト配列の内容を書き込む)
File.WriteAllBytes 解説へ
ファイルへの追記を行うためのメソッド
目的 メソッド 解説
テキストファイルへ追記したい
(文字列の内容を追記する)
File.AppendAllText 解説へ
テキストファイルへ行単位で追記したい
(1行ごとの内容を含む文字列配列を追記する)
File.AppendAllLines 解説へ

Fileクラスのメソッドは言わばユーティリティメソッドで、ファイル内容すべてを読み書きするというごく基本的な読み込み・書き込み操作しか行えません。 そのため、ファイルの一部分のみを読み込んだり、データ構造やフォーマットが定められたファイルを扱う目的には不向きです。 ファイルの読み込み・書き込みに関して、目的に応じて以下のページをご覧ください。

1文字ずつ読み込む・次の文字を先読みしながら読み込む
StreamReaderクラス・StreamWriterクラス §.文字単位での読み込み (Read, Peek)
改行文字を指定してテキストファイルを書き込む
StreamReaderクラス・StreamWriterクラス §.改行文字
標準入出力を読み込み元・書き込み先に指定する
自プロセスの標準入出力
読み込みの際に文字コードを判別する
Shift JISとEUC-JPの判別
圧縮されたファイルを書き込む・読み込む
System.IO.Compression.GZipStream §.gzファイルの書き込み・読み込みSystem.IO.Compression.ZipArchive
暗号化されたファイルを書き込む・読み込む
テキスト変換・フォーマット変換 §.暗号化・復号化
BASE64などフォーマット変換した状態で書き込む・読み込む
テキスト変換・フォーマット変換 §.Base64
CSVファイル(カンマ区切り・タブ区切り)・固定幅のファイルを読み込む
Microsoft.VisualBasic.FileIO.TextFieldParser
XMLファイルを書き込む・読み込む
XMLの構築・出力
インスタンスをファイルに保存する・復元する
シリアライズの基本

このほか、ファイルの読み書きに際して細かい制御を行いたい場合は、FileStreamクラスStreamReaderクラス・StreamWriterクラスBinaryReaderクラス・BinaryWriterクラスを使います。

§1 ファイルからの読み込み

§1.1 File.ReadAllText (テキストファイルの読み込み)

File.ReadAllTextメソッドを使ってテキストファイルの内容をすべて読み込む
using System;
using System.IO;
using System.Text;

class Sample {
  static void Main()
  {
    string text;

    // テキストファイルsample1.txtの内容をすべて読み込む (UTF-8で読み込む)
    text = File.ReadAllText("sample1.txt");

    // テキストファイルsample2.txtの内容をすべて読み込む (UTF-8で読み込む)
    text = File.ReadAllText("sample2.txt", Encoding.UTF8);

    // テキストファイルsample3.txtの内容をすべて読み込む (Shift_JISで読み込む)
    text = File.ReadAllText("sample3.txt", Encoding.GetEncoding("Shift_JIS"));
  }
}

File.ReadAllTextメソッドは、指定されたファイルの内容をすべて読み込み、一つの文字列として返します。 また、文字コードが指定されていればその文字コードで読み込み、文字コードを指定しない場合はデフォルトでUTF-8として読み込みを行います。

File.ReadAllTextメソッドの呼び出し
File.ReadAllText(ファイル名)
File.ReadAllText(ファイル名, 文字コード)

文字コードはEncodingクラスで指定します。 文字コードに対応するEncodingの取得方法は§.文字コードに別途まとめています。

ファイルから読み込んだ文字列を加工・編集したり、有用な部分を検索・抽出したりするにはStringクラスのメソッドを使います。 文字列操作のメソッドについては文字列の加工・編集および文字列の探索・比較を参照してください。

ファイルから読み込んだ文字列を数値など別の型に変換するにはint.Parseなどのメソッドを使います。 文字列からの型変換については基本型の型変換 §.文字列からの変換 (Parse, TryParse)を参照してください。

テキストファイルからデータを読み込む具体例は§.CSVを読み込むとして別途まとめています。

§1.2 File.ReadAllLines, File.ReadLines (行単位でのテキストファイルの読み込み)

File.ReadAllLinesメソッドを使ってテキストファイルの内容を行ごとに分けて配列に読み込む
using System;
using System.IO;
using System.Text;

class Sample {
  static void Main()
  {
    string[] lines;

    // ファイルsample1.txtの内容を行ごとに分けて配列に読み込む (UTF-8で読み込む)
    lines = File.ReadAllLines("sample1.txt");

    // ファイルsample2.txtの内容を行ごとに分けて配列に読み込む (UTF-8で読み込む)
    lines = File.ReadAllLines("sample2.txt", Encoding.UTF8);

    // ファイルsample3.txtの内容を行ごとに分けて配列に読み込む (Shift_JISで読み込む)
    lines = File.ReadAllLines("sample3.txt", Encoding.GetEncoding("Shift_JIS"));
  }
}

FileReadAllLinesメソッドは、指定されたファイルの内容を行ごとに分割して読み込み、文字列配列に格納して返します。 読み込む際、改行文字は自動的に除去されるため、chopchompなどの操作は不要です。 また、文字コードが指定されていればその文字コードで読み込み、文字コードを指定しない場合はデフォルトでUTF-8として読み込みを行います。

File.ReadAllTextメソッドの呼び出し
File.ReadAllLines(ファイル名)
File.ReadAllLines(ファイル名, 文字コード)

文字コードはEncodingクラスで指定します。 文字コードに対応するEncodingの取得方法は§.文字コードに別途まとめています。

ファイルから読み込んだ文字列を加工・編集したり、有用な部分を検索・抽出したりするにはStringクラスのメソッドを使います。 文字列操作のメソッドについては文字列の加工・編集および文字列の探索・比較を参照してください。

ファイルから読み込んだ文字列を数値など別の型に変換するにはint.Parseなどのメソッドを使います。 文字列からの型変換については基本型の型変換 §.文字列からの変換 (Parse, TryParse)を参照してください。

テキストファイルからデータを読み込む具体例は§.CSVを読み込むとして別途まとめています。


File.ReadAllLinesメソッドは、すべての行を読み込み終えるまで処理が戻りません。 一方File.ReadLinesメソッドでは、一行読み込むごとに処理が戻ります。 したがって、次のような場合にはFile.ReadAllLinesメソッドよりもFile.ReadLinesメソッドを使ったほうがメリットがあります。

巨大なファイルを読み込んで一行ずつ処理するような場合
File.ReadLinesメソッドでは一行ずつ読み込んで逐次処理できるため、必要最小限のメモリを使用します。 File.ReadAllLinesメソッドではすべての行を読み込んでから次の処理に移るため、ファイルサイズに比例したメモリを専有します。
ファイルの先頭の方に読み込みたい内容があるなど、必ずしもファイルを末尾まで読み込まなくてもよい場合
File.ReadLinesメソッドではファイルの先頭から逐次読み込み、必要なくなった時点で読み込みを中断できます。 File.ReadAllLinesメソッドでは、目的には必要のない行であっても、すべて読み込んでからでなければ次の処理を行えません。
File.ReadLinesメソッドを使ってファイルの先頭3行のみを読み込む
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

class Sample {
  static void Main()
  {
    var lines = new List<string>();

    // ファイルsample.txtの内容を最大で3行分読み込む
    foreach (var line in File.ReadLines("sample.txt", Encoding.UTF8)) {
      lines.Add(line); // 行の内容をListに追加

      if (3 <= lines.Count)
        break; // 3行目に達した時点で読み込みを中断する
    }
  }
}

File.ReadAllLinesメソッドとFile.ReadLinesメソッドでは動作は異なりますが、呼び出し方はどちらも同じです。

File.ReadLinesメソッドの呼び出し
File.ReadLines(ファイル名)
File.ReadLines(ファイル名, 文字コード)

§1.3 File.ReadAllBytes (バイナリファイルの読み込み)

File.ReadAllBytesメソッドを使ってバイナリファイルの内容をすべて読み込む
using System;
using System.IO;

class Sample {
  static void Main()
  {
    byte[] bytes;

    // バイナリファイルsample.datの内容をすべて読み込む
    bytes = File.ReadAllBytes("sample.dat");
  }
}

File.ReadAllBytesメソッドは、指定されたファイルの内容をすべて読み込み、一つのバイト配列として返します。 バイナリファイルだけでなく、テキストファイルの生の内容(デコードされていないバイナリ表現の内容)を読み込む場合にも使うことができます。

File.ReadAllBytesメソッドの呼び出し
File.ReadAllBytes(ファイル名)

バイト配列の一部分を数値など別の型に変換するには、BitConverter.ToInt32などのメソッドを使います。 詳しくは基本型の型変換 §.基本型とバイト配列への/からの変換を参照してください。



§2 ファイルへの書き込み

§2.1 File.WriteAllText (テキストファイルの書き込み)

File.WriteAllTextメソッドを使って文字列の内容をテキストファイルに書き込む
using System;
using System.IO;
using System.Text;

class Sample {
  static void Main()
  {
    var text = "text日本語テキスト";

    // 文字列textの内容をテキストファイルsample1.txtに書き込む (UTF-8で書き込む)
    File.WriteAllText("sample1.txt", text);

    // 文字列textの内容をテキストファイルsample2.txtに書き込む (UTF-8で書き込む)
    File.WriteAllText("sample2.txt", text, Encoding.UTF8);

    // 文字列textの内容をテキストファイルsample3.txtに書き込む (Shift_JISで書き込む)
    File.WriteAllText("sample3.txt", text, Encoding.GetEncoding("Shift_JIS"));
  }
}

File.WriteAllTextメソッドは、指定された文字列の内容を指定されたファイルへと書き込みます。 また、文字コードが指定されていれば、その文字コードで書き込みを行い、文字コードを指定しない場合はデフォルトでUTF-8として書き込みを行います。

File.WriteAllTextメソッドの呼び出し
File.WriteAllText(ファイル名, ファイルに書き込む内容)
File.WriteAllText(ファイル名, ファイルに書き込む内容, 文字コード)

文字コードはEncodingクラスで指定します。 文字コードに対応するEncodingの取得方法は§.文字コードに別途まとめています。

§2.2 File.WriteAllLines (行単位でのテキストファイルの書き込み)

File.WriteAllLinesメソッドを使ってListに格納された行ごとの内容をファイルに書き込む
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

class Sample {
  static void Main()
  {
    // 行ごとの内容を格納するList
    var lines = new List<string>();

    lines.Add("1行目");
    lines.Add("2行目");
    lines.Add("3行目");

    // List内の各文字列を1行としてテキストファイルsample1.txtに書き込む (UTF-8で書き込む)
    File.WriteAllLines("sample1.txt", lines);

    // List内の各文字列を1行としてテキストファイルsample2.txtに書き込む (UTF-8で書き込む)
    File.WriteAllLines("sample2.txt", lines, Encoding.UTF8);

    // List内の各文字列を1行としてテキストファイルsample3.txtに書き込む (Shift_JISで書き込む)
    File.WriteAllLines("sample3.txt", lines, Encoding.GetEncoding("Shift_JIS"));
  }
}

File.WriteAllLinesメソッドは、指定された文字列配列や文字列コレクションに格納されている内容を行ごとの内容として、指定されたファイルへと書き込みます。 書き込みに際して、各行の内容に続けて改行文字が自動的に書き込まれます。 また、文字コードが指定されていれば、その文字コードで書き込みを行い、文字コードを指定しない場合はデフォルトでUTF-8として書き込みを行います。

File.WriteAllLinesメソッドの呼び出し
File.WriteAllLines(ファイル名, ファイルに書き込む内容(文字列配列または文字列のコレクション))
File.WriteAllLines(ファイル名, ファイルに書き込む内容(文字列配列または文字列のコレクション), 文字コード)

文字コードはEncodingクラスで指定します。 文字コードに対応するEncodingの取得方法は§.文字コードに別途まとめています。

File.WriteAllLinesメソッドでの書き込みにおける改行文字に関しては後述の§.改行文字を参照してください。

§2.3 File.WriteAllBytes (バイナリファイルの書き込み)

File.WriteAllBytesメソッドを使ってバイト配列の内容をファイルに書き込む
using System;
using System.IO;

class Sample {
  static void Main()
  {
    var bytes = new byte[] {0x01, 0x23, 0x45, 0x67};

    // バイト配列bytesの内容をバイナリファイルsample.datに書き込む
    File.WriteAllBytes("sample.dat", bytes);
  }
}

File.WriteAllBytesメソッドは、指定されたバイト配列の内容を指定されたファイルへと書き込みます。

File.WriteAllBytesメソッドの呼び出し
File.WriteAllBytes(ファイル名, ファイルに書き込む内容(バイト配列))

File.WriteAllBytesではバイト配列の一部分だけを書き込むことはできません。 一部分だけを書き込みたい場合は、BinaryWriterクラスStreamクラスのWriteメソッドを使って書き込む必要があります。

また、バイト型以外の配列を書き込むこともできません。 その場合もやはりBinaryWriterクラスを使って書き込むか、あるいは事前にバイト配列へ変換してから書き込む必要があります。

バイト配列への変換については基本型の型変換 §.バイト配列への/からの変換を参照してください。

§3 ファイル内容の追記

§3.1 File.AppendAllText (テキストファイルへの追記)

File.AppendAllTextメソッドを使って文字列をファイルの末尾に追記する
using System;
using System.IO;
using System.Text;

class Sample {
  static void Main()
  {
    var text = "追記内容";

    // 文字列textの内容をテキストファイルsample1.txtに追記する (UTF-8で書き込む)
    File.AppendAllText("sample1.txt", text);

    // 文字列textの内容をテキストファイルsample2.txtに追記する (UTF-8で書き込む)
    File.AppendAllText("sample2.txt", text, Encoding.UTF8);

    // 文字列textの内容をテキストファイルsample3.txtに追記する (Shift_JISで書き込む)
    File.AppendAllText("sample3.txt", text, Encoding.GetEncoding("Shift_JIS"));
  }
}

File.AppendAllTextメソッドは、指定された文字列の内容を指定されたファイルの末尾へと追記します。 また、文字コードが指定されていれば、その文字コードで書き込みを行い、文字コードを指定しない場合はデフォルトでUTF-8として書き込みを行います。

File.AppendAllTextメソッドの呼び出し
File.AppendAllText(ファイル名, ファイルに追記する内容)
File.AppendAllText(ファイル名, ファイルに追記する内容, 文字コード)

文字コードはEncodingクラスで指定します。 文字コードに対応するEncodingの取得方法は§.文字コードに別途まとめています。 追記前のファイルと異なる文字コードを指定して追記した場合は文字化けが起こるので注意してください。


File.AppendAllTextではファイルの先頭に追記することはできません。 先頭へ追記する場合は、次の例のように一旦ファイルの内容を文字列などに読み込み、その先頭に追記したい内容を追加した後に改めてファイルに書き込むなどする必要があります。

File.ReadAllTextメソッド・WriteAllTextメソッドを使ってファイルの先頭に追記する
using System;
using System.IO;
using System.Text;

class Sample {
  static void Main()
  {
    // ファイルの現在の内容を読み込む
    var text = File.ReadAllText("sample.txt", Encoding.UTF8);

    // 読み込んだ内容の'前に'追記内容を追加する
    text = "追記内容" + text;

    // 追記した内容をファイルへ書き込む
    File.WriteAllText("sample.txt", text, Encoding.UTF8);
  }
}

§3.2 File.AppendAllLines (行単位でのテキストファイルへの追記)

File.AppendAllLinesメソッドを使ってListに格納された行ごとの内容をファイルに追記する
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

class Sample {
  static void Main()
  {
    // 行ごとの内容を格納するList
    var lines = new List<string>();

    lines.Add("追記1行目");
    lines.Add("追記2行目");
    lines.Add("追記3行目");

    // List内の各文字列を1行としてテキストファイルsample1.txtに追記する (UTF-8で書き込む)
    File.AppendAllLines("sample1.txt", lines);

    // List内の各文字列を1行としてテキストファイルsample2.txtに追記する (UTF-8で書き込む)
    File.AppendAllLines("sample2.txt", lines, Encoding.UTF8);

    // List内の各文字列を1行としてテキストファイルsample3.txtに追記する (Shift_JISで書き込む)
    File.AppendAllLines("sample3.txt", lines, Encoding.GetEncoding("Shift_JIS"));
  }
}

File.AppendAllLinesメソッドは、指定された文字列配列や文字列コレクションに格納されている内容を行ごとの内容として、指定されたファイルの末尾に追記します。 書き込みに際して、各行の内容に続けて改行文字が自動的に書き込まれます。 また、文字コードが指定されていれば、その文字コードで書き込みを行い、文字コードを指定しない場合はデフォルトでUTF-8として書き込みを行います。

File.AppendAllLinesメソッドの呼び出し
File.AppendAllLines(ファイル名, ファイルに追記する内容(文字列配列または文字列のコレクション))
File.AppendAllLines(ファイル名, ファイルに追記する内容(文字列配列または文字列のコレクション), 文字コード)

文字コードはEncodingクラスで指定します。 文字コードに対応するEncodingの取得方法は§.文字コードに別途まとめています。 追記前のファイルと異なる文字コードを指定して追記した場合は文字化けが起こるので注意してください。

File.AppendAllLinesメソッドでの追記における改行文字に関しては後述の§.改行文字を参照してください。


File.AppendAllLinesではファイルの先頭に追記することはできません。 先頭へ追記する場合は、一旦ファイルの内容を文字列などに読み込み、その先頭に追記したい内容を追加した後に改めてファイルに書き込むなどする必要があります。 具体的な実装方法については§.File.AppendAllText (テキストファイルへの追記)での例を参照してください。

§4 改行文字

File.WriteAllLinesメソッドおよびFile.AppendAllLinesメソッドを使って行単位で書き込む際、プラットフォームで定義されている改行文字が用いられます。 すなわち、Windows系の環境ではCRLF、Macintosh系ではCR、Unix系ではLFが使われます。

Fileクラスの書き込みメソッドでは、引数などで書き込み時の改行文字を指定することはできません。 そのため、実行環境によらず特定の改行文字を指定して書き込みたい場合は、次の例のように目的の改行文字で連結した文字列をFile.WriteAllTextメソッドで書き込むか、あるいはStreamWriterを用いて書き込む必要があります。

目的の改行文字で連結した文字列をファイルに書き込む
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

class Sample {
  static void Main()
  {
    // 行ごとの内容を格納するList
    var lines = new List<string>();

    lines.Add("1行目");
    lines.Add("2行目");
    lines.Add("3行目");

    // linesの内容を改行文字LFで結合した文字列を作成する
    var text = string.Join("\n", lines);

    // 結合した文字列textの内容をテキストファイルsample.txtに書き込む
    // (LFで改行した状態の内容が書き込まれる)
    File.WriteAllLines("sample.txt", lines, Encoding.UTF8);
  }
}

プラットフォームの改行文字を取得・参照する方法についてはランタイム・システム・プラットフォームの情報 §.改行文字を参照してください。

StreamWriterを用いて改行文字を指定して書き込む方法についてはStreamReaderクラス・StreamWriterクラス §.改行文字を参照してください。


なお、ReadAllLinesメソッド・ReadLinesメソッドでは、プラットフォームによらずCRLFCRLFのすべてが改行として扱われた上で読み込まれます。 特定の文字だけを改行として扱いたい場合は、次の例のようにいったんReadAllTextメソッドを用いてすべての改行文字を維持した状態で読み込んだのち、String.Splitメソッドによって特定の改行文字で行に分割するなどの処理を行う必要があります。

CRのみを改行として行単位で読み込む(不完全なコード)
using System;
using System.IO;

class Sample {
  static void Main()
  {
    // 改行文字を維持したままファイル内容をすべて読み込む
    // (sample.txtは改行文字が混在した内容を想定)
    var text = File.ReadAllText("sample.txt");

    // CRのみを改行として読み込んだ内容を行に分割する
    var lines = text.Split('\r');
  }
}

この例では、"CRLF"のシーケンスを適切に扱えません。 例えば"行1CRLF行2…"のように"CRLF"のシーケンスで改行されている場合は"行1 <改行> LF行2…"として分割されます。 "CRLF"のシーケンスを改行とみなさずそのまま維持するには、より詳細に分割処理を記述する必要があります。


改行文字が混在するファイルを読み込み、特定の改行文字に置き換えた上で保存するような場合は次のようにすることができます。

  1. まず、File.ReadAllLinesメソッドを使って行に分割した状態で読み込む (このときファイル内に混在するCRLFCRLFはすべて改行として扱われた上で除去される)
  2. 次に、String.Joinメソッドを使って行の配列を目的の改行文字で結合した文字列にする
  3. 作成した文字列をファイルに保存する

これにより、ファイル内の改行文字を統一することができます。

ファイル内の混在する改行文字をCRLFに統一する
using System;
using System.IO;

class Sample {
  static void Main()
  {
    // 行に分割した状態でファイル内容をすべて読み込む
    // (sample.txtは改行文字が混在した内容を想定)
    var lines = File.ReadAllLines("sample.txt");

    // 改行文字にCRLFを使用して行を1つの文字列に結合する
    var text = string.Join("\r\n", lines);

    // 改行文字を統一した文字列をファイルに書き込む
    File.WriteAllText("sample.txt", text);
  }
}

§5 文字コード

§5.1 Encodingの取得

Fileクラスのメソッドを使ってファイルの読み書きを行う際、文字コードの指定にSystem.Text.Encodingクラスを使います。 特定の文字コードに対応するEncodingを取得するには次のようにします。

文字コードと対応するEncoding
文字コード BOM 対応するEncodingを取得するコード
UTF-8 あり Encoding.UTF8
なし new UTF8Encoding(false)
UTF-16 Little Endian あり Encoding.Unicode
なし new UnicodeEncoding(false, false)
UTF-16 Big Endian あり Encoding.BigEndianUnicode
なし new UnicodeEncoding(true, false)
UTF-32 Little Endian あり Encoding.UTF32
なし new UTF32Encoding(false, false)
UTF-32 Big Endian あり new UTF32Encoding(true, true)
なし new UTF32Encoding(true, false)
ASCII (7bit) Encoding.ASCII
Shift_JIS Encoding.GetEncoding("Shift_JIS")
Encoding.GetEncoding(932)
EUC-JP Encoding.GetEncoding("EUC-JP")
Encoding.GetEncoding(20932)
ISO-2022-JP Encoding.GetEncoding("ISO-2022-JP")
Encoding.GetEncoding(50220)
文字コード 対応するEncodingを取得するコード

このほかの文字コードに関してはEncodingクラスのドキュメントを参照してください。

実際のコードでは次のように文字コードを指定します。

文字コードを指定してテキストファイルを書き込む
using System;
using System.IO;
using System.Text;

class Sample {
  static void Main()
  {
    var text = "text日本語テキスト";

    // BOMありのUTF-8で書き込む
    File.WriteAllText("sample-utf8bom.txt", text, Encoding.UTF8);

    // BOMなしのUTF-8で書き込む
    File.WriteAllText("sample-utf8.txt", text, new UTF8Encoding(false));

    // Shift_JISで書き込む
    File.WriteAllText("sample-shiftjis.txt", text, Encoding.GetEncoding("Shift_JIS"));

    // Shift_JISで書き込む (上記のコードと同じ)
    File.WriteAllText("sample-shiftjis.txt", text, Encoding.GetEncoding(932));
  }
}

UTFエンコーディングを用いる場合、書き込みに際してBOM(Byte Order Mark)を出力するかどうかは、書き込みメソッドに指定するEncodingによって変えることができます。 一方、読み込みの場合は、BOMの有無に関わらず自動的にBOMが除去された上で読み込まれます。

EncodingクラスとBOMに関してより詳しくはSystem.Text.EncodingのBOMありなしの制御で解説しています。

BOMを除去せずに読み込みたい場合は、File.ReadAllBytesメソッドによっていったんバイナリとして読み、その後テキストとして処理する必要があります。

§5.2 文字コードの自動判別

Fileクラスの読み込みメソッドでは、文字コードの自動判別は行えません。 必ず文字コードを指定した上で読み込む必要があります。 ファイルの内容と異なる文字コードを指定した場合は文字化けが起こります。 なお、ファイルの先頭にBOMが付与されている場合は、UTF-8およびUTF-32のみ自動的に検出されるとされています。

文字コードを自動判別して読み込むにはShift JISとEUC-JPの判別で掲載しているような判別コードを自前で用意するか、あるいはサードパーティー製のライブラリ等を用いる必要があります。

§5.3 言語設定に対応する文字コード

プラットフォームのデフォルトの文字コードを取得したい場合はEncoding.Defaultプロパティを使用します。 また、現在の言語設定に対応する文字コード(ANSIコード)を取得したい場合は、Encoding.GetEncodingメソッドの引数にCultureInfo.TextInfo.ANSICodePageプロパティの値を指定します。

詳しくはプロセス・アセンブリの情報 §.デフォルトエンコーディングおよびプロセス・アセンブリの情報 §.カルチャのエンコーディングを参照してください。

§6 ファイルのパス

Fileクラスのメソッドでは、ファイル名にカレントディレクトリからの相対パス、あるいは絶対パスを指定することができます。 ディレクトリとファイル名を別けた状態で指定することはできないので、その場合はPath.Combineメソッドでパスを結合します。

また、ワイルドカードを指定して複数のファイルを同時に読み書きすることもできません。 Fileクラスのメソッドではファイルをひとつずつ扱う必要があります。 ワイルドカードを使ってファイルを検索するには、Directory.EnumerateFilesメソッドでファイルを検索します。

Fileクラスのメソッドとファイルパスの指定方法
using System;
using System.IO;

class Sample {
  static void Main()
  {
    string text;

    // カレントディレクトリにあるsample.txtの内容を読み込む (相対パスでの指定)
    text = File.ReadAllText("sample.txt");

    // E:\sample.txtの内容を読み込む (絶対パスでの指定)
    text = File.ReadAllText(@"E:\sample.txt");

    // ディレクトリE:\text\にあるsample.txtの内容を読み込む
    // (Path.Combineでディレクトリパスとファイルパスを結合する)
    string directory = @"E:\text\";

    text = File.ReadAllText(Path.Combine(directory, "sample.txt"));

    // ディレクトリE:\text\、ワイルドカードsample-*.txtにマッチするファイルをひとつずつ読み込む
    foreach (var file in Directory.EnumerateFiles(@"E:\text\", "sample-*.txt")) {
      text = File.ReadAllText(file);
    }
  }
}

ワイルドカードを指定したファイルの検索についてはファイル・ディレクトリの操作 §.ディレクトリの走査・ファイルの検索を参照してください。

Path.Combineメソッドによるパスの結合など、ファイルパスに関する操作についてはパスの操作を参照してください。

カレントディレクトリを取得・参照する方法はプロセス・アセンブリの情報 §.カレントディレクトリ、現在実行している実行可能ファイルのあるディレクトリを取得する方法はプロセス・アセンブリの情報 §.自プロセスのパスを参照してください。

C#ではパス文字列の記述に逐語的文字列リテラルを用いることができます。 詳しくはリテラルとサフィックス §.逐語的文字列リテラルを参照してください。

§7 CSVを読み込む

ここではFileクラスを使ったファイルの読み込み、および読み込んだ内容を型変換する具体例として、CSVファイルを読み込み、読み込んだデータをインスタンスに復元する例を紹介します。 この例では、以下のようにカンマを区切り文字とするCSVファイルを読み込みます。

入力ファイル(sample.csv)
Alice,0,2016-01-01T00:00:00
Bob,1,2016-02-29T12:34:56
Charlie,2,2016-03-01T15:00:00
File.ReadAllLinesメソッドを使ってCSVファイルを読み込む
using System;
using System.IO;
using System.Text;

// CSVファイルから読み込むデータ構造を表すクラス
class Account {
  public string Name;
  public int ID;
  public DateTime LastLogin;

  public override string ToString()
  {
    return string.Format("Name = {0}, ID = {1}, LastLogin = {2:r}",
                         Name, ID, LastLogin);
  }
}

class Sample {
  static void Main()
  {
    // sample.csvを1行ずつ読み込む
    foreach (var line in File.ReadLines("sample.csv")) {
      // 行をカンマで分割する
      var columns = line.Split(',');

      // 読み込んだデータを設定するインスタンス
      var a = new Account();

      // 1カラム目は変換せず代入する
      a.Name = columns[0];

      // 2カラム目は数値に変換する
      a.ID = int.Parse(columns[1]);

      // 3カラム目は厳密に定義された書式"s"でDateTimeに変換する
      a.LastLogin = DateTime.ParseExact(columns[2], "s", null);

      // 読み込んだデータを表示する
      Console.WriteLine(a);
    }
  }
}
実行結果
Name = Alice, ID = 0, LastLogin = Fri, 01 Jan 2016 00:00:00 GMT
Name = Bob, ID = 1, LastLogin = Mon, 29 Feb 2016 12:34:56 GMT
Name = Charlie, ID = 2, LastLogin = Tue, 01 Mar 2016 15:00:00 GMT

このサンプルで使用している書式"s"およびDateTime.ParseExactメソッドについては日時・文字列の変換と書式 §.標準の書式および書式指定子 §.日付と時刻の書式指定子を参照してください。

このサンプルはごく基本的な機能しか実装していません。 このサンプルには以下のような不足があります。

カラムの前後に空白があった場合、それもそのまま読み込まれる
前後の空白を除去する場合はString.Trimなどのメソッドを使うことができます。 (文字列の加工・編集 §.余白の削除 (Trim, TrimEnd, TrimStart))
行または個々のカラムのデータや書式が不正だった場合に例外となる
int.Parseなどのメソッドは、文字列が不正な書式の場合に例外FormatExceptionをスローします。 文字列が値として妥当かチェックした上で、不正だった場合にデフォルト値など代替となる値を設定したいような場合にはint.TryParseなどのメソッドを使うことができます。 (基本型の型変換 §.文字列からの変換 (Parse, TryParse))
コメント行などを記述できない
行頭が#の場合はコメント行として扱うなどの処理を記述する場合は、String.StartsWithなどのメソッドを使うことによってそれらの行を無視するようにすることができます。 (文字列の探索・比較 §.部分文字列の一致 (Contains, StartsWith, EndsWith))
"'でクオートされているカラムを適切に処理できない
String.Splitメソッドではクオートされているかを考慮せずに分割を行うため、クオートされたカラムを含むCSVを適切に扱えません。 より厳密に分割処理を行うように記述するか、独自に処理を実装する代わりにMicrosoft.VisualBasic.FileIO.TextFieldParserなどのクラスを使います。

クラスや構造体のインスタンスをファイルに保存したり、逆にファイルから復元するにはシリアライズを用いることもできます。 詳しくはシリアライズの基本を参照してください。

§8 FileクラスのメソッドとStreamReader/Writer・BinaryReader/Writerの対比

一般に、何らかのデータ構造やフォーマットを持っているファイルの読み書きでは、StreamReader/StreamWriterあるいはBinaryReader/BinaryWriterの方が向いています。 特に、ファイルから数値など特定のデータ型の値を読み込む・書き込むような場合には、FileクラスのメソッドよりもStreamReader/StreamWriter・BinaryReader/BinaryWriterの方が適しています。 一方、ファイルにそういった構造やフォーマットがない場合、あるいは無視して単なるデータ列として読み込み・書き込みを行う場合は、Fileクラスのメソッドが便利です。

以下では、FileクラスのメソッドとStreamReader/StreamWriterおよびBinaryReader/BinaryWriterを使った場合を比較を例示します。 ファイルを扱う際に、どちらが目的にあっているか検討する際の参考としてご覧ください。

§8.1 テキストファイルから1行ずつ読み込む

File.ReadLinesを使って1行ずつ読み込み、行番号を付けて表示する
using System;
using System.IO;
using System.Text;

class Sample {
  static void Main()
  {
    int lineCount = 0;

    foreach (var line in File.ReadLines("sample.txt", Encoding.UTF8)) {
      lineCount++;

      // 行番号を付けて行の内容を表示する
      Console.WriteLine("{0:D3}: {1}", lineCount, line);
    }
  }
}
StreamReaderを使って1行ずつ読み込み、行番号を付けて表示する
using System;
using System.IO;
using System.Text;

class Sample {
  static void Main()
  {
    using (var reader = new StreamReader("sample.txt", Encoding.UTF8)) {
      int lineCount = 0;
      string line = null;

      for (;;) {
        line = reader.ReadLine(); // 1行読み込む

        if (line == null)
          break; // ファイルの終端まで読み込んだ

        lineCount++;

        // 行番号を付けて行の内容を表示する
        Console.WriteLine("{0:D3}: {1}", lineCount, line);
      }
    }
  }
}
sample.txtの内容
かごめかごめ
かごのなかのとりは
いついつでやる
実行結果
001: かごめかごめ
002: かごのなかのとりは
003: いついつでやる

この例で使用している書式指定子D3は、数値を三桁の10進数として出力するものです。 この書式指定子については書式指定子 §.D, d (decimal/10進数)を参照してください。

§8.2 テキストファイルに1行ずつ書き込む

File.WriteAllTextメソッドを使って行ごとに改行された内容を書き込む
using System;
using System.IO;
using System.Text;

class Sample {
  static void Main()
  {
    string text; // ファイルに書き込む内容

    // 1行目
    text = "かごめかごめ" + Environment.NewLine;

    // 2行目
    text += "かごのなかのとりは" + Environment.NewLine;

    // 3行目
    text += "いついつでやる" + Environment.NewLine;

    File.WriteAllText("sample.txt", text, Encoding.UTF8);
  }
}
StreamWriterを使って行ごとに改行された内容を書き込む
using System;
using System.IO;
using System.Text;

class Sample {
  static void Main()
  {
    // sample.txtに書き込むStreamWriterを作成する
    // (false: 内容の追記ではなく上書きする)
    using (var writer = new StreamWriter("sample.txt", false, Encoding.UTF8)) {
      writer.WriteLine("かごめかごめ");        // 1行目
      writer.WriteLine("かごのなかのとりは");  // 2行目
      writer.WriteLine("いついつでやる");      // 3行目
    }
  }
}
sample.txtに書き込まれる内容
かごめかごめ
かごのなかのとりは
いついつでやる

この例で使用しているEnvironment.NewLineは現在のプラットフォームにおける改行文字を取得するプロパティです。 詳しくはランタイム・システム・プラットフォームの情報 §.改行文字を参照してください。

文字列を改行しながら連結していく場合、StringBuilderクラスとStringBuilder.AppendLineメソッドを使うこともできます。

§8.3 バイナリファイルから数値を読み込む

File.ReadAllBytesを使ってバイナリファイルから数値を読み込む
using System;
using System.IO;

class Sample {
  static void Main()
  {
    var data = File.ReadAllBytes("sample.dat");

    // 読み込んだバイト配列から4バイト整数を3つ読み込んで表示する

    // バイト配列のインデックス0から4バイト分を32ビット整数に変換する
    Console.WriteLine(BitConverter.ToInt32(data, 0));

    // バイト配列のインデックス4から4バイト分を32ビット整数に変換する
    Console.WriteLine(BitConverter.ToInt32(data, 4));

    // バイト配列のインデックス8から4バイト分を32ビット整数に変換する
    Console.WriteLine(BitConverter.ToInt32(data, 8));
  }
}
BinaryReaderを使ってバイナリファイルから数値を読み込む
using System;
using System.IO;

class Sample {
  static void Main()
  {
    // ファイルsample.datを開いて、そのファイルから読み込むFileStreamを開く
    using (var stream = File.OpenRead("sample.dat")) {
      // FileStreamから読み込むBinaryReaderを作成
      using (var reader = new BinaryReader(stream)) {
        // 4バイト(32ビット)整数を読み込んで表示する
        Console.WriteLine(reader.ReadInt32());
        Console.WriteLine(reader.ReadInt32());
        Console.WriteLine(reader.ReadInt32());
      }
    }
  }
}
入力ファイルsample.datの内容(バイナリダンプ)
0000000 10 00 00 00 03 00 00 00 5b d7 03 00
0000014
実行結果
16
3
251739

この例で使用しているBitConverterについては基本型の型変換 §.基本型とバイト配列への/からの変換を参照してください。

§8.4 バイナリファイルに数値を書き込む

File.WriteAllBytesメソッドを使ってバイナリファイルに数値を書き込む
using System;
using System.IO;

class Sample {
  static void Main()
  {
    var buffer = new byte[12]; // 書き込むデータを格納するバッファ(12バイト)

    // 4バイト整数値16をバイト配列に変換し、
    // バッファのインデックス0からの4バイト分にコピーする
    Array.Copy(BitConverter.GetBytes((int)16), 0, buffer, 0, 4);

    // 4バイト整数値3をバイト配列に変換し、
    // バッファのインデックス4からの4バイト分にコピーする
    Array.Copy(BitConverter.GetBytes((int)3), 0, buffer, 4, 4);

    // 4バイト整数値251739をバイト配列に変換し、
    // バッファのインデックス8からの4バイト分にコピーする
    Array.Copy(BitConverter.GetBytes((int)251739), 0, buffer, 8, 4);

    File.WriteAllBytes("sample.dat", buffer);
  }
}
BinaryWriterを使ってバイナリファイルに数値を書き込む
using System;
using System.IO;

class Sample {
  static void Main()
  {
    // ファイルsample.datを上書きモードで作成して、そのファイルに書き込むFileStreamを開く
    using (var stream = File.Create("sample.dat")) {
      // FileStreamに書き込むBinaryWriterを作成
      using (var writer = new BinaryWriter(stream)) {
        writer.Write((int)16); // 4バイト整数を書き込む
        writer.Write((int)3);
        writer.Write((int)251739);
      }
    }
  }
}
sample.datに書き込まれる内容(バイナリダンプ)
0000000 10 00 00 00 03 00 00 00 5b d7 03 00
0000014

この例で使用しているBitConverterについては基本型の型変換 §.基本型とバイト配列への/からの変換を参照してください。