この記事では筆者がFileStreamについて学んだことをまとめています。
そもそもStreamって
C#にはOOStreamというクラスがたくさんありますが、それらはすべてStreamという抽象クラスを継承して作られたものです。
FileStreamもStreamを継承したもので主にファイルの入出力に携わります。
本題:FileStreamの使い方
FileStream
は主に二つのモードに分かれていて、一つがファイルの書き出し、もう一つがファイルの読み込みです。具体例を交えてみてみましょう。
ファイルを書き出すとき
まず大前提としてファイルに何かを書き込むときは、それをByteに直して書き込みます。以下のコードを参照。
string text1 = "abcdef";
string text2 = "ghijkl";
byte[] textbyte1 = Encoding.UTF8.GetBytes(text1);
byte[] textbyte2 = Encoding.UTF8.GetBytes(text2);
ではこのbyte[]
を書き込んでいきます。
FileStream fs = new FileStream(/*ファイルのパス*/,FileMode.Create,FileAccess.Write);
fs.Write(BitConverter.GetBytes(textbyte1.Length), 0, sizeof(int));/*注目*/
fs.Write(textbyte1,0,textbyte1.Length);
fs.Write(BitConverter.GetBytes(textbyte2.Length), 0, sizeof(int));/*注目*/
fs.Write(textbyte2,0,textbyte2.Length);
fs.Close();
ここで注目してほしい点が二つあります。
一つ目
fs.Write(BitConverter.GetBytes(textbyte1.Length), 0, sizeof(int));
なぜこの行が存在するかというとtextbyte1
を書き込んだファイルを読み込む際にbyte[]
のサイズがわからないと困るからです。この行があることでtextbyte1
のサイズを書き込むことができます。sizeof(int)
については下で補足します。
補足1
textbyte1
のサイズを書き込んだbyte[]
の長さはtextbyte1.Length
がint型
なのでかならず4バイトになります。なのでsizeof(int)
となっているところを4バイトと書いてもいいんですが、後で見て何をしたかったのかがすぐにわかるのでこちらをおすすめします。
補足2
上記のコードブロックでは最終行にfs.Close();
と記述されいますが、OOStreamでは基本的にやりたい動作が終わったらこのように解放してあげましょう。C#は基本的にプログラマーが意識して解放しなくてもいいように作られているので最初こそ慣れないでしょうが、失敗してでもいいので頑張りましょう。なお筆者は動画のフレームを開放し忘れてメモリが成仏しかけました。
ただし、方法がないわけではありません.。
C#にはこれまた便利なステートメントがあります。それが次に紹介するusing()
ステートメントです。これを使ってコードブロックを書き換えると
using(var fs = new FileStream(/*ファイルのパス*/,FileMode.Create,FileAccess.Write)){
fs.Write(BitConverter.GetBytes(textbyte1.Length), 0, sizeof(int));
fs.Write(BitConverter.GetBytes(textbyte2.Length), 0, sizeof(int));/*24,25行目に注目*/
fs.Write(textbyte1,0,textbyte1.Length);
fs.Write(textbyte2,0,textbyte2.Length);
}
主な機能としてはこのブロックの処理が終わってusing()
ステートメントを抜けると自動的に解放されます。また処理部がわかりやすくなるのも筆者的にgoodポイントです。
ファイルを読み込むとき
次にファイルを読み込んでみましょう。
string text1 = "";
string text2 = "";
using(var fs = new FileStream(/*ファイルのパス*/,FileMode.Open,FileAccess.Read)){
byte[] basebytes = new byte[sizeof(int)];
fs.Read(basebytes,0,sizeof(int));
bytes[] text1bytes = new byte[BitConverter.ToInt32(basebytes, 0)];
fs.Read(text1bytes,0,BitConverter.ToInt32(basebytes, 0));//intに変換する
text1 = Encoding.UTF8.GetString(text1bytes);/*UTF-8で書き込んだからUTF-8で読み込みます。*/
~~~~ text2も同様 ~~~~
}
まずはtext1bytes
のlength
を求めるため、basebytes
に書き込んでいます。次にbasebytes
をtext1bytes
の初期化時にint型へ変えて範囲に使います。
補足1
Write()
やRead()
を実行するとfs.Position
プロパティが自動的に更新されます。なのでfs.Read()
などを実行しても基本的に読み取る範囲が重複することはありません。
お疲れさまでした。
以上がFileStream
を使った基本的なファイルの入出力です。応用として与えるbytes[]
を暗号化してファイルに書き込むなどいろいろ考えられます。ぜひ活用してください。
最後に
この記事は初めて書いたもので説明が偏ったり、文章の拙い部分があったりと読みにくいところもあったと思いますが、読んでいただきありがとうございました。一緒にいろんなことを学んでいきましょう!