【问题标题】:Fastest Way to Save 3D int Array? (XNA \ C#)保存 3D int 数组的最快方法? (XNA\C#)
【发布时间】:2013-11-17 23:40:11
【问题描述】:

我需要一种快速的方法来尽快将小型 3D 数组保存到文件中。 数组大小为 32x32x4。 我还需要一种快速读取文件的方法。

到目前为止,我已经尝试遍历所有元素:

for (int xx = 0; xx < 32; xx += 1)
{
    for (int yy = 0; yy < 32; yy += 1)
    {
        for (int zz = 0; zz < 4; zz += 1)
        {
            String += FormatInt(array[xx, yy, zz]);
        }
    }
}

将每个整数转成2位数的字符串:(上面的FormatInt()方法)

public string FormatInt(int num)
    {
        string String = "";
        String = Convert.ToString(num);
        int length = String.Length;
        for (int i = 0; i < (2 - length); i += 1)
        {
            String = String.Insert(0, "0");
        }
        return String;
    }

然后将该字符串保存到 .txt 文件中。 然后我加载文件,然后将每个 2 位子字符串转换为整数:

int Pos = 0;
            for (int xx = 0; xx < chunkSize; xx += 1)
            {
                for (int yy = 0; yy < chunkSize; yy += 1)
                {
                    for (int zz = 0; zz < 4; zz += 1)
                    {
                        array[xx, yy, zz] = Convert.ToInt32(String.Substring(Pos * 2, 2));
                        Pos += 1;
                    }
                }
            }

我需要一种更快的方法来保存文件。 (更快的加载也不错,但现在还不算太慢。)

【问题讨论】:

    标签: c# arrays xna 2d


    【解决方案1】:

    我会使用BinaryReaderBinaryWriter。您当前的方法在存储方面效率非常低,并且在使用+= 附加这么多字符串时会出现内存问题(请改用StringBuilder

    保存:

    using (BinaryWriter b = new BinaryWriter(File.Open("file.ext", FileMode.Create)))
    {
        for (int xx = 0; xx < 32; xx += 1)
        {
            for (int yy = 0; yy < 32; yy += 1)
            {
                for (int zz = 0; zz < 4; zz += 1)
                {
                    b.Write(array[xx, yy, zz]);
                }
            }
        }
    }
    

    加载中

    using (BinaryReader b = new BinaryReader(File.Open("file.ext", FileMode.Open)))
    {
        for (int xx = 0; xx < 32; xx += 1)
        {
            for (int yy = 0; yy < 32; yy += 1)
            {
                for (int zz = 0; zz < 4; zz += 1)
                {
                    array[xx, yy, zz] = b.ReadInt32();
                }
            }
        }
    }
    

    这比将字符串写入文件要有效得多,如果您的数据类型较小,您可以事件写入Int16s 和Bytes。对于非常小的文件,您可以将其与 Gzip 结合使用。

    【讨论】:

    • 谢谢,但不幸的是我在 b.Write(array[xx, yy, zz]); 上得到了 NullReferenceException;
    • 好的,这很好用!我将把我的值转换为 int16 以帮助文件大小。谢谢!
    • 如果您只有 2 位数字,您可以使用 byte 而不是 int
    【解决方案2】:

    Cyral 的回答是正确的。但是由于您要求最快的方法,我自己的测试表明使用 P/Invoke 大约快三倍:

    [DllImport("kernel32.dll")]
    private static extern bool WriteFile(IntPtr hFile, IntPtr lpBuffer, int nNumberOfBytesToWrite, out int lpNumberOfBytesWritten, IntPtr lpOverlapped);
    
    private static unsafe void Write(Int32[,,] array)
    {
        fixed (int* pArray = array)
        {
            using (var file = File.Open("filename", FileMode.Create, FileAccess.Write))
            {
                int written;
                WriteFile(file.SafeFileHandle.DangerousGetHandle(), (IntPtr)pArray, array.Length, out writter, IntPtr.Zero);
            }
        }
    }
    

    kernel32.dll中有对应的ReadFile()函数可以用来读取,比照

    【讨论】:

      【解决方案3】:

      如果您想使用字符串,请使用 StringBuilder 而不是 String +=,因为它更有效

      【讨论】:

        猜你喜欢
        • 2014-11-27
        • 2012-02-27
        • 2018-04-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-12-04
        • 2020-09-25
        相关资源
        最近更新 更多