我从内存中的 zip 文件中读取 CSV 文件的内容(要求不写入磁盘)到 MemoryStream 中。并使用以下代码获取人类可读的字符串
string result = Encoding.ASCII.GetString(memoryStream.ToArray());
但是,我们希望结果是一个 string[] 来映射 CSV 文件中的每一行。
有没有办法自动处理这个?
谢谢
我从内存中的 zip 文件中读取 CSV 文件的内容(要求不写入磁盘)到 MemoryStream 中。并使用以下代码获取人类可读的字符串
string result = Encoding.ASCII.GetString(memoryStream.ToArray());
但是,我们希望结果是一个 string[] 来映射 CSV 文件中的每一行。
有没有办法自动处理这个?
谢谢
首先,不需要调用ToArray
内存流。只需使用StreamReader
, 并ReadLine()
重复调用:
memoryStream.Position = 0; // Rewind!
List<string> rows = new List<string>();
// Are you *sure* you want ASCII?
using (var reader = new StreamReader(memoryStream, Encoding.ASCII))
{
string line;
while ((line = reader.ReadLine()) != null)
{
rows.Add(line);
}
}
您可以使用Split
方法通过换行符拆分字符串:
string[] result = Encoding.
ASCII.
GetString(memoryStream.ToArray()).
Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
根据您的 CSV 文件的内容,这可能比您认为的要困难得多。
假设这是你的 csv:
id, data1, data2
1, some data, more data
2, “这个元素
在字段中间有一个新行”,如果你逐行阅读,这可能会产生问题
如果你只是用 reader.ReadLine() 逐行阅读,如果你碰巧在中间有新行的引用字段(这在 CSV 中通常是允许的),你将不会得到你想要的。你需要更多这样的东西
List<String> results = new List<string>();
StringBuilder nextRow = new StringBuilder();
bool inQuote = false;
char nextChar;
while(reader.ReadChar(out nextChar)){ // pretend ReadChar reads a char into nextChar and returns false when it hits EOF
if(nextChar == '"'){
inQuote = !inQuote;
} else if(!inQuote && nextChar == '\n'){
results.Add(nextRow.ToString());
nextRow.Length = 0;
} else{ nextString.Append(nextChar); }
}
请注意,这处理双引号。缺少引号将是一个问题,但它们始终位于 .csv 文件中。