【问题标题】:What is the efficient way to write stream of bytes into a file in c#?在c#中将字节流写入文件的有效方法是什么?
【发布时间】:2015-10-23 13:13:15
【问题描述】:

我有 5GB 左右的字节形式的大数据。

我需要将此数据存储在文件ServerData.xml 中。这个数据应该先转换成字符串,然后保存到文件中,这样我们就可以对文件进行操作了。

我使用下面的代码将字节流转换为字符串,然后将其保存在文件中。

private const string fileName = "ServerData.xml";

public void ProcessBuffer(byte[] receiveBuffer, int bytes)
{
    if (!File.Exists(fileName))
    {
        using (File.Create(fileName)) { };
    }

    TextWriter tw = new StreamWriter(fileName, true);
    tw.Write(Encoding.UTF8.GetString(receiveBuffer).TrimEnd((Char)0));
    tw.Close();
}

这是正确的方法吗?

或者请提出更好的方法,以便将来不会出现任何内存问题?

【问题讨论】:

  • 对我来说,创建一个 5GB 的字符串听起来是错误的。
  • 我明白,但我们别无选择。我们从第三方获取这些数据,所以我们必须处理它:(
  • 根据您的prior question,您不应该将字节转换为string 只是为了保存它。正如阿列克谢列文科夫所说:What the point of converting byte array to string (2x memory size) when you can just read it directly as stream?。你似乎忽略了别人的好建议。
  • 为什么要转换成字符串。只需在文件中写入字节。它速度快,占用空间少,
  • 如果我将字节保存到文件中,那么我该如何读取它?它包含 xml 数据。请建议

标签: c#


【解决方案1】:

只有当ProcessBuffer 始终使用在代码点边界上被破坏的 UTF-8 编码文本调用时,您问题中的代码才能工作。这对我来说似乎不太可能,所以我希望您在解码为文本时遇到错误。

然而,解码成文本然后写入,是相当没有意义的,而且确实适得其反。这些字节已经是 UTF-8 编码的。当它们从套接字到达时,将它们直接写入文件。不要对它们进行任何处理。当您使用XmlReader 读取 XML 时,解析器将从文档的 XML 声明中读取编码为 UTF-8,并能够解码文档的其余部分。我假设文档的 XML 声明指定了 UTF-8,但这似乎很有可能。你应该检查一下。

您应该摆脱对您编写字节没有用处的文本编写器。将字节直接写入文件流。并尽量避免重复打开和关闭文件。这是非常低效的。仅打开和关闭文件一次。

【讨论】:

  • 您的意思是说我可以使用tw.Write(receiveBuffer); 直接将字节写入文件?或者是其他东西 ?当我使用XmlReader 时它会自动正确读取?
  • 是的,完全正确,因为字节已经是编码为 UTF-8 的文本,我假设它与文档的 XML 声明相匹配。请注意,这里的其他人都和我说的完全一样。
  • 使用tw.Write(receiveBuffer); 我明白了System.Byte[]System.Byte[]System.Byte[]System.Byte[]System.Byte[]System.Byte[]System.Byte[]System.Byte[]System.Byte[]System.Byte[]System.Byte[]
  • 当然可以。您正在使用文本写入。只需打开一个文件流,寻找到最后,然后写入字节。也不要忽略字节数参数。请注意,继续打开和关闭文件效率低下。只做一次。
  • using (var stream = new FileStream(fileName, FileMode.Append)) { stream.Write(receiveBuffer, 0, receiveBuffer.Length); }
【解决方案2】:

您可以使用FileStream 将这些字节简单地写入文件:

public void ProcessBuffer(byte[] receivedBuffer, int bytes)
{
    using (var fileStream = new FileStream(fileName, FileMode.Create)) // overwrites file
    {
        fileStream.Write(receivedBuffer, 0, bytes);
    }
}

更新:如果您没有足够的资源,您将无法处理如此大的 XML 文档。我建议重新格式化这个文件。例如,我会解析这个 XML 并将数据插入 SQL 数据库。然后,您可以轻松地处理如此大量的数据。

【讨论】:

  • 他想将字节转换为字符串,然后将字符串写入文件,
  • @FaisalHafeez 那么,分配 10 GB 内存有什么意义呢?无需转换为字符串即可将数据写入文件。
  • @FaisalHafeez OP 想要的不是高效
  • @YeldarKurmangaliyev:如果我将字节保存到文件中,那么我该如何读取它?它包含 xml 数据。我必须一次又一次地使用这个 xml。请建议
  • @Gaurav123 我不确定您是否能够使用XmlDocument 这样的大 XML 文档。当然,如果您没有足够的资源来处理它:) 您需要重新格式化这个 XML。例如,我会解析这个 XML 并将数据插入 SQL 数据库。然后,您可以轻松地处理如此大量的数据。
【解决方案3】:

为什么要转成字符串?

using System.IO;

public static void WriteBytes(byte[] bytes, string filename)
{
    using (FileStream fs = new FileStream(filename, FileMode.OpenOrCreate))
    using (BinaryWriter writer = new BinaryWriter(fs, Encoding.UTF8))
    {
        writer.Write(bytes);
    }
}

【讨论】:

  • 如果我将字节保存到文件中,那么我该如何读取它?它包含 xml 数据。我不得不一次又一次地使用这个xml
  • 您会像往常一样阅读它。字节不会写成字符串。
【解决方案4】:

我希望将所有字节都写入文件。并且在读取的时候先转成字符串,然后再用XDocument、XElement等转成XML。通过在文件中写入字节可以节省空间,而且效率很高,

我更喜欢 File.WriteAllBytes 方法,而不是使用 FileStream。

private const string fileName = "ServerData.xml";
public void ProcessBuffer(byte[] receiveBuffer, int bytes)
{
    File.WriteAllBytes(filename, bytes);


    // And when reading
    var bytes = File.ReadAllBytes(filename);
    var binaryReader = new BinaryReader(new MemoryStream(bytes));
    // Parse strings and make xml,
    binaryReader.ReadString();

}

【讨论】:

  • 你为什么要将 5GB 读入 byte[] 以便将其包装在 MemoryStream 中?当您将其读入string 时,这至少会使内存使用量翻倍。 OP 最终想要一个可以说用XmlReaderXDocument 替换的XML 更好。 string 不需要解析。
  • @Faisal : WriteAllBytes 将创建一个不正确的新文件。我需要将数据附加到同一个文件中
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-07-04
  • 1970-01-01
  • 2014-01-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-10
相关资源
最近更新 更多