c# - 用c#方法读取csv文件
问题描述
我的目标是在我的 c# 方法中读取一个 csv 文件。此 csv 文件未定义,它可以有 n 列。始终保持不变的一件事是 csv 文件中只有两行。一个是标题行,另一个是值行。当我的值是字符串值时,我的以下方法可以正常工作,但当我的值之一是这样的 [test,test1,test2] 时会失败。我尝试使用 Csv 助手类,但我做不到。有人可以建议我应该如何处理吗?
元数据是我从 StreamReader 读取的行列表private void AddValuesToTable( DynamicTableEntity tableEntry, List<string> metadata )
{
var headers = metadata[0].Split( "," );
var values = metadata[1].Split( "," );
for( int i = 0; i < headers.Count(); i++ )
{
tableEntry.Properties.Add( headers[i].ToString(), EntityProperty.CreateEntityPropertyFromObject( values[i] ) );
}
}
样本值:
columnA,columnB,columnC
valA,[testa,testb],valc
解决方案
这是我用来解析 CSV 行的代码。
private static string Peek(this string source, int peek) => (source == null || peek < 0) ? null : source.Substring(0, source.Length < peek ? source.Length : peek);
private static (string, string) Pop(this string source, int pop) => (source == null || pop < 0) ? (null, source) : (source.Substring(0, source.Length < pop ? source.Length : pop), source.Length < pop ? String.Empty : source.Substring(pop));
public static string[] ParseCsvLine(this string line)
{
return ParseCsvLineImpl(line).ToArray();
IEnumerable<string> ParseCsvLineImpl(string l)
{
string remainder = line;
string field;
while (remainder.Peek(1) != "")
{
(field, remainder) = ParseField(remainder);
yield return field;
}
}
}
private const string DQ = "\"";
private static (string field, string remainder) ParseField(string line)
{
if (line.Peek(1) == DQ)
{
var (_, split) = line.Pop(1);
return ParseFieldQuoted(split);
}
else
{
var field = "";
var (head, tail) = line.Pop(1);
while (head != "," && head != "")
{
field += head;
(head, tail) = tail.Pop(1);
}
return (field, tail);
}
}
private static (string field, string remainder) ParseFieldQuoted(string line)
{
var field = "";
var head = "";
var tail = line;
while (tail.Peek(1) != "" && (tail.Peek(1) != DQ || tail.Peek(2) == DQ + DQ))
{
if (tail.Peek(2) == DQ + DQ)
{
(head, tail) = tail.Pop(2);
field += DQ;
}
else
{
(head, tail) = tail.Pop(1);
field += head;
}
}
if (tail.Peek(2) == DQ + ",")
{
(head, tail) = tail.Pop(2);
}
else if (tail.Peek(1) == DQ)
{
(head, tail) = tail.Pop(1);
}
return (field, tail);
}
它正确处理带引号的字段。
推荐阅读
- javascript - 使用 window.innerWidth 和 window.innerHeight 使滚动条出现
- python - python3.x 使用 format() 打印列表的每个值
- node.js - 我们如何仅从 js 的新行中删除逗号
- python - PyTorch - 有效地应用注意力
- php - 使用图形 API 进行 Facebook 分页
- java - 如何使内容列表比父屏幕长?
- php - 雄辩的特定 $fillable 用于 Model::create() 和另一个 $fillable 用于 Model->update()
- c++ - 从版本控制签出后,Visual Studio C++ Google Test 无法识别 TEST 宏
- python - Sklearn:将类名传递给 make_scorer
- amazon-web-services - 无法让 LetsEncrypt SSL 证书与 AWS Lightsail 一起使用