索引超出了数组exception的范围

这是我从平面文件中获取数据并插入SQL Server的代码。 它正在生成exception( Index was outside the bounds of the array )。

 string path = string.Concat(Server.MapPath("~/TempFiles/"), Fileupload1.FileName); string text = System.IO.File.ReadAllText(path); string[] lines = text.Split(' '); con.Open(); SqlCommand cmd = new SqlCommand(); string[] Values = new string[3]; foreach (string line1 in lines) { Values = line1.Split(';'); string query = "INSERT INTO demooo VALUES ('" + Values[0] + "','" + Values[1] + "','" + Values[2] + "')"; cmd = new SqlCommand(query,con); cmd.ExecuteNonQuery(); } 

发生exception是因为您的一行中有少于三个以分号分隔的元素 。 即使您将Values声明为包含三个元素的String数组,但将变量影响到String.Split()函数的结果会使其无关紧要:您的数组将具有返回数组所具有的任何长度。 如果它更少,你的代码肯定会失败。

如果它不应该发生,我建议你在代码中做一个断言来帮助你调试:

 // ... Values = line1.Split(';'); // the following will make the debugger stop execution if line.Length is smaller than 3 Debug.Assert(line1.Length >= 3); // ... 

作为旁注,我应该提到批处理INSERT会更有效率。 您声明和重新生成cmd变量的方式也不太正确。 最后,您应该在值上调用String.Replace以确保任何撇号加倍。 否则,您的代码将打开SQL注入攻击。

有关代码在运行时的行为方式的一些详细信息:

 // This line declares a variable named Values and sets its value to // a new array of strings. However, this new array is never used // because the loop overwrites Values with a new array before doing // anything else with it. string[] Values = new string[3]; foreach (string line1 in lines) { Values = line1.Split(';'); // At this point in the code, whatever was previously stored in Values has been // tossed on the garbage heap, and Values now contains a brand new array containing // the results of splitting line1 on semicolons. // That means that it is no longer safe to assume how many elements the Values array has. // For example, if line1 is blank (which often happens at the end of a text file), then // Values will be an empty array, and trying to get anything out of it will throw an // exception string query = "INSERT INTO demooo VALUES ('" + Values[0] + "','" + Values[1] + "','" + Values[2] + "')"; cmd = new SqlCommand(query,con); cmd.ExecuteNonQuery(); } 

与值不断被覆盖的方式类似,在循环外创建的SqlCommand也将永远不会被使用。 将这两个声明放在循环中是安全的。 下面的代码执行此操作,并添加了一些错误检查以确保从行中检索可用数量的值。 它只会跳过任何不够长的行 – 如果不行,那么你可能需要创建一些更复杂的error handling代码。

 foreach(string line in lines) { string[] values = line.split[';']; if(values.Length >= 3) { string query = "INSERT INTO demooo VALUES ('" + Values[0] + "','" + Values[1] + "','" + Values[2] + "')"; using (SqlCommand command = new SqlCommand(query, con)) { cmd.ExecuteNonQuery(); } } } 

最后要注意的是,如果你在像Web应用程序这样的东西中使用它,上面的代码可能容易受到黑客攻击。 如果您正在处理如下所示的文件,请考虑可能会将命令发送到服务器:

 1;2;3 4;5;6 7;8;9') DROP TABLE demooo SELECT DATALENGTH('1 

更安全的选择是使用参数化查询,这将有助于防止此类攻击。 他们通过将命令与其参数分开来实现此目的,这有助于保护您不会传递看起来像SQL代码的参数的值。 如何以这种方式设置的示例看起来更像是:

 string query = "INSERT INTO demooo VALUES (@val1, @val2, @val3); using (var command = new SqlCommand(query, con)) { command.Parameters.AddWithValue("@val1", Values[0]); command.Parameters.AddWithValue("@val2", Values[1]); command.Parameters.AddWithValue("@val3", Values[2]); command.ExecuteNonQuery(); } 

试试这个。

 string path = string.Concat(Server.MapPath("~/TempFiles/"), Fileupload1.FileName); string text = System.IO.File.ReadAllText(path); string[] lines = text.Split(' '); con.Open(); string[] Values; foreach (string line1 in lines) { Values = line1.Split(';'); if (Values.Length >= 3) { string query = "INSERT INTO demooo VALUES ('" + Values[0] + "','" + Values[1] + "','" + Values[2] + "')"; } else { //Some error occured } using (var cmd = new SqlCommand(query,con)) { cmd.ExecuteNonQuery(); } }