C# – バイナリファイル (バイナリデータ) の読み込み・書き込み

概要

  • 「FileStream」クラスのオブジェクトを作成する
  • 「BinaryReader」クラスを使用して、バイナリデータを読み込む
  • 「BinaryWriter」クラスを使用して、バイナリデータを書き込む
using System;
using System.IO;
using System.Collections.Generic;

namespace BinaryEditorBase
{
    public static class BinaryEditor
    {
        /// <summary>
        /// バイナリ読み込み
        /// </summary>
        /// <param name="binFileStream">FileStream型オブジェクト</param>
        /// <param name="address">読み込み開始アドレス</param>
        /// <param name="length">読み込むバイト長</param>
        /// <returns>バイト型配列</returns>
        /// <remarks>
        /// 異常な値を入力した場合、空配列が返る
        /// </remarks>
        public static byte[] BinaryRead(FileStream binFileStream, long address, int length)
        {
            // byte型変数を格納できるListコレクションを宣言
            List<byte> data = new List<byte>();
            // ファイルストリームとアドレスのチェック
            if (binFileStream != null && address > -1)
            {
                // ファイルの最終アドレスより指定アドレスが大きい場合、
                // 空のバイト型配列を返す
                if (binFileStream.Length - 1 < address)
                {
                    return data.ToArray();
                }
                // 開始アドレス + 読み取り範囲の値がファイルの最終アドレスを
                // 超える場合、読み取り範囲をファイルの最終アドレス迄にする
                int readLength = length;
                if (address + readLength > binFileStream.Length)
                {
                    readLength = (int)(binFileStream.Length - address);
                }
                // バイナリ読み込み
                BinaryReader binReader = new BinaryReader(binFileStream);
                // 指定したアドレスに読み込み位置を移動
                binFileStream.Seek(address, SeekOrigin.Begin);
                // 読み込み
                data.AddRange(binReader.ReadBytes(readLength));
                // バイト型配列にして返す
                return data.ToArray();
            }
            else
            {
                // 空のバイト型配列を返す
                return data.ToArray();
            }
        }

        /// <summary>
        /// バイナリ書き込み
        /// </summary>
        /// <param name="binFileStream">FileStream型オブジェクト</param>
        /// <param name="address">書き込み開始アドレス</param>
        /// <param name="data">書き込むバイト型配列</param>
        public static void BinaryWrite(FileStream binFileStream, long address, ref byte[] data)
        {
            // ファイルストリームとアドレスのチェック
            if (binFileStream != null && address > -1)
            {
                // バイナリ書き込み
                BinaryWriter binWriter = new BinaryWriter(binFileStream);
                // 指定したアドレスに書き込み位置を移動
                binFileStream.Seek(address, SeekOrigin.Begin);
                // 書き込み
                binWriter.Write(data);
            }
        }
        [STAThread]
        static void Main()
        {
            // ファイル読み込み用
            FileStream rfs = null;
            // ファイル書き込み用
            FileStream wfs = null;
            try
            {
                // 「input.bin(パスは必要に応じて変更)」からバイナリデータを読み込む
                rfs = new FileStream("../../input.bin", FileMode.Open, FileAccess.Read, FileShare.Read);
                // バイナリファイル読み込み
                byte[] bytes = BinaryEditor.BinaryRead(rfs, 0x00000000, 0x00000040);
                // 「output.bin(パスは必要に応じて変更)」へバイナリデータを書き込む
                wfs = new FileStream("../../output.bin", FileMode.OpenOrCreate, FileAccess.Write);
                // バイナリファイル書き込み
                BinaryEditor.BinaryWrite(wfs, 0x00000000, ref bytes);
                Console.WriteLine("ファイルを出力しました");
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
            finally
            {
                if (rfs != null)
                {
                    rfs.Close();
                }
                if (wfs != null)
                {
                    wfs.Close();
                }
            }
            // 終了処理
            Console.Write("何かキーを押してください");
            Console.Read();
        }
    }
}

説明

(15行目) そのまま読み込むのはあまりに手抜きなので、ここでは誤った数字を入れてもエラーを回避するように関数を定義しました。「FileStream」インスタンス、 読み込みを開始するアドレス、及び、そこから読み込むバイト数を引数として与えています。開始アドレスや読み込み量が以上の場合、戻り値は空のbyte型配列となります。

(39~45行目) 「BinaryReader」クラスを使用して、バイナリデータを読み込んでいます。

(61行目) 読み込みとほぼ同じです。「FileStream」インスタンス、書き込みを開始するアドレス、及び実際に書き込むデータをbyte型配列の参照で渡します。byte型配列は 大きくなりがちなので、参照として渡すことで、メモリの節約等が出来ます。

(67~73行目) 「BinaryWriter」クラスを使用して、バイナリデータを書き込んでいます。

(88行目) FileStream型のオブジェクトを生成しています。ここでは読み込み用として宣言しています。

(91行目) ファイル「input.bin」からバイナリデータを読み込みます。開始位置はアドレス「0x00000000(ファイルの先頭)」、読み込み量は「0x00000040(64バイト)」としました。「0x??」という表記は、 16進数表記を意味します

(94行目) FileStream型のオブジェクトを生成しています。ここでは書き込み専用として宣言しています。

(97行目) ファイル「output.bin」へバイナリデータを書き込みます。開始位置は「0x00000000(ファイルの先頭)」で、91行目で読み込んだバイナリデータをそのまま書き込んでいます。

とりあえず基本ですね^^;ここで切っておきます。