我使用csvHelper来读取文本文件,其中列可以有像这样的名称"column1 "。
当然我不想在我的ColumnAttribute
里放这么丑的字符串[ColumnInfo(typeof(string), "column1")
public string Column1{get;set;}
这就是为什么在
之前var reader = new CsvReader(path);
var result = reader.GetRecords<MyObject>();
我想在读取文件之前预处理它的列名。
所以我写了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");
}
}
现在我卡住了。我可以从字符串创建流阅读器并返回它,但对我来说,这看起来不是最好的决定。有经验的人能解释一下如何使它既能工作又能满足正常的编码风格吗?
[更新]这就是我现在做的,但它看起来不太好…[更新2]我刚刚意识到它也很糟糕,因为我正在关闭一个流并在这个函数中创建另一个流。
好吧,我想出了这个决定,但如果有人有更好的请分享,因为这是非常重要的改进!
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;
}
}
和测试是:
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;
}
}