0

I'm using csvHelper for reading txt file where columns can have names like this "column1 ".

Of course I don't want to put such ugly string in my ColumnAttribute

[ColumnInfo(typeof(string), "column1")
public string Column1{get;set;}

That is why, before

var reader = new CsvReader(path);
var result = reader.GetRecords<MyObject>();

I want to pre process column names of the file before read it.

So, I've made preprocessor

    public void TrimmColumns(ref StreamReader reader)
    {
        var columns = reader.ReadLine();
        if (columns != null)
        {
            columns = string.Join(";", columns.Split(';').Select(str => str.Trim()).ToArray());
            var res = columns + reader.ReadToEnd();
            var stream = new MemoryStream();
            var streamWriter = new StreamWriter(stream);
            streamWriter.Write(res);
            streamWriter.Flush();
            stream.Position = 0;
            reader = new StreamReader(stream);
        }
        else
        {
            throw new ArgumentException("Host file is empty");
        }


    }

And now I stuck. I can create stream reader from the string and return it but for me it looks not best decision. Can anyone with real experience explain how to make it not only work but also satisfy normal coding style?

[Updated] that is how I'm doing now, but it isn't looks nice at all... [Updated 2] I just realized that it is also bad, coz I'm closing one stream and create other inside this function.

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129

1 Answers1

0

Okay, I came up with this decision, but if someone has better please share, coz it is really important to improve!

using System;
using System.IO;
using System.Linq;

using OtexReportingRef.OtexReader.Interfaces;

public class CsvFileColumnTrimmer:ICsvFileColumnTrimmer
{
    public void TrimmColumns(ref StreamReader reader)
    {
        var columns = reader.ReadLine();
        if (columns != null)
        {
            columns = string.Join(";", columns.Split(';').Select(str => str.Trim()).ToArray());
            var res = columns + reader.ReadToEnd();
            var stream = WriteStringToStream(res);
            reader = new StreamReader(stream);
        }
        else
        {
            throw new ArgumentException("Host file is empty");
        }


    }

    public StreamReader TrimmColumns(StreamReader reader)
    {
        using (reader)
        {
            var columns = reader.ReadLine();
            if (columns != null)
            {
                columns = string.Join(";", columns.Split(';').Select(str => str.Trim()).ToArray());
                var res = columns + reader.ReadToEnd();
                var stream = WriteStringToStream(res);
                return new StreamReader(stream);
            }
            else
            {
                throw new ArgumentException("Host file is empty");
            }
        }



    }

    private static MemoryStream WriteStringToStream(string res)
    {
        var stream = new MemoryStream();
        var streamWriter = new StreamWriter(stream);
        streamWriter.Write(res);
        streamWriter.Flush();
        stream.Position = 0;
        return stream;
    }
}

And tests Are:

using System.IO;

using NUnit.Framework;

using OtexReportingRef.OtexReader.Implementation;

[TestFixture]
public class CsvFileColumnTrimmerTest
{
    private const string Columns =
        "col1;col2        ;col3      ;";
    [Test]
    public void TrimColumns_Test()
    {
        var stream = WriteStringToStream(Columns);
        var streamReader = new StreamReader(stream);
        var trimmer = new CsvFileColumnTrimmer();
        trimmer.TrimmColumns(ref streamReader);
        var res = streamReader.ReadLine();
        Assert.AreEqual("col1;col2;col3;",res);
    } 
    [Test]
    public void TrimColumns_WithUsing_Test()
    {
        var stream = WriteStringToStream(Columns);
        using (var streamReader = new StreamReader(stream))
        {
            var trimmer = new CsvFileColumnTrimmer();
            using (var reader = trimmer.TrimmColumns(streamReader))
            {
                var res = reader.ReadLine();
                Assert.AreEqual("col1;col2;col3;", res);
            }
        }
    }

    [Test]
    public void TrimColumns_WithTryCatch_Test()
    {
        var stream = WriteStringToStream(Columns);
        var streamReader = new StreamReader(stream);
        try
        {
            var trimmer = new CsvFileColumnTrimmer();
            trimmer.TrimmColumns(ref streamReader);
            var res = streamReader.ReadLine();
            Assert.AreEqual("col1;col2;col3;", res);
        }
        finally 
        {
            streamReader.Dispose();
        }
    }


    private static MemoryStream WriteStringToStream(string res)
    {
        var stream = new MemoryStream();
        var streamWriter = new StreamWriter(stream);
        streamWriter.Write(res);
        streamWriter.Flush();
        stream.Position = 0;
        return stream;
    }
}