C#中读取⽂本⽂件导⼊SQL数据库解决⽅法
概述:
⽂本⽂件是⼀种⾮常常⽤的⽂件格式,因其通⽤的阅读⽅式⽽经常被⽤做不同单位的数据交换⽂件格式。
⽂本⽂件需要能够正确导⼊数据库,
必须要满⾜以下两个条件其中之⼀:
1:⽂本⽂件的结构格式固定,长度固定.
2:⽂本⽂件每⾏长度不固定,但每个字段之间有特殊符号分开.
本⽂给出的是满⾜条件1的⽂本⽂件导⼊到数据库的解决⽅法,对于满⾜条件2的⽂本⽂件,道理类似,
有兴趣的朋友可以⾃⾏测试,如有问题,欢迎交流和沟通!
⼀:问题描述:
这是⽼婆⼤⼈单位的⼀个项⽬,需求其实还是⽐较清晰的:要求编写Asp.Net程序,⾃动读取每天⽣成的⽂本⽂件,
根据业务逻辑处理后,保存到SQLSERVER数据库。
⽂本格式定义:
1:每⼀⾏具有相同固定格式,⼀⾏就对应于数据库中的⼀条记录,记录的每个字段都有明确的长度定义。
2:每⼀⾏⽂本都是连续的,中间没有任何的特殊的符号来区分不同的字段。
3:⽂本中有英⽂字母和数字,也可能有中⽂汉字。
4:格式规定,⼀个英⽂字母或数字对应的长度为1,中⽂汉字对应的长度为2.
根据项⽬需求分析,整个需求并不复杂,⼀般来说,⽂本⽂件需要能够正确导⼊数据库,
必须要满⾜以下两个条件其中之⼀:
1:⽂本⽂件的结构格式固定,长度固定.
2:⽂本⽂件每⾏长度不固定,但每个字段之间有特殊符号分开.
上述需求满⾜条件1,肯定可以能正确导⼊到数据库。
⼆:初步的解决思路和步骤
1:读取⽂本⽂件内容到数据流StreamReader
2:开始事务
3:循环从数据流中读取每⼀⾏到字符串,按表结构定义通过SubString函数对字符串进⾏截取到每⼀个字段变量。
4:定义SQL存储过程,传⼊步骤3中的每个字段值,在存储过程中完成每条记录的插⼊!
5:执⾏事务
6:事务回滚
7:错误消息捕捉,返回友好信息提⽰
8:释放相关资源
三:实际开发中出现的问题与解决⽅法
问题:
实际的程序中,按照⽂本⽂件定义的字段长度进⾏字符串截取,取出来的字符串长度与实际长度不⼀致,不论是使⽤bg2312编码还是默认编码。具体现象通过调试跟踪,在C#中,不论是英⽂字母还是汉字,取出来的长度也是1,⽽不是如⽂本⽂件中规定的那样,汉字长度为2.导致整个字符串与实际定义的长度不⼀致,所以在⽤SubString()函数截取字符串时,⽆法根据数据结构定义中的长度正确取得每个字段值。
原因分析:
问题原因很明显是编码格式出现问题,汉字保存在磁盘中的编码有多种,常见的有:GB、BIG5 、Unicode、UTF-7、UTF-8等。在⽂本⽂件读取过程中,  ⽂件的编码(Encoding)和StreamReader/Writer指定的Encoding不对应,就会出现乱码问题。虽然StreamReader可以根据⽂本⽂件格式⾃动识别编码格式,正确读取不同编码格式的⽂本⽂件。但对于字符串来说,是⽆法识别字符串中的中⽂字符与英⽂,数字的区别,统⼀都作⽤长度为1处理。正确的处理⽅法是使⽤将字符串转换为字节数组,对字节数组按⽂本⽂件定义的字段长度读取每个字段值。
四:修正的解决思路
1:读取⽂本⽂件内容到数据流StreamReader
2:开始事务
3:循环从数据流中读取每⼀⾏到字符串,并转换为字节数组。按表结构定义对字节数组进⾏截取到每⼀个字段变量。
4:定义SQL存储过程,传⼊步骤3中的每个字段值,在存储过程中完成每条记录的插⼊!
5:执⾏事务
6:事务回滚
7:错误消息捕捉,返回友好信息提⽰
8:释放相关资源
五:相关的⽂本⽂件处理函数参考,完整的源码见附件
1///<summary>
2///通⽤函数,读⽂本⽂件
3///</summary>
4///<param name="fileName">读⼊的⽂本⽂件名称</param>
5public static void ReadTextFromFileName(string fileName)
6    {
7string strRecord = "";
8
9//读⼊⽂本⽂件时,⼀定要指定⽂件的编码格式.其中:default为⽂本⽂件本来的编码格式
10//如果是简体中⽂的⽂本⽂件,也可以这样设置编码格式: System.Text.Encoding.GetEncode("gb2312")
11//Encoding.GetEncode("gb2312")为简体中⽂编码格式,Encoding.GetEncode("big5")为繁体中⽂编码格式.
12      StreamReader reader = new StreamReader(fileName,System.Text.Encoding.Default);
13
14      da = new DataAccess();
15      da.OpenConnection();
16
17//指定本次数据操作进⾏事务处理
18      da.StartTrans = true;
19
20//开始事务处理
21      da.BeginTrans();
22
23//i is the really row
24//j is the row of writed to database
25int i ,j;
26      i=0;
27      j=0;
28try
29      {
30while (reader.Peek() >= 0)
31        {
32          strRecord = reader.ReadLine();
33if (StringConvertByteArray(strRecord))
34          {
35            j++;
36          }
37          i++;
38        }
39
40//执⾏事务
41        da.Commit();
42
43        TotalLine = i;
44        RealLine = j;
存储过程 字符串转数组45      }
46catch (Exception ex)
47      {
48//事务回滚
49        da.Rollback();
50
51
52        SystemError.SystemLog("⽂件:" + fileName +"导⼊失败,错误⾏是第"+ i.ToString()+ "⾏,原因是: " + ex.Message);  53throw new Exception(ex.Message);
54      }
55
56//相关资源的消除
57finally
58      {
59        reader.Close();
60        da.CloseConnection();
61      }
62    }
63
64
65///<summary>
66///处理定长⽂本⽂件的函数,将字符串转换成byte[]数组
67///</summary>
68///<param name="aRecord"></param>
69private static bool StringConvertByteArray(string aRecord)
70    {
71//解决⽂本⽂件⼀⾏中可能存在中⽂的情况,将string类型转换为byte[]来达到
72//正确处理⽂本⽂件的⽬的
73byte[] repRecord = System.Text.Encoding.Default.GetBytes(aRecord);
74
75//判断取得的⽂本⽂件长度是否等于定义的⽂本⽂件长度
76if (repRecord.Length    != iLineLength)
77      {
78        SystemError.SystemLog("⽂件:" + fileName +"导⼊出错,出错原因是⽂件长度不符合");
79throw new Exception("⽂件⽂本长度不对,导⼊失败,请检查⽂件⽂件格式");
80      }
81
82bool isInsert=false;
83      isInsert = AddRecord(
84        GetString(repRecord,0,8),
85        GetString(repRecord,8,8),
86        GetString(repRecord,16,6),
87        GetString(repRecord,22,6),
88        GetString(repRecord,28,8),
89        GetString(repRecord,36,6),
90        GetString(repRecord,42,10),
91        GetString(repRecord,52,4),
92        GetString(repRecord,56,6),
93        GetString(repRecord,62,8),
94        GetString(repRecord,70,7),
95        GetString(repRecord,77,32),
96        GetString(repRecord,109,72),
97        GetString(repRecord,181,8),
98        GetString(repRecord,189,30),
99        GetString(repRecord,219,45),
100        GetString(repRecord,264,10),
101        GetString(repRecord,274,25),
102        GetString(repRecord,299,2),
103        GetString(repRecord,301,25),
104        GetString(repRecord,326,3),
105        GetString(repRecord,329,15),
106        GetString(repRecord,344,1),
107        GetString(repRecord,345,8),
108        GetString(repRecord,353,6),
109        GetString(repRecord,359,8),
110        GetString(repRecord,367,1),
111        GetString(repRecord,368,1),
112        GetString(repRecord,369,32),
113        GetString(repRecord,401,7),
114        GetString(repRecord,408,60),
115        GetString(repRecord,468,20),
116        GetString(repRecord,488,20),
117        GetString(repRecord,508,20),
118        GetString(repRecord,528,36),
119        GetString(repRecord,564,15),
120        GetString(repRecord,579,15),
121        GetString(repRecord,594,15)
122        );
123return isInsert;
124
125    }
126
127
128//private static void
129///<summary>
130///处理长度固定的⽂本⽂,读取到每个字段的值
131///</summary>
132///<param name="aStr">⽂本⽂件的每⾏⽂本转换的Byte数组</param> 133///<param name="iStart">读取的起始位置</param>
134///<param name="iLength">读取的长度</param>
135///<returns>返回的字符串,对应于具体的字段值</returns>
136private static string GetString(byte[] aStr,int iStart,int iLength)
137    {
138
139byte[] tempStr = new byte[iLength];
140for ( int i = 0; i < iLength; i ++)
141      {
142        tempStr[i] = (byte)aStr.GetValue(iStart + i);
143      }
144
145return System.Text.Encoding.Default.GetString(tempStr);
146    }

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。