A C# equivalent of C's fread file i/o

前端 未结 2 2054
名媛妹妹
名媛妹妹 2020-11-27 05:59

Can anyone tell me how to get a array of bytes into a structure in a direct fashion in C# .NET version 2? Like the familiar fread as found in C, so far I have n

相关标签:
2条回答
  • 2020-11-27 06:35

    There isn't anything wrong with using the P/Invoke marshaller, it is not unsafe and you don't have to use the unsafe keyword. Getting it wrong will just produce bad data. It can be a lot easier to use than explicitly writing the deserialization code, especially when the file contains strings. You can't use BinaryReader.ReadString(), it assumes that the string was written by BinaryWriter. Make sure however that you declare the structure of the data with a struct declaration, this.GetType() is not likely to work out well.

    Here's a generic class that will make it work for any structure declaration:

      class StructureReader<T> where T : struct {
        private byte[] mBuffer;
        public StructureReader() {
          mBuffer = new byte[Marshal.SizeOf(typeof(T))];
        }
        public T Read(System.IO.FileStream fs) {
          int bytes = fs.Read(mBuffer, 0, mBuffer.Length);
          if (bytes == 0) throw new InvalidOperationException("End-of-file reached");
          if (bytes != mBuffer.Length) throw new ArgumentException("File contains bad data");
          T retval;
          GCHandle hdl = GCHandle.Alloc(mBuffer, GCHandleType.Pinned);
          try {
            retval = (T)Marshal.PtrToStructure(hdl.AddrOfPinnedObject(), typeof(T));
          }
          finally {
            hdl.Free();
          }
          return retval;
        }
    

    A sample declaration for the structure of the data in the file:

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
    struct Sample {
      [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 42)]
      public string someString;
    }
    

    You'll need to tweak the structure declaration and the attributes to get a match with the data in the file. Sample code that reads a file:

      var data = new List<Sample>();
      var reader = new StructureReader<Sample>();
      using (var stream = new FileStream(@"c:\temp\test.bin", FileMode.Open, FileAccess.Read)) {
        while(stream.Position < stream.Length) {
          data.Add(reader.Read(stream));
        }
      }
    
    0 讨论(0)
  • 2020-11-27 06:39

    You probably want to use a BinaryReader which allows you to read in primitive types in binary form.

    Create a MemoryStream from the byte[] and then use the BinaryReader from that. You should be able to read out the structure and fill in your object accordingly.

    0 讨论(0)
提交回复
热议问题