c# 读取一个1G的文件到数据库

时间:2022-05-31 17:20:33
大家好,我用c#读取一个1G的文件到数据库,总是会卡死。 请大家帮我参考下,是哪里的问题。 我电脑内存是1.5G的.


foreach (string file in files)
                {
                    //把要执行的SQL保存到数组,然后用事务一起提交
                    List<string> sqlList = new List<string>();
                    List<MySqlParameter[]> paraList = new List<MySqlParameter[]>();


                    using (StreamReader reader = new StreamReader(file))
                    {

                     
                        //计数器,5万条写一次数据库
                        int dataNum = 0;

                        while ((line = reader.ReadLine()) != null)
                        {
                            

                              sqlList.Add(str);
                              paraList.Add(cmdParms); 
                                                 
                            dataNum++;
                            //5万条保存一次数据库
                            if (dataNum == 50000)
                            {
                                ExecuteTransaction(sqlList, paraList);
                                dataNum = 0;
                                sqlList.Clear();
                                paraList.Clear();

                            }

                        }

                        //保存订单到数据库
                        DBHelper.ExecuteTransaction(sqlList, paraList);
                       

}

15 个解决方案

#1


一次性都读进去 应该会很慢  ,可以试试每次读100M  。
个人理解。

#2


使用多线程或者并行编程,让读取操作放在后台进行,你不要一次性读取所有数据到内存中,应该设置个缓存

#3


请问,有这方面的例子么

#4


这么大的文件读取加载本身就是个问题,建议试试多线程

#5


多线程也需要内存的吧。 我们服务器内存太少了

#6


这个例子希望对你有所帮助。这个程序处理的大批量txt数据,进行处理后批量导入到数据库中,时间方面还是不错的,没有卡死等现象出现。关键是BatchSize方法的设置,一定小心,否则就出现你的情况。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.SqlClient;
using System.IO;

namespace bulkdata
{
    class Program
    {

        static void Main(string[] args)
        {
            string[] directoy = Directory.GetFiles(@"E:\工作\巡检分析\txt数据\3月\下");//存放了状态数据文件夹下的所有文件夹

            for (int di = 0; di < directoy.Length; di++)
            {
                StreamReader sr = new StreamReader(directoy[di],System.Text.Encoding.Default);//最为常用的打开txt,设定编码方式

                DataTable dt = new DataTable();//创建表                                                       
                //添加表头
                DataColumn a = new DataColumn("time", Type.GetType("System.DateTime"));
                DataColumn b = new DataColumn("name", Type.GetType("System.String"));
                DataColumn j = new DataColumn("type", Type.GetType("System.Char"));
                DataColumn c = new DataColumn("rost", Type.GetType("System.Int32"));
                DataColumn d = new DataColumn("threshold", Type.GetType("System.Int32"));
                DataColumn e = new DataColumn("tcr", Type.GetType("System.Single"));
                DataColumn f = new DataColumn("longitude", Type.GetType("System.Single"));
                DataColumn g = new DataColumn("latitude", Type.GetType("System.Single"));
                DataColumn h = new DataColumn("dop", Type.GetType("System.Single"));
                DataColumn i = new DataColumn("fe", Type.GetType("System.Int32"));
                dt.Columns.Add(a); dt.Columns.Add(b); dt.Columns.Add(c); dt.Columns.Add(d); dt.Columns.Add(e);
                dt.Columns.Add(f); dt.Columns.Add(g); dt.Columns.Add(h); dt.Columns.Add(i); dt.Columns.Add(j);

                String line;
                while ((line = sr.ReadLine()) != null)
                  {
                      try
                      {
                          string[] splits = line.Split(new Char[] { ' ', ' ' }, StringSplitOptions.RemoveEmptyEntries);//用' ', ' '分开 
                          splits[0] = splits[0] + " " + splits[1];
                          char stype = getstationtype(splits[2]);
                          string sname = getstationname(splits[2]);
                          DateTime stime = DateTime.Parse(splits[0]);
                          if ((stime > DateTime.Parse("9999-12-31 11:59:59")) || (stime < DateTime.Parse("1753-1-1 12:00:00")))
                          {
                              continue; 
                          }
                          DataRow dr = dt.NewRow();//添加行数据
                          dr["time"] = DateTime.Parse(splits[0]);
                          dr["name"] = sname;
                          dr["type"] = stype;
                          dr["rost"] = Convert.ToInt32(splits[3]);
                          dr["threshold"] = Convert.ToInt32(splits[4]);
                          dr["tcr"] = Convert.ToSingle(splits[5]);
                          dr["longitude"] = Convert.ToSingle(splits[6]);
                          dr["latitude"] = Convert.ToSingle(splits[7]);
                          dr["dop"] = Convert.ToSingle(splits[8]);
                          dr["fe"] = Convert.ToInt32(splits[9]);
                          dt.Rows.Add(dr);
                      }
                      catch
                      {
                          continue;
                      }
                  }
               sr.Close();
               if(dt!=null)           
                 AddDataByLocal(dt); //批量插入       
               Console.WriteLine(directoy[di].ToString());
             }
        }

        public static bool AddDataByLocal(DataTable dt)
              {
                  bool result = false;
                  string constring = @"server=.\sqlexpress;integrated security=true;database=status201303";
                  using (System.Data.SqlClient.SqlConnection conn = new System.Data.SqlClient.SqlConnection(constring))
                    {
                      conn.Open();
                      try
                        {
                           using (System.Data.SqlClient.SqlBulkCopy sbc = new System.Data.SqlClient.SqlBulkCopy(constring))
                              {
                                try
                                  {
                                     sbc.DestinationTableName = "Late"; //服务器上目标表的名称
                                     sbc.BatchSize = 1000;//很重要,否则会报时间超时的错误
                                     sbc.BulkCopyTimeout = 1000;//设置允许超时时间为100秒
                                     sbc.ColumnMappings.Add("time", "time"); //本地表和目标表列名
                                     sbc.ColumnMappings.Add("name", "name");//如果表有多个字段,下面继续添加
                                     sbc.ColumnMappings.Add("type", "type");
                                     sbc.ColumnMappings.Add("rost", "rost"); //本地表和目标表列名
                                     sbc.ColumnMappings.Add("threshold", "threshold");//如果表有多个字段,下面继续添加
                                     sbc.ColumnMappings.Add("tcr", "tcr"); //本地表和目标表列名
                                     sbc.ColumnMappings.Add("longitude", "longitude");   //如果表有多个字段,下面继续添加
                                     sbc.ColumnMappings.Add("latitude", "latitude"); //本地表和目标表列名
                                     sbc.ColumnMappings.Add("dop", "dop");   //如果表有多个字段,下面继续添加
                                     sbc.ColumnMappings.Add("fe", "fe");   //如果表有多个字段,下面继续添加
                                     sbc.WriteToServer(dt);//插入数据
                                     result = true;
                                  }
                               catch (Exception ex)
                                  { 
                                      throw ex;
                                  }
                              }
                       }
                     catch (Exception ex) 
                      { 
                         throw ex;
                      }
                     finally 
                      { 
                          if (conn.State != ConnectionState.Closed) 
                              conn.Close();
                      }
                    }
                   return result;
    }

        public static char getstationtype(string s)
        {
            char a = s[s.Length - 1];
            if (a == 'B')
                return 'B';
            else
                return 'A';
        }

        public static string getstationname(string s)
        {
            char a = s[s.Length - 1];
            if (a == 'B')
                return s.TrimEnd('B');
            else
                return s;
        }
    }
}

#7


哥们,你的优化在写数据库这里。我的问题在文件读取太大

#8


“卡死”很正常,如果你在界面线程执行阻塞的操作,这个期间无法响应用户操作,当然是卡死。

如果你等个几个小时乃至几天,等操作完成就恢复了。事实上,你执行插入一条数据也会“卡死”,只是也许只“卡死”0.0001秒,你感觉不出来而已。

#9


多线程 也没法解决吧 总不能多个线程去操作这个文件吧  服务器内存一共就512M的话 操作1G文件我觉得怎么都是不可能的!

#10


你这里的卡死和你服务器内存大小没关系,8g内存照样卡死。

#11


使用线程试试,放到后台执行

#12


在循环开始或者结束地方加上 Application.Doevent(); 用来响应界面操作,你那个卡上是假死状态,程序一直在执行这个方法,没有时间来处理界面操作

#13


读取一个1G的文件到数据库

一次性读取是脑子进水。

#14


引用 2 楼 lizhi3186575 的回复:
使用多线程或者并行编程,让读取操作放在后台进行,你不要一次性读取所有数据到内存中,应该设置个缓存


设置个缓存? 怎么个搞法

#15


application.doevents()

#1


一次性都读进去 应该会很慢  ,可以试试每次读100M  。
个人理解。

#2


使用多线程或者并行编程,让读取操作放在后台进行,你不要一次性读取所有数据到内存中,应该设置个缓存

#3


请问,有这方面的例子么

#4


这么大的文件读取加载本身就是个问题,建议试试多线程

#5


多线程也需要内存的吧。 我们服务器内存太少了

#6


这个例子希望对你有所帮助。这个程序处理的大批量txt数据,进行处理后批量导入到数据库中,时间方面还是不错的,没有卡死等现象出现。关键是BatchSize方法的设置,一定小心,否则就出现你的情况。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.SqlClient;
using System.IO;

namespace bulkdata
{
    class Program
    {

        static void Main(string[] args)
        {
            string[] directoy = Directory.GetFiles(@"E:\工作\巡检分析\txt数据\3月\下");//存放了状态数据文件夹下的所有文件夹

            for (int di = 0; di < directoy.Length; di++)
            {
                StreamReader sr = new StreamReader(directoy[di],System.Text.Encoding.Default);//最为常用的打开txt,设定编码方式

                DataTable dt = new DataTable();//创建表                                                       
                //添加表头
                DataColumn a = new DataColumn("time", Type.GetType("System.DateTime"));
                DataColumn b = new DataColumn("name", Type.GetType("System.String"));
                DataColumn j = new DataColumn("type", Type.GetType("System.Char"));
                DataColumn c = new DataColumn("rost", Type.GetType("System.Int32"));
                DataColumn d = new DataColumn("threshold", Type.GetType("System.Int32"));
                DataColumn e = new DataColumn("tcr", Type.GetType("System.Single"));
                DataColumn f = new DataColumn("longitude", Type.GetType("System.Single"));
                DataColumn g = new DataColumn("latitude", Type.GetType("System.Single"));
                DataColumn h = new DataColumn("dop", Type.GetType("System.Single"));
                DataColumn i = new DataColumn("fe", Type.GetType("System.Int32"));
                dt.Columns.Add(a); dt.Columns.Add(b); dt.Columns.Add(c); dt.Columns.Add(d); dt.Columns.Add(e);
                dt.Columns.Add(f); dt.Columns.Add(g); dt.Columns.Add(h); dt.Columns.Add(i); dt.Columns.Add(j);

                String line;
                while ((line = sr.ReadLine()) != null)
                  {
                      try
                      {
                          string[] splits = line.Split(new Char[] { ' ', ' ' }, StringSplitOptions.RemoveEmptyEntries);//用' ', ' '分开 
                          splits[0] = splits[0] + " " + splits[1];
                          char stype = getstationtype(splits[2]);
                          string sname = getstationname(splits[2]);
                          DateTime stime = DateTime.Parse(splits[0]);
                          if ((stime > DateTime.Parse("9999-12-31 11:59:59")) || (stime < DateTime.Parse("1753-1-1 12:00:00")))
                          {
                              continue; 
                          }
                          DataRow dr = dt.NewRow();//添加行数据
                          dr["time"] = DateTime.Parse(splits[0]);
                          dr["name"] = sname;
                          dr["type"] = stype;
                          dr["rost"] = Convert.ToInt32(splits[3]);
                          dr["threshold"] = Convert.ToInt32(splits[4]);
                          dr["tcr"] = Convert.ToSingle(splits[5]);
                          dr["longitude"] = Convert.ToSingle(splits[6]);
                          dr["latitude"] = Convert.ToSingle(splits[7]);
                          dr["dop"] = Convert.ToSingle(splits[8]);
                          dr["fe"] = Convert.ToInt32(splits[9]);
                          dt.Rows.Add(dr);
                      }
                      catch
                      {
                          continue;
                      }
                  }
               sr.Close();
               if(dt!=null)           
                 AddDataByLocal(dt); //批量插入       
               Console.WriteLine(directoy[di].ToString());
             }
        }

        public static bool AddDataByLocal(DataTable dt)
              {
                  bool result = false;
                  string constring = @"server=.\sqlexpress;integrated security=true;database=status201303";
                  using (System.Data.SqlClient.SqlConnection conn = new System.Data.SqlClient.SqlConnection(constring))
                    {
                      conn.Open();
                      try
                        {
                           using (System.Data.SqlClient.SqlBulkCopy sbc = new System.Data.SqlClient.SqlBulkCopy(constring))
                              {
                                try
                                  {
                                     sbc.DestinationTableName = "Late"; //服务器上目标表的名称
                                     sbc.BatchSize = 1000;//很重要,否则会报时间超时的错误
                                     sbc.BulkCopyTimeout = 1000;//设置允许超时时间为100秒
                                     sbc.ColumnMappings.Add("time", "time"); //本地表和目标表列名
                                     sbc.ColumnMappings.Add("name", "name");//如果表有多个字段,下面继续添加
                                     sbc.ColumnMappings.Add("type", "type");
                                     sbc.ColumnMappings.Add("rost", "rost"); //本地表和目标表列名
                                     sbc.ColumnMappings.Add("threshold", "threshold");//如果表有多个字段,下面继续添加
                                     sbc.ColumnMappings.Add("tcr", "tcr"); //本地表和目标表列名
                                     sbc.ColumnMappings.Add("longitude", "longitude");   //如果表有多个字段,下面继续添加
                                     sbc.ColumnMappings.Add("latitude", "latitude"); //本地表和目标表列名
                                     sbc.ColumnMappings.Add("dop", "dop");   //如果表有多个字段,下面继续添加
                                     sbc.ColumnMappings.Add("fe", "fe");   //如果表有多个字段,下面继续添加
                                     sbc.WriteToServer(dt);//插入数据
                                     result = true;
                                  }
                               catch (Exception ex)
                                  { 
                                      throw ex;
                                  }
                              }
                       }
                     catch (Exception ex) 
                      { 
                         throw ex;
                      }
                     finally 
                      { 
                          if (conn.State != ConnectionState.Closed) 
                              conn.Close();
                      }
                    }
                   return result;
    }

        public static char getstationtype(string s)
        {
            char a = s[s.Length - 1];
            if (a == 'B')
                return 'B';
            else
                return 'A';
        }

        public static string getstationname(string s)
        {
            char a = s[s.Length - 1];
            if (a == 'B')
                return s.TrimEnd('B');
            else
                return s;
        }
    }
}

#7


哥们,你的优化在写数据库这里。我的问题在文件读取太大

#8


“卡死”很正常,如果你在界面线程执行阻塞的操作,这个期间无法响应用户操作,当然是卡死。

如果你等个几个小时乃至几天,等操作完成就恢复了。事实上,你执行插入一条数据也会“卡死”,只是也许只“卡死”0.0001秒,你感觉不出来而已。

#9


多线程 也没法解决吧 总不能多个线程去操作这个文件吧  服务器内存一共就512M的话 操作1G文件我觉得怎么都是不可能的!

#10


你这里的卡死和你服务器内存大小没关系,8g内存照样卡死。

#11


使用线程试试,放到后台执行

#12


在循环开始或者结束地方加上 Application.Doevent(); 用来响应界面操作,你那个卡上是假死状态,程序一直在执行这个方法,没有时间来处理界面操作

#13


读取一个1G的文件到数据库

一次性读取是脑子进水。

#14


引用 2 楼 lizhi3186575 的回复:
使用多线程或者并行编程,让读取操作放在后台进行,你不要一次性读取所有数据到内存中,应该设置个缓存


设置个缓存? 怎么个搞法

#15


application.doevents()