バイナリファイルの読み書き。PNG の縦横サイズを取得してみる
BinaryReader, BinaryWriter クラスを用いて、バイナリデータの読み書きを行うサンプルです。
using System; using System.IO; class Program { const string filename = "data.dat"; static void Read() { using (var reader = new BinaryReader(File.Open(filename, FileMode.Open))) { int x = reader.ReadInt32(); char c1 = reader.ReadChar(); char c2 = reader.ReadChar(); Console.WriteLine("x: 0x{0:X}", x); Console.WriteLine("c1: {0}", c1); Console.WriteLine("c2: {0}", c2); } } static void Write() { using (var writer = new BinaryWriter(File.Open(filename, FileMode.Create))) { writer.Write(0x11FF33cc); writer.Write('a'); writer.Write('あ'); } } static void Main() { Write(); Read(); } }
実行結果です。
x: 0x11FF33CC c1: a c2: あ
hexdump コマンドで作成したファイルの中身を確認してみます。
$ hexdump data.dat 0000000 cc 33 ff 11 61 e3 81 82 0000008
PNG ファイルの縦横サイズを取得してみる
PNGについて のページには、PNG のファイルフォーマットの解説があります。
ここでは BinaryReader クラスを用いて、PNG ファイルの縦横サイズを取得してみます。
using System; using System.Collections.Generic; using System.Linq; using System.IO; class Program { // BinaryReader の ReadInt32() はリトルエンディアンで読み込むので自作する static int Read32(BinaryReader reader) { int x = 0; for (int i = 0; i < 4; i++) { var b = reader.ReadByte(); x = (x << 8) | b; } return x; } // bytes バイト分読み込む static byte[] Eat(int bytes, BinaryReader reader) { var ret = new byte[bytes]; for (int i = 0; i < bytes; i++) { ret[i] = reader.ReadByte(); } return ret; } static void Read(string filename) { using (var reader = new BinaryReader(File.Open(filename, FileMode.Open))) { // PNG 識別部 var png = Eat(8, reader); Console.WriteLine("PNG 識別部"); Console.WriteLine(string.Join(" ", png.Select(e => string.Format("0x{0:X}", e)))); // --- 本体部 ---- Read32(reader); // データ長 // 名称 var name = Eat(4, reader); Console.WriteLine(string.Join("", name.Select(e => (char)e))); // IHDR が一番最初に必ず存在する int width = Read32(reader); int height = Read32(reader); Console.WriteLine("width = {0}", width); Console.WriteLine("height = {0}", height); } } static void Main() { Read("test.png"); // 横 320 縦 60 の画像を読み込む } }
4 バイトのデータ長を取得するときに、BinaryReader クラスの ReadInt32() メソッドではなく自作の Read32() メソッドを使用しています。これは、ReadInt32() メソッドはリトルエンディアンで読み込むためです。
実行結果です。
PNG 識別部 0x89 0x50 0x4E 0x47 0xD 0xA 0x1A 0xA IHDR width = 320 height = 60