来自 MemoryStream 的 StreamReader

StreamReader from MemoryStream

我正在从 base64 字符串解码 csv 文件:

byte[] input;
using (var ms = new MemoryStream())
using (var cs = new CryptoStream(ms, new FromBase64Transform(), CryptoStreamMode.Write))
using (var tr = new StreamWriter(cs))
{
    tr.Write(data);
    tr.Flush();
    input = ms.ToArray();
}

如何简单地通过字符串读取解码后的文件? 例如,类似于我们如何从 HttpWebResponse 流中读取文件的方式:

using (StreamReader input = new StreamReader(response.GetResponseStream(), Encoding.GetEncoding(1251), true))
{
    while (!input.EndOfStream)
    {
         string row = input.ReadLine();
    }
}

不用转数组,直接把内存流位置重置为0然后把内存流传给reader读到结束

using (var ms = new MemoryStream()) {
    using (var cs = new CryptoStream(ms, new FromBase64Transform(), CryptoStreamMode.Write)) {
        using (var tr = new StreamWriter(cs)) {
            tr.Write(data);
            tr.Flush();
            ms.Position = 0;
            using (var reader = new StreamReader(ms, Encoding.GetEncoding(1251), true)) {
                string csv = reader.ReadToEnd();
                //OR
                //while (!reader.EndOfStream) {
                //    var line = reader.ReadLine();
                //}
            }
        }
    }
}

还有一个选择

byte[] input;
using (var ms = new MemoryStream()) {
    using (var cs = new CryptoStream(ms, new FromBase64Transform(), CryptoStreamMode.Write)) {
        using (var tr = new StreamWriter(cs)) {
            tr.Write(data);
            tr.Flush();
            input = ms.ToArray();
        }
    }
}
using (var ms = new MemoryStream(input)) {
    using (var reader = new StreamReader(ms, Encoding.GetEncoding(1251), true)) {
        string csv = reader.ReadToEnd();
        //OR
        //while (!reader.EndOfStream) {
        //    var line = reader.ReadLine();
        //}
    }
}

您可以从数组开始初始化 MemoryStream;那么您不必向流中写入任何内容。由于根据定义,Base64 是纯 ascii 文本,您只需使用 ASCII 编码将输入字符串转换为字节。

不过,如果您要解析 CSV,则有比逐行读取文本更好的输出选项。从技术上讲,CSV 格式可以包含换行符 inside 字段,几乎所有从电子表格文件写入 CSV 的东西(如 MS Excel)都支持此功能。要支持这一点,line-by-line-reading 方法太简单了。 .Net 框架包含一个本机 CSV reader,虽然在 Microsoft.VisualBasic classes 中隐藏得很好。但是,由于 .Net 是一个框架,因此没有什么可以阻止您添加引用并在 C# 中使用它。 class 是 TextFieldParser,来自 Microsoft.VisualBasic.FileIO

public static List<String[]> ParseBase64Csv(String data, Encoding encoding, Char separator, Boolean ignoreEmptyLines)
{
    List<String[]> splitLines = new List<String[]>();
    using (MemoryStream ms = new MemoryStream(Encoding.ASCII.GetBytes(data)))
    using (FromBase64Transform tr = new FromBase64Transform(FromBase64TransformMode.IgnoreWhiteSpaces))
    using (CryptoStream cs = new CryptoStream(ms, tr, CryptoStreamMode.Read))
    using (StreamReader sr = new StreamReader(cs, encoding))
    using (TextFieldParser tfp = new TextFieldParser(sr))
    {
        tfp.TextFieldType = FieldType.Delimited;
        tfp.Delimiters = new String[] { separator.ToString() };
        while (true)
        {
            try
            {
                String[] curLine = tfp.ReadFields();
                if (curLine == null)
                    break;
                if (ignoreEmptyLines && (curLine.Length == 0 || curLine.All(x => String.IsNullOrEmpty(x) || String.IsNullOrEmpty(x.Trim()))))
                    continue;
                splitLines.Add(curLine);
            }
            catch (MalformedLineException mfle)
            {
                // do something with errors here.
            }
        }
    }
    return splitLines;
}