【问题标题】:Convert StreamReader to byte[]将 StreamReader 转换为 byte[]
【发布时间】:2011-08-17 13:21:06
【问题描述】:

我得到了StreamReader对象的结果。

我想将结果转换成byte[]

如何将StreamReader转换为byte[]

谢谢

【问题讨论】:

    标签: c# stream


    【解决方案1】:

    您可以使用此代码:不应使用此代码:

    byte[] bytes = streamReader.CurrentEncoding.GetBytes(streamReader.ReadToEnd());
    

    请参阅对此答案的评论以了解原因。我会留下答案,所以人们知道这种方法的问题,因为我直到现在才知道。

    【讨论】:

    • 这是错误的。 (所以停止投票!)这首先将字节转换为文本,然后再转换回字节。除了映射效率低下这一事实之外,它还可能是非同构的(例如,并非每个字节序列在每种编码中都是有效的字符序列)。因此,这可能会破坏字节序列,或导致错误。这不是读取字节的适当方式。
    • (顺便说一句,更新后的答案可以作为仅供参考,因此也无需downvote ...)
    • @KonradRudolph 如果我们用的答案来回答每个问题,那么很快就会变得一团糟,因为每个问题都可能有数千个这样的有效答案。出于这个原因,我认为“不要做这件事”的答案没有任何价值。
    • @julealgon 是的,我现在同意。
    【解决方案2】:

    StreamReader 用于文本,而不是纯字节。不要使用 StreamReader,而是直接来自底层流的read

    【讨论】:

      【解决方案3】:

      只需将您读到的所有内容都放入MemoryStream 并最终获得字节数组。如前所述,您应该从底层流中读取以获取原始字节。

      var bytes = default(byte[]);
      using (var memstream = new MemoryStream())
      {
          var buffer = new byte[512];
          var bytesRead = default(int);
          while ((bytesRead = reader.BaseStream.Read(buffer, 0, buffer.Length)) > 0)
              memstream.Write(buffer, 0, bytesRead);
          bytes = memstream.ToArray();
      }
      

      或者如果您不想管理缓冲区:

      var bytes = default(byte[]);
      using (var memstream = new MemoryStream())
      {
          reader.BaseStream.CopyTo(memstream);
          bytes = memstream.ToArray();
      }
      

      【讨论】:

      • 呃...为什么要绕道使用 MemoryStream?
      • @Daniel:好吧,除非您事先知道流的长度,否则您将不得不将其读入某种可变长度的东西。我猜 MemoryStream 是一种选择。 @Jeff:default() 有什么用?我不认为它使事情更具可读性。
      • @Daniel:我不确定您所说的“绕道”是什么意思,但据我所知,提问者想要创建流的全部内容的字节数组,而不仅仅是一部分。使用MemoryStream 将在我们读取数据时为我们管理大小。
      • @Matti:这只是我学会的一种编码风格,我会尽可能地使用var 关键字(对于大多数局部变量)。我不希望每个人都对此感到满意,但我可以接受。
      • @Daniel:MemoryStream 的效率可能稍高一些,因为它旨在有效地处理字节数组。例如,您可以使用Write 仅添加数组的一部分(与List<T> 上的AddRange 不同),并且它不通过接口访问字节数组,这可能会稍微降低效率。您也可以直接使用GetBuffer() 获取底层数组,而无需创建它的副本。当然,这仅在您拥有大量数据时才重要。
      【解决方案4】:

      您也可以使用 CopyTo:

      var ms = new MemoryStream();
      yourStreamReader.BaseStream.CopyTo(ms); // blocking call till the end of the stream
      ms.GetBuffer().CopyTo(yourArray, ms.Length);
      

      var ms = new MemoryStream();
      var ct = yourStreamReader.BaseStream.CopyToAsync(ms);
      await ct;
      ms.GetBuffer().CopyTo(yourArray, ms.Length);
      

      【讨论】:

        【解决方案5】:

        对于每个说要获取字节的人,将其复制到 MemoryStream 等 - 如果预计内容不会大于计算机的内存应该合理地允许,为什么不直接使用 StreamReader'内置ReadLine()ReadToEnd()?我看到这些甚至没有被提及,他们为你做了一切。

        我有一个用例,我只想存储用户在同步/初始化过程中选择的FileDialogResult 中的 SQLite 文件的路径。然后,我的程序在为正常的应用程序进程运行时需要使用此路径。也许不是捕获/重用信息的理想方式,但它与写入/读取 .ini 文件没有太大区别——我只是不想为一个值设置一个。所以我只是从一个扁平的单行文本文件中读取它。这是我所做的:

        string filePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
        if (!filePath.EndsWith(@"\")) temppath += @"\"; // ensures we have a slash on the end
        filePath = filePath.Replace(@"\\", @"\"); // Visual Studio escapes slashes by putting double-slashes in their results - this ensures we don't have double-slashes
        filePath += "SQLite.txt";
        
        string path = String.Empty;
        FileStream fs = new FileStream(filePath, FileMode.Open);
        StreamReader sr = new StreamReader(fs);
        path = sr.ReadLine();  // can also use sr.ReadToEnd();
        sr.Close();
        fs.Close();
        fs.Flush();
        
        return path;
        

        如果出于某种原因您真的需要 byte[] 而不是 string,使用我的示例,您总是可以这样做:

        byte[] toBytes;
        FileStream fs = new FileStream(filePath, FileMode.Open);
        StreamReader sr = new StreamReader(fs);
        toBytes = Encoding.ASCII.GetBytes(path);
        sr.Close();
        fs.Close();
        fs.Flush();
        
        return toBytes;
        

        (返回toBytes 而不是path。)

        如果您不想要 ASCII,您可以轻松地将其替换为 UTF8Unicode 等。

        【讨论】:

        • 回答与问题无关
        • @MikeKeskinov 真的吗?您甚至完全阅读了我的答案吗?你知道如何阅读代码吗? OP 想要将 Stream 转换为字节。这个答案显示了如何获取一个文件,将其读入 Stream,然后将文本读入path,一个字符串变量(因为当你想从文件中读取文本时为什么需要字节?!)。但我还介绍了如何将该字符串转换为字节(如果确实需要字节)。
        • 原来的问题没有提到阅读text。它可能是正在读取的二进制文件。您提到使用 Encoding.ASCII.GetBytes(...),但快速查看文档显示它提到了 7 位,因此输入很可能会被破坏。类似地,UTF-8 编码对输入进行假设,当输入任意二进制文件时,这些假设也不成立。
        • @xyz 你是对的,但这取决于开发人员知道他们的输入是什么并为其调整编码,首先是给定的。这个问题的 OP 没有提供很多关于从哪里读取数据或其格式的信息,所以为了建立一个答案,我不得不假设它是文本文件中的文本,甚至 (作为奖励!)包括关于获取字节的内容。如果是字节,当然不仅仅是Encoding.ASCII.GetBytes(),还有Encoding.UTF8.GetBytes()Encoding.Unicode.GetBytes() 等。在拼命回答之前使用智能感知。
        • @vapcguy 够公平的。祝你有美好的一天。
        【解决方案6】:
                BlobClient blob = container.GetBlobClient(path);
                //blob.DownloadTo(@"temp\"+ file);
                var response = blob.DownloadContent();
                var stream = response.Value.Content.ToStream();
                using (var sr = new StreamReader(stream))
                {
                    using (MemoryStream ms = new MemoryStream())
                    {
                        sr.BaseStream.CopyTo(ms);
                        return Convert.ToBase64String(ms.ToArray()) ;
                    }
                }
        

        【讨论】:

        • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
        猜你喜欢
        • 2011-06-08
        • 2014-07-21
        • 1970-01-01
        • 2014-05-22
        • 1970-01-01
        • 2020-02-03
        • 2011-10-15
        • 2011-02-15
        • 2011-12-12
        相关资源
        最近更新 更多