【问题标题】:Having trouble with the .Split() method.Split() 方法有问题
【发布时间】:2012-04-15 05:27:44
【问题描述】:

这段代码抛出异常,“索引超出了数组的范围”。这不应该简单地将每个拆分数据添加到指定的数组槽中吗?

while (input != null)
{
    string[] splitInput = inputLine.Split();
    EmpNum = int.Parse(splitInput[0]);
    EmpName = (splitInput[1]);
    EmpAdd = (splitInput[2]);
    EmpWage = double.Parse(splitInput[3]);
    EmpHours = double.Parse(splitInput[4]);
    inputLine = (myFile.ReadLine());
    Console.WriteLine("test {0},{1},{2}", EmpNum, EmpWage, EmpHours);
}

为了澄清一点,我正在从一个包含员工数据(姓名、地址、工作时间、员工编号、工资)的简单文本文件中读取数据。

为了清楚起见,我添加了整个主要方法。

using System;
using System.IO;

class Program
{
static void Main()
{

    //declare an array of employees
    Employee[] myEmployees = new Employee[10];

    //declare other variables
    string inputLine;
    string EmpName;
    int EmpNum;
    double EmpWage;
    double EmpHours;
    string EmpAdd;

    //declare filepath
    string environment =            System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal) + "\\";

    //get input
    Console.Write("\nEnter a file name in My Documents: ");
    string input = Console.ReadLine();
    string path = environment + input;
    Console.WriteLine("Opening the file...");

    //read file
    StreamReader myFile = new StreamReader(path);
    inputLine = (myFile.ReadLine());

    //split input
    while (inputLine != null)
    {

        string[] splitInput = inputLine.Split();
        EmpNum = int.Parse(splitInput[0]);
        EmpName = (splitInput[1]);
        EmpAdd = (splitInput[2]);
        EmpWage = double.Parse(splitInput[3]);
        EmpHours = double.Parse(splitInput[4]);
        Console.WriteLine("test {0},{1},{2}", EmpNum, EmpWage, EmpHours);
    }

    Console.ReadLine();
}//End Main()
}//End class Program

【问题讨论】:

  • 另外,如果需要任何其他信息,我可以发布更多我的代码。
  • 当你拆分 inputLine 时,你得到的元素少于 5 个
  • 不应该是while (input != null) 而应该是while (inputLine != null)
  • 另外,当抛出异常时,您可以查看堆栈跟踪并查看它发生的代码行 - 通常这会很快告诉您出了什么问题..

标签: c# arrays split


【解决方案1】:

也许这个版本会获得额外的荣誉 :) 说真的,虽然我不想在这里炫耀 - 只是即使它是一个学习示例,如果你找到一份工作并被赋予编写代码的任务例如,读取 CSV 文件时,您不希望它崩溃并让您看起来很糟糕,因此您可以帮自己一个忙,了解一些使其更健壮的步骤。

注意 - 这并不是试图就编写示例代码的完美方式展开辩论 - 只是试图展示一些我知道有用的技巧。希望对您有所帮助。

            StreamReader myFile = new StreamReader("TextFile1.txt");
            int lineNumber = 0;
            while (!myFile.EndOfStream)
            {
                // Read the next line.
                string inputLine = myFile.ReadLine();
                lineNumber++;

                // Extract fields line.
                string[] splitInput = inputLine.Split();

                // Make sure the line has the correct number of fields.
                if (splitInput.Length == 5)
                {
                    // Parse and validate each field.

                    if (!int.TryParse(splitInput[0], out EmpNum))
                    {
                        Console.WriteLine("could not parse int " + splitInput[0] + " on line " + lineNumber);
                        continue;
                    }

                    EmpName = (splitInput[1]);

                    EmpAdd = (splitInput[2]);

                    if(!double.TryParse(splitInput[3], out EmpWage))
                    {
                        Console.WriteLine("could not parse double " + " on line " + lineNumber);
                        continue;
                    }

                    EmpHours = double.Parse(splitInput[4]);

                    if (!double.TryParse(splitInput[4], out EmpHours))
                    {
                        Console.WriteLine("could not parse double: " + " on line " + lineNumber);
                        continue;
                    }

                    // Output
                    Console.WriteLine("test {0},{1},{2}", EmpNum, EmpWage, EmpHours);
                }
                else
                {
                    Console.WriteLine("Expecting 5 items from split opertation but got " + splitInput.Length  + " on line " + lineNumber);
                }
            }
            myFile.Close();

TextFile1.txt

1 2 3 4 5
6 7 8 f9 10
11 12

程序输出

test 1,5,5
could not parse double:  on line 2
Expecting 5 items from split opertation but got 2 on line 3

【讨论】:

    【解决方案2】:

    您有一行没有包含足够的项目。在读取项目之前检查数组的长度:

    string[] splitInput = inputLine.Split();
    if (splitInput.Length >= 5) {
      EmpNum = int.Parse(splitInput[0]);
      EmpName = (splitInput[1]);
      EmpAdd = (splitInput[2]);
      EmpWage = double.Parse(splitInput[3]);
      EmpHours = double.Parse(splitInput[4]);
    } else {
      // not enough items - show an error message or something
    }
    

    此外,您正在检查 where 中的变量 input 而不是 inputLine,但这不是您得到错误的原因。如果你读到文件的末尾,当你尝试在拆分中使用空引用时,你会得到一个空引用异常。

    【讨论】:

      【解决方案3】:

      检查您的字符串,您可能没有在输入中获得 5 个元素并在拆分方法中提供一些字符

      如果您用逗号分隔元素,请将inputLine.Split() 更改为inputLine.Split(',')

      您的输入将是“第一”、“第二”、“第三”、“第四”、“第五”

      【讨论】:

      • 我开始意识到我的错误。好的。所以我创建了一个名为“Employee”的类,并创建了一个包含 10 个这些员工对象的数组。我真正需要做的是从这个文件中读取数据并将引用存储在这个员工对象数组中。希望这可以解决问题。
      • 在文件中重复此模式并制作 5 行“第一”、“第二”、“第三”、“第四”、“第五”然后读取文件以供输入您可以在此处找到如何从文件中读取msdn.microsoft.com/en-us/library/ms228592(v=vs.80).aspx
      【解决方案4】:

      在拆分输入后在行中添加一个断点,然后您可以将鼠标悬停在结果数组上并单击加号。这样您就可以准确地看到数据是如何被拆分的。如果存在会导致拆分的隐藏字符 (\n,\t,\r),这将特别有用。

      【讨论】:

        【解决方案5】:

        你有几个问题。第一个问题是Split()。您需要将inputLine.Split() 更改为inputLine.Split(',')。现在您正在调用 System.String.Split(params char[]) 的重载,并且由于您没有指定要拆分的任何字符,因此它将返回整个字符串。

        其他问题(作为一名 CS 学生),您应该真正致力于命名约定和错误检查。代码相当脆弱,很容易崩溃。您应该尽早开始学习良好的软件工程实践和编写高质量的代码。

        using (FileStream fstream = new FileStream("path", FileMode.Open))
        using (StreamReader reader = new StreamReader(fstream)) {
            string line;
        
            while (!reader.EndOfStream && (line = reader.ReadLine()) != null) {
                string[] data = line.Split(',');
        
                if (data.Length < 5) {
                    // You will have IndexOutOfRange issues
                    continue; // skip processing the current loop
                }
        
                int employeeNumber;
                string employeeName;
                string employeeAddress;
                double employeeWage;
                double employeeHours;
        
                // Will be used to check validity of fields that require parsing into a type.
                bool valid;
        
                valid = int.TryParse(data[0], out employeeNumber);
        
                if (!valid) {
                    // employee number is not parsable
                }
        
                employeeName = data[1];
                employeeAddress = data[2];
        
                valid = double.TryParse(data[3], out employeeWage);
        
                if (!valid) {
                    // employee wage is not parsable
                }
        
                valid = double.TryParse(data[4], out employeeHours);
        
                if (!valid) {
                    // employee hours are not parsable
                }
            }
        }
        

        【讨论】:

        • 另外,你能解释一下有效的布尔值吗?感谢您的回答!
        • 检查畸形数据。如果您的数据格式错误,double.Parse 将引发异常。假设您的数据文件意外包含- 字符(在输入 0 后很常见)。 double.Parse 会失败并抛出异常。解决方案是使用double.TryParse,如果输入成功转换为double,则返回true,否则如果出现错误(您的数据格式错误)则返回false。这可以防止抛出异常,并允许您在代码中优雅地处理问题。
        【解决方案6】:

        1) input 不应该是 inputLine 吗?

        2)在使用之前为每个数组元素添加一个空检查。

        我也猜,

        while (input != null)
            {
                string[] splitInput = inputLine.Split();
                EmpNum = int.Parse(splitInput[0]);
                EmpName = (splitInput[1]);
                EmpAdd = (splitInput[2]);
                EmpWage = double.Parse(splitInput[3]);
                EmpHours = double.Parse(splitInput[4]);
                inputLine = (myFile.ReadLine());
                Console.WriteLine("test {0},{1},{2}", EmpNum, EmpWage, EmpHours);
            }
        

        应该是

        while (input != null)
            {
                inputLine = (myFile.ReadLine());
                string[] splitInput = inputLine.Split();
                EmpNum = int.Parse(splitInput[0]);
                EmpName = (splitInput[1]);
                EmpAdd = (splitInput[2]);
                EmpWage = double.Parse(splitInput[3]);
                EmpHours = double.Parse(splitInput[4]);
        
                Console.WriteLine("test {0},{1},{2}", EmpNum, EmpWage, EmpHours);
        

        }

        首先使用inputLine = (myFile.ReadLine());从文件中读取,然后进行拆分操作...

        3) 正如@Aaron Anodide 所建议的,添加长度检查应该可以解决问题..

        类似..

        inputLine = (myFile.ReadLine());
        string[] splitInput = inputLine.Split();
        if(splitInput!=null && splitInput.length ==5)
        {
         EmpNum = int.Parse(splitInput[0]);
                EmpName = (splitInput[1]);
                EmpAdd = (splitInput[2]);
                EmpWage = double.Parse(splitInput[3]);
                EmpHours = double.Parse(splitInput[4]);
                Console.WriteLine("test {0},{1},{2}", EmpNum, EmpWage, EmpHours);
        }
        

        【讨论】:

        • 在拆分操作后在答案中添加对数组长度的检查,您感觉如何?我认为这对海报很有帮助......
        • 检查数组中的空值根本没有帮助。数组中永远不会有任何空值。
        • @Guffa:你的意思是数组还是数组元素?如果您指的是splitInput!=null,那么我添加它只是为了在使用该物业之前更安全。如果您指的是数组元素,那么如果文件中的一行仅包含3个元素,那么其他元素不会为空吗?
        • @ShashankKadne:我的意思是:"2)在使用之前为每个数组元素添加一个空检查。"如果一行只包含 3 个项目,那么你会得到一个包含三个项目的数组,数组中没有添加额外的空项。另外,在拆分之前检查字符串的长度也没有帮助,您必须在拆分后检查数组的长度。
        • 空值检查是在到达文件末尾时停止读取数据
        猜你喜欢
        • 2011-03-25
        • 2018-07-23
        • 1970-01-01
        • 1970-01-01
        • 2015-08-28
        • 1970-01-01
        • 2017-10-20
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多