Wczytanie pliku do RichTextBox z enterami

0

Chce wczytac plik .csv (moja mini baza danych) w taki sposób, żeby móc go później wrzucić do RichTextBox'a przy zachowaniu enterów. Bez enterów program hula super, ale gdy w pliku zrobie enter to dostaje błąd.

Metoda wczytywania pliku

 using (StreamReader sr = new StreamReader("recipes.csv"))
            {
                if (sr != null)
                {
                    while (!sr.EndOfStream)
                    {
                        var line = sr.ReadLine();
                        //var line = sr.ReadToEnd();
                        var values = line.Split(';');
                        Recipe r = new Recipe();
                        listOfRecipes.Add(r);
                        r.RecipeName = values[0];
                        r.Preparation = values[1];
                        r.ComponentsTable = values[2].Split(','); // tutaj dostaje błąd IndexOutOfRangeException was unhandled
                        r.Photo = values[3];
                        r.PreparationTime = values[4];
                    }
                }
            }
 

a tak wygląda plik:

NazwaPrzepisu2;Jakiś tam przepis sobie jest przykładowy2 //enter
dalsza czesc przepisu; skladnik10, skladnik20, skladnik30, skladnik40, skladnik50;images/potrawa2.jpg;okolo 60 minut;
NazwaPrzepisu3;Jakiś tam przepis sobie jest przykładowy3; skladnik6, skladnik7, skladnik8, skladnik9, skladnik10;images/potrawa3.jpg;15 minut;
 

Próbowałem coś w tym stylu, ale tez nie idzie...

 r.PreparationTable = values[1].Split(System.Environment.NewLine);
1

Łamanie linii pola w Twoim pliku jest niezgodne z dokumentacją formatu; Wartość pola, która zawarta jest w kilku liniach musi być opatrzona znakami " (choć wiele implementacji parserów plików tego formatu wcale tego nie wspiera); Do poczytania np. artykuł na wikipedii: Comma-separated values - basic rules and examples;

Co do kodu to niech wypowiedzą się znawcy C# (ja do nich nie należę).

1

A o co pytasz?
Czemu twój kod nie działa? Bo najpierw do line wczytujesz pierwszą linię tekstu, potem splitujesz ją do values co z pierwszej lini tekstu daje ci 2 wartości (1 separator), a później próbujesz odwołać się do 2'ego(3'ego) elementu values, który po prostu nie istnieje.

1

To oczywiste, że się program wywala. Skoro w linii pliku masz jeden średnik, to po użyciu metody Split w tabeli values będziesz miał tylko elementy na indeksach 0 i 1, a Ty próbujesz się odwołać do elementu na indeksie 2.
Po prostu nie możesz użyć metody Split do tego celu. Czytaj plik jako jeden string (a nie zbiór linii), i potem parsuj go licząc średniki. W końcu każdy przepis musi zawierać cztery średniki, prawda?

0
somekind napisał(a):

Czytaj plik jako jeden string (a nie zbiór linii), i potem parsuj go licząc średniki.

Okej, ale w jaki sposób to zrobić? Próbowałem przez ReadToEnd(), ale nic to nie daje :/ tak samo ReadAllLines :/

1
malymakar napisał(a):

Okej, ale w jaki sposób to zrobić? Próbowałem przez ReadToEnd(), ale nic to nie daje :/ tak samo ReadAllLines :/

ReadAllLines jak sama nazwa wskazuje wczytuje linie. Użyj lepiej ReadAllText.
A do parsowania przyda Ci się pewno jakaś pętla i umiejętne korzystanie z metody string.IndexOf, aby znajdować kolejne średniki.

0

Okej, działa mi już tak jak powinno tylko kwestia czy pod względem optymalności jest ok?

public static List<Recipe> ReadListOfRecipes1()
        {
            string str = File.ReadAllText("recipes.csv");

            int poczatek = 0, l = 0;
            string[] potrawa = new string[5];

            do
            {
                for (int i = 0; i < 5; i++)
                {
                    l = str.IndexOf(';', poczatek);
                    potrawa[i] = str.Substring(poczatek, l - poczatek);
                    poczatek = str.IndexOf(';', poczatek) + 1;
                }

                Recipe r = new Recipe();
                listOfRecipes.Add(r);
                r.RecipeName = potrawa[0];
                r.Preparation = potrawa[1];
                r.ComponentsTable = potrawa[2].Split(',');
                r.Photo = potrawa[3];
                r.PreparationTime = potrawa[4];
            }
            while (str.Length != l + 1);

            return listOfRecipes;
        }
3

Całkiem nieźle, jeśli mogę mieć jakieś uwagi to:

  1. Nie nazywaj zmiennej l! Nigdy! Ta literka jest zbyt podobna do 1, i to często utrudnia czytanie kodu.
  2. Mieszasz nazwy polskie (poczatek) z angielskimi (ReadListOfRecipes1), to nieładne.
  3. Nazwę pliku lepiej przekazać w argumencie metody, a nie wpisywać na stale.
  4. W pętli for dwa razy wykonujesz operację: str.IndexOf(';', poczatek). Chyba niepotrzebnie, ostatnią linijką w tej pętli mogłoby być po prostu: poczatek = l + 1.

1 użytkowników online, w tym zalogowanych: 0, gości: 1