从.txt文件拆分时,索引超出了数组修复的范围
本文关键字:数组 范围 文件 txt 拆分 分时 索引 | 更新日期: 2023-09-27 18:36:57
我想使用 /
和 *
拆分从 txt 文件中读取的文本。
但是,我浏览文件并出现'Index was outside the bounds of the array.'
!
任何帮助将不胜感激
OpenFileDialog ofd = new OpenFileDialog();
if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
string fileToOpen = ofd.FileName;
System.IO.StreamReader sr = new System.IO.StreamReader(fileToOpen);
string fileContent = sr.ReadLine();
string[] items = fileContent.Split('*').ToArray<string>();
string[] buffer;
foreach (string s in items)
{
ListViewItem lv = new ListViewItem();
buffer = s.Split('/').ToArray<string>();
lv.Text = items[0].ToString();
lv.SubItems.Add(items[1].ToString());
lv.SubItems.Add(items[2].ToString());
lv.SubItems.Add(items[3].ToString());
listView1.Items.Add(lv);
lv.Text = buffer[0];
lv.SubItems.Add(buffer[1]);
lv.SubItems.Add(buffer[2]);
listView1.Items.Add(lv);
}
}
是我的代码,谢谢!
使用项目。计数以确保项目数组中存在多少个元素。并使用从 0 到小于项的索引。计数。
即代码应该是这样的:
foreach (string s in items)
{
ListViewItem lv = new ListViewItem();
buffer = s.Split('/').ToArray<string>();
lv.Text = items[0].ToString();
for(int i=0; i<items.Count; i++)
{
lv.SubItems.Add(items[i].ToString());
}
listView1.Items.Add(lv);
lv.Text = buffer[0];
lv.SubItems.Add(buffer[1]);
lv.SubItems.Add(buffer[2]);
listView1.Items.Add(lv);
}
在 foreach 循环中,您将再次拆分字符串,'/'
为
buffer = s.Split('/').ToArray<string>();
如果在上面的字符串(s
)中找不到'/'
,则缓冲区可能没有2/3
项,因此
lv.SubItems.Add(buffer[1]);
lv.SubItems.Add(buffer[2]);
上面的行可能会导致索引越界错误。
或者可能是由于:
lv.SubItems.Add(items[1].ToString());
lv.SubItems.Add(items[2].ToString());
lv.SubItems.Add(items[3].ToString());
数组索引应始终小于数组中的长度(或项目数)。
您可以同时使用 '/'
和 '*'
拆分字符串;
fileContent.Split(new [] {"*", "/"}, StringSplitOptions.None).ToArray<string>();
您的代码对数组索引大小做出了不安全的假设!
您应该添加一些if
条件,以便获得针对IndexOutOfRangeException
的保护或改用循环。
例如,你怎么知道你这里有 4 个元素:
lv.Text = items[0].ToString();
lv.SubItems.Add(items[1].ToString());
lv.SubItems.Add(items[2].ToString());
lv.SubItems.Add(items[3].ToString());
这样做是为了安全
起见:for(int i = 0; i < items.Length; i++)
{
lv.SubItems.Add(items[i])
}
或者至少先检查您是否有 4 个元素:
if(items.Length == 4)
{
lv.Text = items[0].ToString();
lv.SubItems.Add(items[1].ToString());
lv.SubItems.Add(items[2].ToString());
lv.SubItems.Add(items[3].ToString());
}
若要避免索引超出范围,请以 linq 方式重构代码以处理数据的动态性质,并且不再编制索引。此外,通过使用正则表达式来解析数据,这可能是有益的情况。
下面是使用正则表达式和 Linq 的过程的近似值,以及在将子项添加到列表视图时删除大部分索引的过程。此外,从正则表达式模式中提取的数据使用命名匹配组,不使用索引。
整体概念是使用 foreach 而不是 for; 本身。
列表视图示例
string data = "*Alpha/Beta/Gamma*Zebra/Delta/Tango";
string pattern = @"'*((?<SlashValues>[^/*]+)/?)+";
Regex.Matches(data, pattern, RegexOptions.IgnorePatternWhitespace)
.OfType<Match>()
.Select (mt => new {
LVI = new ListViewItem(),
SubItems = mt.Groups["SlashValues"].Captures
.OfType<Capture>()
.Select (cp => cp.Value),
}
)
.ToList()
.ForEach(item => {
item.LVI.Text = item.SubItems.FirstOrDefault(),
LVI.AddRange(item.SubItems.Skip(1));
listView1.Items.Add(item);
});
正则表达式示例
取出 ListViewItem 代码可以更好地理解正则表达式处理。每个匹配项都是一个新的 ListView 项,其中模式查找 * 作为锚点。找到之后,它会寻找除以/或 * 的多个值,因为它表示匹配的结束和新匹配的开始。
试试这个作为控制台应用程序:
string data = "*Alpha/Beta/Gamma*Zebra/Delta/Tango";
// Put into group "SlashValues" into its capture collection
// [] is a set
// [^] ^ in the set means NOT
// [^*/] Not a * or /
// [^*/]+ + means one or more
// which gets all characters up to a / or *
string pattern = @"'*((?<SlashValues>[^/*]+)/?)+";
Regex.Matches(data, pattern, RegexOptions.IgnorePatternWhitespace)
.OfType<Match>()
.Select (mt => mt.Groups["SlashValues"].Captures
.OfType<Capture>()
.Select (cp => cp.Value))
.ToList()
.ForEach(rs => Console.WriteLine (string.Join(", ", rs)));
/*
Alpha, Beta, Gamma
Zebra, Delta, Tango
*/