5

Cの場合と同様に、構造ポインターを使用してファイルヘッダーなどの構造化バイナリデータを読み書きできますが、C#でこれを行う同様の方法はありますか?

4

3 に答える 3

9

私の意見では、aを使用することが最善の方法BinaryReaderである傾向があります。BinaryWriterMemoryStream

バイナリデータの解析:

byte[] buf = f                     // some data from somewhere
using (var ms = new MemoryStream(buf, false)) {   // Read-only
    var br = new BinaryReader(ms);

    UInt32 len = br.ReadUInt32();
    // ...
}

バイナリデータの生成:

byte[] result;
using (var ms = new MemoryStream()) {   // Expandable
    var bw = new BinaryWriter(ms);

    UInt32 len = 0x1337;
    bw.Write(len);
    // ...

    result = ms.GetBuffer();   // Get the underlying byte array you've created.
}

これらを使用すると、、、、、およびそれらの配列など(U)Int16, 32, 64、ほとんどSingleのファイルヘッダーなどに必要なすべてのプリミティブ型を読み書きできます。s は直接サポートされていますが、Doublebytecharstring

文字列の前には長さがあり、一度に7ビットの整数としてエンコードされます。

これは、この方法からこの方法で文字列を記述した場合にのみ役立つようですBinaryWriter。ただし、文字列の前にDWordの長さがあり、その後にその数のASCII文字が続くと言うのは簡単です。

int len = (int)br.ReadUInt32();
string s = Encoding.ASCII.GetString(br.ReadBytes(len));

およびオブジェクトがブロックにラップされていないことに注意してください。これは、それらがであるにもかかわらず、基礎となるストリーム(これらの例では)を呼び出すだけであるためです。 BinaryReaderBinaryWriterusing()IDisposableDispose()Dispose()MemoryStream

すべてのBinaryReader/ BinaryWriterareは、基になるストリームのRead()/Write()ラッパーのセットであるため、とにかくなぜそれらが存在するのかわかりませIDisposableん。The Right Thingを実行Dispose()してすべてIDisposableのを呼び出しようとすると、混乱します。突然、ストリームが破棄されます。

于 2012-12-20T00:31:59.590 に答える
3

バイナリファイルから任意に構造化されたデータ(a)を読み取るstructには、最初に次のものが必要です。

public static T ToStructure<T>(byte[] data)
{
    unsafe
    {
        fixed (byte* p = &data[0])
        {
            return (T)Marshal.PtrToStructure(new IntPtr(p), typeof(T));
        }
    };
}

その後、次のことができます。

public static T Read<T>(BinaryReader reader) where T: new()
{
    T instance = new T();
    return ToStructure<T>(reader.ReadBytes(Marshal.SizeOf(instance)));
}

struct書き込むには、オブジェクトをバイト配列に変換します。

public static byte[] ToByteArray(object obj)
{
    int len = Marshal.SizeOf(obj);
    byte[] arr = new byte[len];
    IntPtr ptr = Marshal.AllocHGlobal(len);
    Marshal.StructureToPtr(obj, ptr, true);
    Marshal.Copy(ptr, arr, 0, len);
    Marshal.FreeHGlobal(ptr);
    return arr;
}

...そして、結果のバイト配列を。を使用してファイルに書き込むだけですBinaryWriter

于 2012-12-20T00:40:22.727 に答える
0

これは、ファイルとの間でバイナリ形式のデータを読み書きする方法を示す簡単な例です。

using System;
using System.IO;
namespace myFileRead
{
    class Program
     {
       static void Main(string[] args)
       {
           // Let's create new data file.
           string myFileName = @"C:\Integers.dat";
            //check if already exists
            if (File.Exists(myFileName))
               {
                Console.WriteLine(myFileName + " already exists in the selected directory.");

                return;
            }

            FileStream fs = new FileStream(myFileName, FileMode.CreateNew);

            // Instantialte a Binary writer to write data

            BinaryWriter bw = new BinaryWriter(fs);

            // write some data with bw

            for (int i = 0; i < 100; i++)

            {
                    bw.Write((int)i);
            }

            bw.Close();
            fs.Close();

            // Instantiate a reader to read content from file
            fs = new FileStream(myFileName, FileMode.Open, FileAccess.Read);

            BinaryReader br = new BinaryReader(fs);

            // Read data from the file

            for (int i = 0; i < 100; i++)
            {
                //read data as Int32 
                Console.WriteLine(br.ReadInt32());
            }
            //close the file 
            br.Close();
            fs.Close();           
       }

    }

}
于 2012-12-20T00:45:39.637 に答える