The Artima Developer Community
Sponsored Link

.NET Buzz Forum
Unsafe and reading from files

0 replies on 1 page.

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 0 replies on 1 page
Eric Gunnerson

Posts: 1006
Nickname: ericgu
Registered: Aug, 2003

Eric Gunnerson is a program manager on the Visual C# team
Unsafe and reading from files Posted: Apr 13, 2004 11:05 AM
Reply to this message Reply

This post originated from an RSS feed registered with .NET Buzz by Eric Gunnerson.
Original Post: Unsafe and reading from files
Feed Title: Eric Gunnerson's C# Compendium
Feed URL: /msdnerror.htm?aspxerrorpath=/ericgu/Rss.aspx
Feed Description: Eric comments on C#, programming and dotnet in general, and the aerodynamic characteristics of the red-nosed flying squirrel of the Lesser Antilles
Latest .NET Buzz Posts
Latest .NET Buzz Posts by Eric Gunnerson
Latest Posts From Eric Gunnerson's C# Compendium

Advertisement

Einar wrote (long ago),

In the article you wrote on unsafe image processing, you announced a follow-up that would "cover some more unsafe scenarios, including dealing with existing structures on disk". But then I guess something came up, and that article never surfaced (to my knowledge and loss, respectively). How about a blog post instead?

Einar's first mistake was believing anything that I write about future columns. My track record at getting back to topics is pretty poor - so bad, in fact, that I've tried to stop making promises about what I'll write about next.

Let's look at some code from a GPS application I've been playing around with for quite some time. This code opens a file and reads a mess of binary structures out of it, and recreates them as real structures.

  public unsafe static GpsDataset Load(string filename)
  {
   GpsDataset dataset = new GpsDataset();

   FileInfo fileInfo = new FileInfo(filename);
   
   int count = (int) (fileInfo.Length / sizeof(GpsPosition));

   using (FileStream fileStream = new FileStream(filename, FileMode.Open))
   {
    BinaryReader binaryReader = new BinaryReader(fileStream);

    for (int i = 0; i < count; i++)
    {
     byte[] buffer = binaryReader.ReadBytes(sizeof(GpsPosition));
     dataset.positions.Add(new GpsPosition(buffer));
    }
   }
   return dataset;
  }

It starts by getting the size of the file, and then computing how many items are in the file (I could have just read till end-of-file, but that seemed less elegant. Know the size ahead of time allows me to pre-allocate my positions ArrayList (not that I did that, but it *allows me to* do that...)).

Then it's off to reading the chunks out, into a byte[] buffer. It would be considerably more efficient if I stuck with a stream and read the bytes into the same buffer over and over rather than re-allocated a whole buffer, but a) I haven't gotten around to optimizing this yet b) I wrote it to be flexible, when I didn't know what I'd be storing c) The UI operations are far slower than what I'm doing here and d) did I say it wasn't yet optimized.

Anyway, this buffer gets passed off to the constructor for GpsPosition, which looks like this:

 [StructLayout(LayoutKind.Sequential, Pack=1)]
 public unsafe struct GpsPosition
 {
  public float AltitudeAboveWGS84;
  public float EstimatedPositionError;

  public float EstimatedHorizontalError;
  public float EstimatedVeriticalError;
  public PositionFix PositionFix;
  public double TimeOfWeek;

  public double Latitude;
  public double Longitude;
  public float VelocityEast;
  public float VelocityNorth;
  public float VelocityUp;
  public float AltitudeAboveMSL;
  public short LeapSeconds;
  public int WeekNumberDays;

  public GpsPosition(byte[] data)
  {
   fixed (byte* pData = data)
   {
    this = *(GpsPosition*) pData;
   }
  }
}

The constructor simply fixes the data buffer so it's okay to get a pointer to it, then uses a cast and pointer dereference to copy the contents of the buffer over the struct.

Note the StructLayout attribute at the beginning of the routine. In it, I set the packing to 1. By default, the runtime will give you nicely aligned structures that are more efficient to access by padding. In this case, I need the structure to match the definition from the Garmin API spec *exactly*, so I have to set packing to 1.

That's about all there is to it. Define the structure, get a byte[] of the right size, and then copy the data over in a fixed block.

 

Read: Unsafe and reading from files

Topic: DotNet vs. Smalltalk Previous Topic   Next Topic Topic: VS 2005 has a blog?

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use