C# StreamRead 在 CSV 文件中包含一个包含“,”的字段
C# StreamRead in CSV file with a field containing ","
我在封闭的环境中工作,我无法安装额外的软件包并且使用 .Net 框架的能力有限 类。另外,我无法控制我收到的 CSV 文件格式。
我收到一个 CSV 文件,必须将其拉入我们的业务系统并更新数据库。
我可以通过以下代码将文件拉入 DataTable ...
CSV File Ex:
Order# Qty Description ...
12345 3 desc1, desc2, desc3, etc..
while (!sr.EndOfStream)
{
string[] rows = sr.ReadLine().Split(',');
DataRow dr = dt.NewRow();
for (int i = 0; i < rows.Length; i++)
{
dr[i] = rows[i];
}
dt.Rows.Add(dr);
}
但是,问题在于CSV文件中的一个字段是包含多个“,”字符的描述。执行上述操作将描述值中的每个逗号分隔词集加载到行数组中它自己的索引中。
目前 csv 文件中应该总共有 10 列,但是对于描述字段问题,列数会根据描述字段中的 length/number 逗号而有所不同...10, 15, 22 列等
我无法控制 CSV 文件在发送前的格式。有什么办法可以解决这个问题。即使在创建 DataTable 时跳过此字段也可以满足我的目的。
谢谢
您的 CSV 文件似乎有固定大小的列,并用空格填充。所以我想你最好为每一列读取固定数量的字符和 trim 尾随空格,而不是用逗号分隔。
试试 this class。
它按照您的需要处理逗号。
您可以使用 textqualifier 将每个字段括起来,这样逗号或分号就不会被视为分隔符。以下方法应该可以解决问题。
安装包 CsvHelper
public static DataTable ReadCSVToDataTable(string path)
{
CsvHelper.Configuration.CsvConfiguration config = new CsvHelper.Configuration.CsvConfiguration();
config.Delimiter = delimeter;
config.Encoding = new UTF8Encoding(false);
if (string.IsNullOrEmpty(textQualifier))
{
config.QuoteAllFields = false;
}
else
{
char qualifier = textQualifier.ToCharArray()[0];
config.Quote = qualifier;
config.QuoteAllFields = true;
}
DataTable dt = new DataTable();
using (var sr = new StreamReader(path))
{
using (var reader = new CsvReader(sr, config))
{
int j = 0;
while (reader.Read())
{
if (j == 0)
{
if (config.HasHeaderRecord)
{
foreach (string header in reader.FieldHeaders)
dt.Columns.Add(header);
}
else
{
for (int i = 0; i < reader.CurrentRecord.Length; i++)
dt.Columns.Add();
}
j++;
}
AddRow(dt, reader);
}
}
}
return dt;
}
Fstagger,假设您只有一列带有内部逗号并且 CSV 格式正确(特别是如果描述字段以“,”开头并以“,结尾),这应该对您有用。您需要替换我的示例INDEX_OF_DESCRIPTION 与实际值。
int iDescStart = 0;
int iDescEnd = 0;
string zLine = "";
const int INDEX_OF_DESCRIPTION = 3;
const char SEPARATOR = '\u001F'; //ASCII Unit Separator, decimal 31
while(!sr.EndOfStream){
zLine = sr.ReadLine();
iDescStart = zLine.IndexOf(",\"");
iDescEnd = zLine.IndexOf("\",");
zLine = zLine.Substring(0, iDescStart)
+ ","
+ zLine.Substring(iDescStart + 2, iDescEnd - iDescStart - 2).Replace(',', SEPARATOR)
+ ","
+ zLine.Substring(iDescEnd + 2);
string[] zaFields = zLine.Split(',');
zaFields[INDEX_OF_DESCRIPTION] = zaFields[INDEX_OF_DESCRIPTION].Replace(SEPARATOR, ',');
datarow dr = dt.NewRow();
for (int i = 0; i < zaFields.Length; i++){
dr[i] = zaFields[i];
}
dt.Rows.Add(dr);
}
让我知道这是否适合您:)
我的解决方案最终有效
while (!sr.EndOfStream)
{
string[] rows = sr.ReadLine().Split(',');
var fullrow = String.Empty;
foreach (var entry in rows)
{
fullrow += entry.ToString() + ",";
}
var startQuote = fullrow.IndexOf("\"");
var endQuote = fullrow.IndexOf("\"", startQuote + 1); //LastIndexOf("\"");
if (startQuote > -1 && endQuote > -1)
{
var substring = fullrow.Substring(startQuote, Math.Abs(startQuote - endQuote));
substring = substring.Replace(',', ' ');
fullrow = fullrow.Remove(startQuote, Math.Abs(startQuote - endQuote)).Insert(startQuote, substring);
}
rows = fullrow.Split(',');
DataRow dr = dt.NewRow();
for (int i = 0; i < rows.Length; i++)
{
dr[i] = rows[i];
}
dt.Rows.Add(dr);
}
感谢@Michael Gorsich 提供备用代码!
我在封闭的环境中工作,我无法安装额外的软件包并且使用 .Net 框架的能力有限 类。另外,我无法控制我收到的 CSV 文件格式。
我收到一个 CSV 文件,必须将其拉入我们的业务系统并更新数据库。
我可以通过以下代码将文件拉入 DataTable ...
CSV File Ex:
Order# Qty Description ...
12345 3 desc1, desc2, desc3, etc..
while (!sr.EndOfStream)
{
string[] rows = sr.ReadLine().Split(',');
DataRow dr = dt.NewRow();
for (int i = 0; i < rows.Length; i++)
{
dr[i] = rows[i];
}
dt.Rows.Add(dr);
}
但是,问题在于CSV文件中的一个字段是包含多个“,”字符的描述。执行上述操作将描述值中的每个逗号分隔词集加载到行数组中它自己的索引中。
目前 csv 文件中应该总共有 10 列,但是对于描述字段问题,列数会根据描述字段中的 length/number 逗号而有所不同...10, 15, 22 列等
我无法控制 CSV 文件在发送前的格式。有什么办法可以解决这个问题。即使在创建 DataTable 时跳过此字段也可以满足我的目的。
谢谢
您的 CSV 文件似乎有固定大小的列,并用空格填充。所以我想你最好为每一列读取固定数量的字符和 trim 尾随空格,而不是用逗号分隔。
试试 this class。
它按照您的需要处理逗号。
您可以使用 textqualifier 将每个字段括起来,这样逗号或分号就不会被视为分隔符。以下方法应该可以解决问题。
安装包 CsvHelper
public static DataTable ReadCSVToDataTable(string path)
{
CsvHelper.Configuration.CsvConfiguration config = new CsvHelper.Configuration.CsvConfiguration();
config.Delimiter = delimeter;
config.Encoding = new UTF8Encoding(false);
if (string.IsNullOrEmpty(textQualifier))
{
config.QuoteAllFields = false;
}
else
{
char qualifier = textQualifier.ToCharArray()[0];
config.Quote = qualifier;
config.QuoteAllFields = true;
}
DataTable dt = new DataTable();
using (var sr = new StreamReader(path))
{
using (var reader = new CsvReader(sr, config))
{
int j = 0;
while (reader.Read())
{
if (j == 0)
{
if (config.HasHeaderRecord)
{
foreach (string header in reader.FieldHeaders)
dt.Columns.Add(header);
}
else
{
for (int i = 0; i < reader.CurrentRecord.Length; i++)
dt.Columns.Add();
}
j++;
}
AddRow(dt, reader);
}
}
}
return dt;
}
Fstagger,假设您只有一列带有内部逗号并且 CSV 格式正确(特别是如果描述字段以“,”开头并以“,结尾),这应该对您有用。您需要替换我的示例INDEX_OF_DESCRIPTION 与实际值。
int iDescStart = 0;
int iDescEnd = 0;
string zLine = "";
const int INDEX_OF_DESCRIPTION = 3;
const char SEPARATOR = '\u001F'; //ASCII Unit Separator, decimal 31
while(!sr.EndOfStream){
zLine = sr.ReadLine();
iDescStart = zLine.IndexOf(",\"");
iDescEnd = zLine.IndexOf("\",");
zLine = zLine.Substring(0, iDescStart)
+ ","
+ zLine.Substring(iDescStart + 2, iDescEnd - iDescStart - 2).Replace(',', SEPARATOR)
+ ","
+ zLine.Substring(iDescEnd + 2);
string[] zaFields = zLine.Split(',');
zaFields[INDEX_OF_DESCRIPTION] = zaFields[INDEX_OF_DESCRIPTION].Replace(SEPARATOR, ',');
datarow dr = dt.NewRow();
for (int i = 0; i < zaFields.Length; i++){
dr[i] = zaFields[i];
}
dt.Rows.Add(dr);
}
让我知道这是否适合您:)
我的解决方案最终有效
while (!sr.EndOfStream)
{
string[] rows = sr.ReadLine().Split(',');
var fullrow = String.Empty;
foreach (var entry in rows)
{
fullrow += entry.ToString() + ",";
}
var startQuote = fullrow.IndexOf("\"");
var endQuote = fullrow.IndexOf("\"", startQuote + 1); //LastIndexOf("\"");
if (startQuote > -1 && endQuote > -1)
{
var substring = fullrow.Substring(startQuote, Math.Abs(startQuote - endQuote));
substring = substring.Replace(',', ' ');
fullrow = fullrow.Remove(startQuote, Math.Abs(startQuote - endQuote)).Insert(startQuote, substring);
}
rows = fullrow.Split(',');
DataRow dr = dt.NewRow();
for (int i = 0; i < rows.Length; i++)
{
dr[i] = rows[i];
}
dt.Rows.Add(dr);
}
感谢@Michael Gorsich 提供备用代码!