简体   繁体   中英

Reading from a file mixed with text and binary data in c#

  • I'm trying to read data from a file output by a label printer program for a test station.
  • Most of the data is readable text that can be read using StreamReader and taking it a line at a time.
  • Some of the lines need to have dynamic content replacing parts of the line, and I've got that working.
  • The problem is that one of the printer commands is outputting a logo and the line starts with normal text and finishes with binary data.
    • If I try reading the line and processing the whole thing as a string, it messes up the logo. I thought I had a workaround by using the Read() method on that line and converting the result a character at a time from Int32 to byte , but it ends up overflowing when the Read() method produces a value greater than 255 , which doesn't do well with Convert.ToByte() .
    • I wish that StreamReader had a GetByte method like BinaryReader , but it doesn't.
  • Just looking for suggestions as I stumble toward a solution.
  • Use BinaryReader instead of StreamReader .

    • You can use BinaryReader to read text just like StreamReader too - the only catch is that you'll need to bring your own ReadLine as an extension-method, but here's an example below.
  • It is technically possible to use both StreamReader and BinaryReader on the same Stream concurrently - but you need to be familiar with the internals of both and how their read-buffer and stream-reading behaviour works. So I don't recommend using this approach at all.

  • Use the BinaryReaderExtensions below to have ReadLine , and switch to binary methods when you get to the binary part of the file:

using System;
using System.IO;
using System.Text;

public static class BinaryReaderExtensions
{
    public static String ReadLine( this BinaryReader reader )
    {
        if( reader is null ) throw new ArgumentNullException(nameof(reader));
        if( reader.IsEndOfStream() ) return null;

        StringBuilder sb = new StringBuilder();

        while( ReadChar( reader, out Char c ) )
        {
            if( c == '\r' || c == '\n' )
            {
                return sb.ToString();
            }
            else
            {
                sb.Append( c );
            }
        }

        if( sb.Length > 0 ) return sb.ToString();

        return null;

        char character;
    }

    private static Boolean ReadChar( BinaryReader reader, out Char c )
    {
        if( reader.IsEndOfStream() ) return false;
        c = reader.ReadChar();
        return true;
    }

    public static Boolean IsEndOfStream(this BinaryReader reader)
    {
        return reader.BaseStream.Position == reader.BaseStream.Length; 
    }
}

Example:

using( FileStream fs = new FileStream( "file.dat", FileMode.Read, etc ) )
using( BinaryReader rdr = new BinaryReader( fs, Encoding.UTF8 ) )
{
    // I assume the first 5 lines are text:
    List<String> linesOfText = new List<String>();
    for( Int32 i = 0; i < 5; i++ )
    {
        String line = rdr.ReadLine();
        if( line is null ) throw new InvalidOperationException( "Encountered premature EOF in text section." );
        linesOfText.Add( line );
    }

    // And after the 5th line it's a 512 byte blob of binary data (for example):
    Byte[] buffer = new Byte[ 512 ];
    Int32 bytesRead = rdr.Read( buffer, index: 0, count: 512 );
    if( bytesRead != buffer.Length ) throw new InvalidOperationException( "Encountered premature EOF (in binary section)." );
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM