HiveBrain v1.2.0
Get Started
← Back to all entries
debugcsharpMinor

Reading fixed-width data fields in .NET

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
readingfieldswidthnetfixeddata

Problem

I'm working on a communications layer for a system that reads data from a TCPIP client that is formatted as fixed-width ASCII (yeah, old school). I was quite surprised that there seemed to be no built in way to do this, and ended up using the following simple StreamReader subclass:

```
///
/// A Stream reader that reads values as fixed width fields from a stream
///
class FixedWidthFieldStreamReader : StreamReader
{
#region Private/Protected fields
private char[] buffer; // Local buffer used to copy data before conversion
#endregion

#region Methods
///
/// Instantiates a new FixedWidthFieldStreamReader for a stream
///
/// Stream to read from
/// Initial size of the buffer used to copy data before formatting
/// Encoding to use when reading from the stream
public FixedWidthFieldStreamReader(Stream stream, int initialBufferSize, Encoding encoding)
: base(stream, encoding)
{
buffer = new char[initialBufferSize];
}

///
/// Checks if the buffer exists and is large enough,
/// and allocates or grows it if necessary.
///
/// The required buffer length
private void EnsureBufferLength(int length)
{
if (null == buffer ||
buffer.Length
/// Reads a number of bytes into the buffer
///
/// The number of bytes to read
/// True if the required number of bytes was read, false otherwise
private bool ReadToBuffer(int length)
{
EnsureBufferLength(length);

// Read from the stream
int read = Read(buffer, 0, length);
return read == length;
}

///
/// Reads a specified number of bytes from the stream and
/// converts and returns the read value.
///
/// Type of the object to read and return
/// Number of bytes in the field to read from the stream.
/// The read object if successful, or the default value for the type otherwise.
public T Read(int length) where T : IConverti

Solution

I don't know if something does that already, but you could mimic StructLayout if you need to read multiple types of 'objects' or need reusability.

Basically just set starting point/offset and length for each property and read them.

public class Item
{
     // 3 chars starting from 0
    [Layout(0, 3)]
    public int Number { get; set; }

     // 15 chars starting from 3
    [Layout(3, 15)]
    public string Text { get; set; } 

    // 5 chars starting from 18
    [Layout(18, 5)]
    public float Number2 { get; set; } 
}

reader.Read()

Code Snippets

public class Item
{
     // 3 chars starting from 0
    [Layout(0, 3)]
    public int Number { get; set; }

     // 15 chars starting from 3
    [Layout(3, 15)]
    public string Text { get; set; } 

    // 5 chars starting from 18
    [Layout(18, 5)]
    public float Number2 { get; set; } 
}

reader.Read<Item>()

Context

StackExchange Code Review Q#27782, answer score: 4

Revisions (0)

No revisions yet.