简体   繁体   English

C# 从文本文件中读取字符串,拆分并放入tabstring

[英]C# reading a string from text file, splitting and putting into tabstring

I got stuck writing some simple program which writes some data to the text file and reads them form this file later.我在编写一些简单的程序时遇到了困难,该程序将一些数据写入文本文件并稍后从该文件中读取它们。

I have a function that writes lines to a txt file;我有一个 function 将行写入 txt 文件; each line contains Name, Surname, and Idnumber.每行包含姓名、姓氏和身份证号码。

And below I have a function that reads the data from that file.下面我有一个 function 从该文件中读取数据。

I want to separate Name, Surname and Idnumber so below code seems to be correct but during debugging I got a message "An unhandled exception of type 'System.NullReferenceException' occurred" for this line: string[] tabstring = myString.Split(' ', ' ');我想将姓名、姓氏和身份证号码分开,所以下面的代码似乎是正确的,但在调试过程中,我收到一条消息“发生了此行的未处理的 'System.NullReferenceException' 类型的异常”: string[] tabstring = myString.Split(' ', ' '); . .

I created the tab string which contains 3 elements - each for each word in the line ie tabstring[0]=Name and so on.我创建了包含 3 个元素的选项卡字符串 - 每个元素对应于行中的每个单词,即 tabstring[0]=Name 等等。

The while loop is to do it for each line in the text file. while循环是对文本文件中的每一行执行此操作。 But something is wrong.但有些不对劲。

public void ReadFromFile()
        {
           FileStream fsListOfObjects = new FileStream("C:\\Users\\Dom\\Desktop\\ListOfObjects.txt", 
           FileMode.Open);
            StreamReader srListOfObjects = new StreamReader(fsListOfObjects);

            while (srListOfObjects.ReadLine() != null)
            {
                string myString= (srListOfObjects.ReadLine();
                Console.WriteLine(myString);
                **string[] tabstring = myString.Split(' ', ' ');**

                Name = tabstring[0];
                Surname = tabstring[1];
                Id= long.Parse(tabstring[2]);
                ClassName object= new ClassName(Name, Surname, Id);
                myList.Add(object);
            }
            srListOfObjects.Close();

            Console.ReadLine();
        }

And here is what the text file looks like:这是文本文件的样子:

Ann Brown 1233456789
Bruce Willis 098987875
Bill Gates 789678678

and so on...等等...

I would appreciate your comments on the described problem.感谢您对所描述问题的评论。

Your problem is here:你的问题在这里:

while (srListOfObjects.ReadLine() != null)
{
    string myString= (srListOfObjects.ReadLine();

You are entering the loop on the condition that srListOfObjects.ReadLine() returns something other than null but then you are immediately reading a new line form srListOfObjects and storing the returned reference in myString .您正在进入循环,条件是srListOfObjects.ReadLine()返回null以外的内容,但随后您将立即读取新的行形式srListOfObjects并将返回的引用存储在myString中。 This has obviously two problems:这显然有两个问题:

  1. The second call to ReadLine can return null and you are not checking if it is.第二次调用ReadLine可以返回null并且您没有检查它是否是。 The error you are getting is due to this reason.您得到的错误是由于这个原因。
  2. You are losing information.你正在丢失信息。 You are ignoring the line you are reading when checking the while condition.在检查 while 条件时,您忽略了正在阅读的行。 Until your program crashes or runs to the end (depends on wether the input file has even or odd number of lines), you will process only half of the data.直到您的程序崩溃或运行到最后(取决于输入文件的行数是偶数还是奇数),您将只处理一半的数据。

Update: You should only read one line per iteration.更新:每次迭代您应该只阅读一行。 One way to do it is declaring and initializing myString before entering the loop and updating it on every iteration:一种方法是在进入循环之前声明和初始化myString并在每次迭代时更新它:

var myString = srListOfObjects.ReadLine();

while (myString != null)
{
    //do your stuff
    myString = srListOfObjects.ReadLine();
}

https://docs.microsoft.com/en-us/dotnet/api/system.io.streamreader.readline?view=netcore-3.1 https://docs.microsoft.com/en-us/dotnet/api/system.io.streamreader.readline?view=netcore-3.1

ReadLine() - Reads a line of characters from the current stream and returns the data as a string. ReadLine() - 从当前 stream 中读取一行字符并将数据作为字符串返回。

In your code you do a null check, but then call ReadLine again.在您的代码中,您执行 null 检查,然后再次调用 ReadLine。 When you hit the last line, you will get a NULL string, and splitting that will fail with the NULL ref当您点击最后一行时,您将得到一个 NULL 字符串,并且拆分将失败并使用 NULL 参考

while (srListOfObjects.ReadLine().. reads a line but doesn't save it into a variable. string myString= (srListOfObjects.ReadLine()) reads another line. while (srListOfObjects.ReadLine()..读取一行但不将其保存到变量中。 string myString= (srListOfObjects.ReadLine())读取另一行。

Use while (.srListOfObjects.EndOfStream) to check for the end of the stream: StreamReader.EndOfStream Property .使用while (.srListOfObjects.EndOfStream)检查 stream: StreamReader.EndOfStream 属性的结尾。

Also, it is a good idea to check that the correct number of parts of the string were obtained by the Split - it guards against things like lines with only whitespace.此外,检查拆分是否获得了正确数量的字符串部分是一个好主意 - 它可以防止诸如只有空格的行之类的事情。

Things like StreamReaders need have.Dispose() called on them to clear up "unmanaged resources" - an easy way to do that which will work even if the program crashes is to use the using statement. StreamReaders 之类的东西需要 have.Dispose() 调用它们以清除“非托管资源” - 一种简单的方法,即使程序崩溃也可以使用using语句。

If you make the ReadFromFile method into a function instead of a void then you can avoid (no pun) using a global variable for the data.如果您将ReadFromFile方法变成 function 而不是 void,那么您可以避免(无双关语)对数据使用全局变量。 Global variables are not necessarily a problem, but it's usually good to avoid them.全局变量不一定是问题,但通常最好避免它们。

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace ConsoleApp1
{

    public class ClassName
    {
        public string Name { get; set; }
        public string Surname { get; set; }
        public long Id { get; set; }

    }

    class Program
    {
        public static List<ClassName> ReadFromFile(string fileName)
        {
            var result = new List<ClassName>();

            using (var sr = new StreamReader(fileName))
            {
                while (!sr.EndOfStream)
                {
                    string line = sr.ReadLine();
                    var parts = line.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
                    if (parts.Count() == 3)
                    {
                        result.Add(new ClassName
                        {
                            Name = parts[0],
                            Surname = parts[1],
                            Id = long.Parse(parts[2])
                        });
                    }
                }
            }

            return result;

        }

        static void Main(string[] args)
        {
            string myFile = @"C:\temp\namesList.txt";
            var theList = ReadFromFile(myFile);

            foreach(var c in theList)
            {
                Console.WriteLine($"{c.Id} - {c.Surname}, {c.Name}");
            }

            Console.ReadLine();

        }
    }
}

outputs:输出:

1233456789 - Brown, Ann 1233456789 - 布朗,安
98987875 - Willis, Bruce 98987875 - 威利斯,布鲁斯
789678678 - Gates, Bill 789678678 - 盖茨,比尔

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM