首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > .NET > C# >

请问下C#关于大数组怎么快速保存到硬盘的有关问题

2013-10-12 
请教下C#关于大数组如何快速保存到硬盘的问题请教大家,由于在做c#一个数据采集卡的程序,由于采样率很高因

请教下C#关于大数组如何快速保存到硬盘的问题
请教大家,由于在做c#一个数据采集卡的程序,由于采样率很高因此 每秒有200000个double的速度。

     我现在有一个 ADDATA[4,2000000]的二维数组来储存这些数据 , 希望能快速的把这个数组从内存里扔到硬盘中,因为这个数组的值每格1S会重新接受新的数据 ,所以要每隔1S存一次,而且存的值是连续可读的 请问 该如何实现呢?
     我之前用


for (int i = 0; i < ADData.Length; i++)
                    {
                        try
                        {
                           
                            File.AppendAllText("E:\\a.txt", ADData[i].ToString() + "\r\n");
                        }
                        catch (Exception ee)
                        {
                            MessageBox.Show("" + ee);
                        }
                    }

来写入文件,发现非常慢。请问如何解决这个问题呢。

[解决办法]
先放到内存,然后后台开线程去写文件,或者先写入文件流,最后统一将流保存为文件,io效率最低,最好不要频繁的进行io读写
[解决办法]
先转成字节数组,再写入二进制文件
            double[] ADData = new double[2000000];
            byte[] bytes = new byte[ADData.Length * sizeof(double)];
            Buffer.BlockCopy(ADData, 0, bytes, 0, ADData.Length * sizeof(double));

[解决办法]
可以考虑压缩下
[解决办法]
引用:
请教大家,由于在做c#一个数据采集卡的程序,由于采样率很高因此 每秒有200000个double的速度。

     我现在有一个 ADDATA[4,2000000]的二维数组来储存这些数据 , 希望能快速的把这个数组从内存里扔到硬盘中,因为这个数组的值每格1S会重新接受新的数据 ,所以要每隔1S存一次,而且存的值是连续可读的 请问 该如何实现呢?
     我之前用

for (int i = 0; i < ADData.Length; i++)
                    {
                        try
                        {
                           
                            File.AppendAllText("E:\\a.txt", ADData[i].ToString() + "\r\n");
                        }
                        catch (Exception ee)
                        {
                            MessageBox.Show("" + ee);
                        }
                    }

来写入文件,发现非常慢。请问如何解决这个问题呢。


你说的每秒就会存储一次的意思是在数组里面的数据要在1秒钟全部存到disk? 然后清空,接受新的数据重复上面的1秒存储操作? 


[解决办法]
200000个double,每个double8个字节,为1.6兆/秒。硬盘本身应该没有问题。
但是每次File.AppendAllText会打开并关闭文件,开销很大。

建议你采用二进制输出,并采用文件流(利用已有的缓存机制)。


using (FileStream fs = new FileStream("filename", FileMode.Create, FileAccess.Write))
using (BinaryWriter writer = new BinaryWriter(fs))
{
    for (int i = 0; i < ADData.Length; i++)
    {
        writer.Write(ADData[i]);
    }
}

[解决办法]
IO部分可优化的幅度很少,尽量减少文件开关次数就行了
[解决办法]
我的天,appendtext这是最慢的方式。

还ToString()。应该直接写二进制文件。
[解决办法]
这么大量的数据写入文件,时间全部浪费在循环语句上了,建议楼主使用 WINDOWS API 写文件
CreateFile, WriteFile, CloseHandle 
[解决办法]
另外你用多线程IO试一下,就是说用多个stream实例操作一个文件(这里用到了锁的机制),我写了一个例子,你测试一下看看能不能达到你的要求。
    public class ThreadTest
    {
        private ReaderWriterLockSlim l = new ReaderWriterLockSlim();

        public void Write(object obj)
        {
            List<object> lst = obj as List<object>;
            FileStream fs = lst[0] as FileStream;
            long offset = (long)lst[1];
            long count = (long)lst[2];
            byte[] data = lst[3] as byte[];

            l.EnterWriteLock();
            try
            {
                using (fs)
                {
                    fs.Seek(offset, SeekOrigin.Begin);
                    for (long i = offset; i < count; i++)
                    {
                        fs.WriteByte(data[i]);
                    }
                }
            }
            finally
            {
                l.ExitWriteLock();
            }
        }
    }


    class Program
    {
        static byte[] GetBytes(string str)
        {
            byte[] bytes = new byte[str.Length * sizeof(char)];
            System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
            return bytes;
        }

        static void Main(string[] args)
        {
            // 模拟100W double数据
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < 1000000; i++)
            {
                double num = new Random().NextDouble();
                sb.Append(num);


            }

            ThreadTest test = new ThreadTest();
            //string str = "1234567891011121314151617181920212223242526272829303132";
            byte[] data = GetBytes(sb.ToString());
            int threadCount = 10;
            long count = data.Length / threadCount;
            for (long offset = 0; offset < data.Length; offset = count)
            {
                count += offset;
                if (count > data.Length)
                {
                    count = data.Length;
                }
                FileStream fs = new FileStream("Test.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite);
                List<object> lst = new List<object>();
                lst.Add(fs); lst.Add(offset); lst.Add(count); lst.Add(data);
                new Thread(new ParameterizedThreadStart(test.Write)).Start(lst);
            }
        }
    }



其中的threadCount就是你需要启用的线程数,这些线程就是用来异步的写入数据到文件中,分段的写入数据(Seek方法)。

热点排行