C# 来自MemoryStream的StreamReader

C# 来自MemoryStream的StreamReader,c#,stream,.net-4.6,C#,Stream,.net 4.6,我正在从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 = m

我正在从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
stream读取文件的方式:

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

不必费心转换到数组,只需将内存流位置重置为0,然后将内存流传递给读卡器,然后读取到末尾

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格式可以在字段中包含换行符,这是一种几乎所有从电子表格文件(如MS Excel)写入CSV的内容都支持的功能。为了支持这一点,逐行阅读的方法太简单了。尽管.Net framework包含一个本机CSV阅读器,但它在
Microsoft.VisualBasic
类中隐藏得相当好。但是,由于.Net是一个框架,因此没有什么可以阻止您添加引用并在C#中使用它。该类是
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;
}
公共静态列表ParseBase64Csv(字符串数据、编码、字符分隔符、布尔ignoreEmptyLines)
{
列表分割线=新列表();
使用(MemoryStream ms=new MemoryStream(Encoding.ASCII.GetBytes(data)))
使用(FromBase64Transform tr=new FromBase64Transform(FromBase64TransformMode.IgnoreWhiteSpaces))
使用(CryptoStream cs=新的CryptoStream(ms、tr、CryptoStreamMode.Read))
使用(StreamReader sr=新的StreamReader(cs,编码))
使用(TextFieldParser tfp=新的TextFieldParser(sr))
{
tfp.TextFieldType=FieldType.Delimited;
tfp.Delimiters=新字符串[]{separator.ToString()};
while(true)
{
尝试
{
字符串[]curLine=tfp.ReadFields();
if(curLine==null)
打破
if(ignoreEmptyLines&(curLine.Length==0 | | | curLine.All(x=>String.IsNullOrEmpty(x)| | | String.IsNullOrEmpty(x.Trim()))
继续;
拆分线。添加(卷曲线);
}
捕获(格式错误的LineException mfle)
{
//在这里做一些有错误的事情。
}
}
}
返回分割线;
}

@Nkosi将内存流传递给读者的方式正是我所要求的for@Nkosi你的解决方案是可行的,即使不是那么完美。我必须从base64字符串解析csv文件,并将数据写入数据库。从技术上讲,csv格式允许单元格内换行。如果您的输入可能来自转换后的电子表格文件,您可以查看而不是逐行读取。我一直在读取MemoryStream,然后需要从中读取,并且在我的流读取器中不断获取ReadLine()return null。当我看到你在内存流中将位置设置为0时,我会说“你一定是在开玩笑吧”。。。不能相信,它不默认从流读取器中内存流的开头读取。非常感谢你的回答!