1. はじめに
StreamWriterは、.NETの名前空間System.IOの中でも、テキストデータをストリーム経由でファイルに書き込むのに超便利なクラスだよ。
なんでいきなりFileStreamでやっちゃダメなの?
FileStreamはバイト単位でしか操作できないんだ。文字列を書き込もうとすると、自分でテキストをバイトに変換したり、エンコーディングを気にしたりしなきゃいけない(そのうち絶対StreamWriterに戻りたくなるよ)。
StreamWriterなら、そういう面倒は全部おまかせ。文字列を渡せば、必要なバイトにしてファイルに書いてくれる。
主なメリット:
- バイト変換とか気にせずに文字列を書ける。
- 1行ずつテキストを書き込むメソッドがある。
- バッファやエンコーディングの制御もできる(これも後でやるよ)。
超シンプルな例
using System.IO;
string path = "output.txt";
using (StreamWriter writer = new StreamWriter(path))
{
writer.WriteLine("こんにちは、世界!");
writer.WriteLine("これは2行目だよ。");
}
// usingブロックを抜けるとStreamWriterがちゃんとファイルを解放してくれる。
ここで何が起きてる?
- 書き込み用にファイルを開く(ファイルがなければ作られる)。
- 各行はファイルの別々の行として書き込まれる(WriteLineメソッド)。
- usingブロックの後は自動でファイルが閉じられる。エラーがあっても大丈夫。
このプログラムを実行した後でoutput.txtを開くと、ちゃんと2行のテキストが入ってるはず。
大事なポイント
もしファイルがすでに存在してたら、最初から上書きされるよ!中身は全部消えるから注意。大事な論文とか、唯一の領収書とかはこういうファイルに入れないでね。
2. データをストリームに書き込む
StreamWriterの主なメソッド
| メソッド | 説明 |
|---|---|
|
改行なしで文字列を書き込む |
|
改行付きで文字列を書き込む |
|
バッファを強制的にファイルに書き込む(手動でやることはあんまりない) |
/ |
ストリームを閉じてリソース解放(usingがやってくれる) |
|
ベースのストリーム(例: FileStream)にアクセスできる |
Write()メソッド
改行せずにデータを書き込む。続けて書くと同じ行にどんどん追加されるよ。
WriteLine()メソッド
自動で改行コードを追加して書き込む(Windowsなら\r\n、Unix系なら\n)。
毎回Enterキーを押してる感じ。
Write()とWriteLine()の違いデモ
using (var writer = new StreamWriter("example.txt"))
{
writer.Write("最初の ");
writer.Write("段落。");
writer.WriteLine("行を追加して、Enter!");
writer.Write("2番目の段落。");
}
これでexample.txtはこんな感じになるよ:
最初の 段落。行を追加して、Enter!
2番目の段落。
3. エンコーディングの扱い
デフォルトでStreamWriterをパラメータなしで作ると、UTF-8BOM付き(Byte Order Mark)になるよ。
今どきはこれでOKだけど、古いソフトやインポート用データの互換性のためにエンコーディングを指定したい場合もある。
エンコーディングの指定方法
// Windows-1251(古いシステム用キリル文字)のファイルを書き込む
using (var writer = new StreamWriter("cyrillic.txt", false, System.Text.Encoding.GetEncoding("windows-1251")))
{
writer.WriteLine("こんにちは、キリル世界!");
}
大事なポイント:
エンコーディングはシステムでサポートされてる必要があるよ。不安ならUTF-8を使おう。
4. コンストラクタの追加パラメータ
StreamWriterの中身をちょっと覗いてみよう:
public StreamWriter(
string path, // ファイルのパス
bool append = false, // ファイルの末尾に追記する?
Encoding encoding = null, // エンコーディング
int bufferSize = 1024 // バッファサイズ(バイト単位)
)
- append — false(デフォルト)なら上書き。trueなら末尾に追加。
- encoding — 使うエンコーディング。
- bufferSize — 大量データのときに効く内部バッファサイズ。
例: 同じファイルに追記する
// ファイルは上書きじゃなくて追記される
using (var writer = new StreamWriter("log.txt", append: true))
{
writer.WriteLine(DateTime.Now + " -- 新しいイベント");
}
5. 便利なポイント
追記と上書きのとき何が起きる?
| モード | 何をする? | ファイルの結果 |
|---|---|---|
| append: false | 全部きれいに上書き | 古いデータは消える |
| append: true | 新しい行を末尾に追加 | 古い行は残る |
ヒント: 追記モード(append: true)はログとか履歴を残したいときに超便利!
StreamWriterと大量データ
- StreamWriterは書き込みをバッファリングしてる。実際にファイルに書かれるのはちょっと後。でもストリームを閉じる(またはFlush()を呼ぶ)と確実にディスクに保存される。
- WriteLineで1行ずつ書くのはめっちゃ効率的。JSON、CSV、XMLみたいな複雑なフォーマットは専用ライブラリを使うか、カンマやクォートのエスケープに気をつけてね。
正しい終了方法とリソース解放
正しいやり方: いつもusingを使おう!
これで、たとえ例外(例えばディスクが急に「いっぱい」になったり、他のプログラムがファイルをロックしたりしても)でも、ファイルはちゃんと閉じられる。
flowchart TD
A[StreamWriterの作成] --> B[ファイル操作]
B --> C{例外発生?}
C -- はい --> D[Disposeが呼ばれる]
C -- いいえ --> D
D --> E[ファイルは確実に閉じられる]
6. 実践例
この講座の中で、簡単な本の管理プログラムを作るとして、新しい本をファイルに書き込む機能を追加してみよう。
例: 新しい本を別ファイルに保存する
using System;
using System.IO;
class Program
{
static void Main()
{
Console.WriteLine("本のタイトルを入力してね:");
string bookTitle = Console.ReadLine();
Console.WriteLine("著者を入力してね:");
string author = Console.ReadLine();
string path = "books.txt";
using (var writer = new StreamWriter(path, append: true))
{
writer.WriteLine($"{bookTitle};{author}");
// CSV形式: 1行が1冊、セミコロン区切り
}
Console.WriteLine("本をファイルに保存したよ!");
}
}
何冊か続けて追加してみて。books.txtには前の行を消さずにどんどん追加されるよ。こういう動きはログや履歴管理に便利。将来Enterprise開発者になったときの監査システムにも使えるかもね。
7. ファイル書き込みでよくあるミスを避けるには
初心者がよくハマるポイントはこんな感じ:
ファイルが閉じられてなくて他のプロセスにロックされる。原因はusingを忘れたこと。
たくさん書いたのにファイルが空っぽ:Flush()やストリームのクローズを忘れた(usingなら自動でやってくれる)。
追記したつもりが上書きしちゃった:append: trueを指定し忘れた。
エンコーディングの問題:ファイルがメモ帳で「文字化け」するのは、エンコーディングが違うか、他のソフトがUTF-8に対応してない。
UnauthorizedAccessExceptionやDirectoryNotFoundException:保存先に権限がないか、存在しないフォルダに書こうとしてる。パスと権限を確認しよう。
エラー "file is used by another process":ファイルを開いたまま閉じてないか、他の誰かが同時に書き込もうとしてる。
GO TO FULL VERSION