C# чтение строки из текстового файла, разделение и вставка в строку табуляции - PullRequest
0 голосов
/ 05 мая 2020

Я застрял в написании какой-то простой программы, которая записывает некоторые данные в текстовый файл и позже считывает их из этого файла.

У меня есть функция, которая записывает строки в текстовый файл; каждая строка содержит имя, фамилию и номер идентификатора.

И ниже у меня есть функция, которая считывает данные из этого файла.

Я хочу разделить имя, фамилию и номер идентификатора, поэтому код ниже, кажется быть правильным, но во время отладки я получил сообщение «Произошло необработанное исключение типа 'System.NullReferenceException'» для этой строки: string[] tabstring = myString.Split(' ', ' ');.

Я создал строку табуляции, которая содержит 3 элемента - каждый для каждого слова в строке, например, tabstring [0] = Name и т. д.

while l oop - это делать для каждой строки в текстовом файле. Но что-то не так.

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();
        }

А вот как выглядит текстовый файл:

Ann Brown 1233456789
Bruce Willis 098987875
Bill Gates 789678678

и так далее ...

Буду признателен за ваши комментарии по описанной проблеме.

Ответы [ 3 ]

0 голосов
/ 05 мая 2020

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

ReadLine () - считывает строку символов из текущего потока и возвращает данные в виде строки.

В вашем коде вы это делаете нулевую проверку, но затем снова вызовите ReadLine. Когда вы нажмете последнюю строку, вы получите строку NULL, и разделение не удастся с NULL ref

0 голосов
/ 05 мая 2020

while (srListOfObjects.ReadLine().. читает строку, но не сохраняет ее в переменную. string myString= (srListOfObjects.ReadLine()) читает еще одну строку.

Используйте while (!srListOfObjects.EndOfStream) для проверки конца потока: Свойство StreamReader.EndOfStream .

Также , рекомендуется проверить, что правильное количество частей строки было получено с помощью Split - он защищает от таких вещей, как строки, содержащие только пробелы.

Такие вещи, как StreamReaders, должны иметь .Dispose (). их, чтобы очистить «неуправляемые ресурсы» - простой способ сделать то, что будет работать даже в случае сбоя программы, - это использовать оператор using.

Если вы сделаете ReadFromFile в функцию вместо void, тогда вы можете избежать (без каламбура) использования глобальной переменной для данных. Глобальные переменные не обязательно являются проблемой, но обычно их лучше избегать.

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();

        }
    }
}

выходы:

1233456789 - Браун, Энн
98987875 - Уиллис, Брюс
789678678 - Гейтс, Билл

0 голосов
/ 05 мая 2020

Ваша проблема здесь:

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

Вы вводите l oop при условии, что srListOfObjects.ReadLine() возвращает что-то отличное от null, но тогда вы сразу же читаете форму новой строки srListOfObjects и сохранение возвращенной ссылки в myString. Очевидно, это имеет две проблемы:

  1. Второй вызов ReadLine может вернуть null, и вы не проверяете, есть ли это. По этой причине вы получаете сообщение об ошибке.
  2. Вы теряете информацию. Вы игнорируете строку, которую читаете, проверяя условие while. Пока ваша программа не выйдет из строя или не завершится (в зависимости от того, имеет ли входной файл четное или нечетное количество строк), вы будете обрабатывать только половину данных.

Обновление: Вы должны читать только одну строку за итерацию. Один из способов сделать это - объявить и инициализировать myString перед вводом l oop и обновлять его на каждой итерации:

var myString = srListOfObjects.ReadLine();

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