【问题标题】:Is it possible to write a large array of struct directly to a binary file in c#?是否可以在 c# 中将大量结构直接写入二进制文件?
【发布时间】:2021-04-21 09:34:39
【问题描述】:

我知道在 SO 上有很多类似的问题。但他们都没有我想要的答案。

我需要将一个非常大的数组(大约 1 GiB 的存储空间)写入一个二进制文件。它由非常简单的结构组成(只有 4 个只读字节成员的结构)。

我能否将该数组一次性写入二进制文件/流而不将整个数组复制到字节数组中?我绑定到 .NET Standard 2.0,所以没有 MemoryMarshal 的帮助。

干杯, 乔治

【问题讨论】:

  • 什么是“将结构数组写入二进制文件”?序列化?记录/转储(你有想要的格式)?该文件将如何使用?
  • 序列化。我想将整个数组尽可能高效地写入二进制文件,例如BinaryWriter。
  • 也许你只是在内存中使用二进制数组,而你在运行时通过指针获取结构?
  • 只需使用第一个结构的数组创建第二个结构。
  • 使用缓冲区分块写入数据。缓冲区不需要保存所有数据(例如,仅 1 Mb)。缓冲区太小可能会影响性能。

标签: c# arrays memory-management marshalling binaryfiles


【解决方案1】:

这对你有帮助吗?指针复制

public static byte[] GetBytes<T>(T[] structAry) where T : struct
    {
        int len = (int)structAry.Length;
        int size = Marshal.SizeOf(default(T));
        byte[] arr = new byte[size * len];

        IntPtr ptr = Marshal.AllocHGlobal(size);
        try
        {
            for (int i = 0; i < len; ++i)
            {
                Marshal.StructureToPtr(structAry[i], ptr, true);
                Marshal.Copy(ptr, arr, i * size, size);
            }
        }
        catch (Exception e)
        {
            throw e;
        }
        finally
        {
            Marshal.FreeHGlobal(ptr);
        }
        return arr;
    }

【讨论】:

  • 这会将整个内容复制到一个字节数组中,内存中有两次 1GiB。
【解决方案2】:

这取决于您的情况,我将概述一些情况,以便您选择最适合您的情况。

您的数组已经在内存中

您不需要将它复制到另一个数组中,您可以将其写出来。

您有一个文件,其中包含要保存到另一个文件中的内容

您可以使用 [File.Copy][1] 来复制文件。

不能直接复制数据

如果您的数据要从远程源中提取,或者您的数据由于某种原因需要在保存之前进行解析/修改,那么您需要将其加载到内存中,这是没有办法的。但是,您可以使用以下算法加载较小的数据包,而不是一次加载整个数据包

while (packet <- packets.Next) do
    initialize(packet)
    save(packet)
    finalize(packet)
while end

在此处查看更多信息:https://social.msdn.microsoft.com/Forums/vstudio/en-US/54eb346f-f979-49fb-aa2d-44dddad066bd/how-to-read-file-in-chunks-with-for-loop?forum=netfxbcl [1]:https://docs.microsoft.com/en-us/dotnet/api/system.io.file.copy?view=net-5.0

【讨论】:

  • 它已经在内存中了。如何写出来?
【解决方案3】:

我不知道有一种方法可以在不复制数据的情况下将其与File.Write... 一起使用。

我建议分块写:

  1. 将零件复制到缓冲区
  2. 将缓冲区写入文件
  3. 复制下一个块
  4. 将缓冲区写入文件
  5. 重复直到完成整个对象。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-04-27
    • 1970-01-01
    • 1970-01-01
    • 2018-03-20
    • 1970-01-01
    • 1970-01-01
    • 2012-05-16
    • 1970-01-01
    相关资源
    最近更新 更多