C# 将文本文件中的数据加载到词典中

C# 将文本文件中的数据加载到词典中,c#,C#,我有一个由文本列表组成的文件,如下所示: ABC Abbey something ABD Aasdasd 第一个字符串的长度始终为3。所以我想循环遍历文件内容,将前3个字母存储为键,其余字母存储为值。我正在删除它们之间的空白和子字符串,如下所示进行存储。键工作正常,但存储值的行返回以下错误ArgumentOutOfRangeException 这正是导致问题的代码 line.Substring(4, line.Length) 如果我调用0和line.length之间的子字符串,它可以正常工

我有一个由文本列表组成的文件,如下所示:

ABC Abbey something
ABD Aasdasd

第一个字符串的长度始终为3。所以我想循环遍历文件内容,将前3个字母存储为键,其余字母存储为值。我正在删除它们之间的空白和子字符串,如下所示进行存储。键工作正常,但存储值的行返回以下错误ArgumentOutOfRangeException

这正是导致问题的代码

line.Substring(4, line.Length)
如果我调用0和line.length之间的子字符串,它可以正常工作。只要我把它称为介于1和向上-line.length之间,我就得到了错误。老实说,我不明白,我已经做了好几个小时了。请帮忙

class Program {

        static string line;
        static Dictionary<string, string> stations = new Dictionary<string, string>();

        static void Main(string[] args) {
            var lines = File.ReadLines("C:\\Users\\username\\Desktop\\a.txt");
            foreach (var l in lines) {
                line = l.Replace("\t", "");
                stations.Add(line.Substring(0, 3), line.Substring(4, line.Length));//error caused by this line
            }

            foreach(KeyValuePair<string, string> item in stations) {
                //Console.WriteLine(item.Key);
                Console.WriteLine(item.Value);
            }

            Console.ReadLine();
        }
    }
类程序{
静态弦线;
静态字典站=新字典();
静态void Main(字符串[]参数){
var lines=File.ReadLines(“C:\\Users\\username\\Desktop\\a.txt”);
foreach(行中的变量l){
行=l。替换(“\t”和“);
stations.Add(line.Substring(0,3),line.Substring(4,line.Length));//由此行引起的错误
}
foreach(站点中的KeyValuePair项){
//控制台。写入线(项。键);
Console.WriteLine(项值);
}
Console.ReadLine();
}
}

您需要实际获得的长度小于总行的长度:

line.Substring(4, line.Length - 4)    //subtract the chars which you're skipping
您的字符串:

ABC Abbey something
Length = 19
Start  = 4
Remaining chars = 19 - 4 = 15 //and you are expecting 19, that is the error

这是因为文档指定它将抛出一个if:

startIndex
plus
length
表示不在此实例中的位置

签名:

public string Substring(int startIndex, int length)
由于使用了
line.Length
,您知道
startIndex
加上
Length
将是
4+line.Length
,这肯定不是此实例的位置

我建议使用:

因此,
line.Substring(3)
(归功于@adv12 for)。因为这里您只需要提供
startIndex
。当然,您可以使用
line.SubString(3,line.Length-3)
,但与往常一样,最好使用库,因为库的作用是使程序不会出错(这不是攻击性的,只需确保减少此任务的脑循环量即可)。但是,请注意,如果出现以下情况,它仍可能抛出错误:

startIndex
小于零或大于此实例的长度

所以最好提供
3
小于或等于
line.length
的检查

附加建议
也许你应该看看正则表达式。现在,文件中的每个键都包含三个字符。但在不久的将来,有可能出现四个字符。使用regex capture,您可以指定一种模式,这样在解析过程中就不太可能出现错误。

我知道这是一个迟来的答案,它没有解决代码的问题,但我觉得其他人已经这样做了。相反,我有不同的方法来制作字典,它根本不涉及子字符串,所以它更健壮,IMHO

只要您能保证这两个值总是由制表符分隔,那么即使键中有更多或更少的字符,这也会起作用。它使用的LINQ应该是.NET3.5中的好版本

// LINQ
using System.Linq;

// Creates a string[][] array with the list of keys in the first array position
// and the values in the second
var lines = File.ReadAllLines(@"path/to/file.txt")
                .Select(s => s.Split('\t'))
                .ToArray();

// Your dictionary
Dictionary<string, string> stations = new Dictionary<string, string>();

// Loop through the array and add the key/value pairs to the dictionary
for (int i = 0; i < lines.Length; i++)
{
    // For example lines[i][0] = ABW, lines[i][1] = Abbey Wood
    stations[lines[i][0]] = lines[i][1];
}

// Prove it works
foreach (KeyValuePair<string, string> entry in stations)
{
    MessageBox.Show(entry.Key + " - " + entry.Value);
}
//LINQ
使用System.Linq;
//创建一个字符串[][]数组,其中键列表位于第一个数组位置
//以及第二个表中的值
var lines=File.ReadAllLines(@“path/to/File.txt”)
.Select(s=>s.Split('\t'))
.ToArray();
//你的字典
字典站=新字典();
//循环遍历数组并将键/值对添加到字典中
对于(int i=0;i

希望这是有意义的,并给你另一个考虑;p> 不需要两个参数的版本<代码>“ABC XYZ”。子字符串(4)
“XYZ”
…@AlexK。谢谢,这是可行的,但我仍然不明白为什么它不适用于当前代码。因为您试图读取字符串末尾以外的内容,所以第二个参数是长度,而不是末尾索引。@Trevor_zam很多人都会犯这个错误,尤其是当他们习惯于Java时。另外,请注意,他正在一行上执行子字符串,而该行已经删除了制表符,因此他确实希望在索引3而不是索引4处开始子字符串。@adv12:确实如此。虽然我认为使用split或regex捕获进行提取通常不太容易出错。另外,请注意,他正在一行上执行子字符串,该行已经删除了制表符,因此他确实希望在索引3而不是索引4处启动子字符串。这不会导致错误,因为OP使用的是
string.Length
属性,没有指定固定长度。如果文件包含错误,例如一行只有三个字符,这可能会导致程序崩溃,而忽略行可能是更合理的解决方案;我是说从4开始会给他错误的数据。@Shaharyar+1。一直在考虑第二个参数是结束索引。
// LINQ
using System.Linq;

// Creates a string[][] array with the list of keys in the first array position
// and the values in the second
var lines = File.ReadAllLines(@"path/to/file.txt")
                .Select(s => s.Split('\t'))
                .ToArray();

// Your dictionary
Dictionary<string, string> stations = new Dictionary<string, string>();

// Loop through the array and add the key/value pairs to the dictionary
for (int i = 0; i < lines.Length; i++)
{
    // For example lines[i][0] = ABW, lines[i][1] = Abbey Wood
    stations[lines[i][0]] = lines[i][1];
}

// Prove it works
foreach (KeyValuePair<string, string> entry in stations)
{
    MessageBox.Show(entry.Key + " - " + entry.Value);
}