csv - dopisywanie w kolejnej linii

0

Witam, mam klasę która zapisuje dane do pliku CSV.
Nie potrafię zmodyfikować tego kodu tak aby dopisywał nowe dane w kolejnej linii.
Na tą chwilę dane są zapisane od początku.```

wywołanie

                        var export = new CsvExport();
                        export.AddRow();
                        export["KOD"] = parsDanychzWiersz_tmp2[0];
                        export["NR"] = parsDanychzWiersz_tmp2[1];
                        DateTime thisDay = DateTime.Today;
                        export["Date Opened"] = thisDay;
                        export.ExportToFile("aa.csv");

klasa

        public class CsvExport
        {

            public char delim = ';';
            /// <summary>
            /// To keep the ordered list of column names
            /// </summary>
            List<string> fields = new List<string>();

            /// <summary>
            /// The list of rows
            /// </summary>
            List<Dictionary<string, object>> rows = new List<Dictionary<string, object>>();

            /// <summary>
            /// The current row
            /// </summary>
            Dictionary<string, object> currentRow { get { return rows[rows.Count - 1]; } }

            /// <summary>
            /// Set a value on this column
            /// </summary>
            public object this[string field]
            {
                set
                {
                    // Keep track of the field names, because the dictionary loses the ordering
                    if (!fields.Contains(field)) fields.Add(field);
                    currentRow[field] = value;
                    //Console.WriteLine(field);
                }
            }

            /// <summary>
            /// Call this before setting any fields on a row
            /// </summary>
            public void AddRow()
            {
                rows.Add(new Dictionary<string, object>());
            }

            /// <summary>
            /// Converts a value to how it should output in a csv file
            /// If it has a comma, it needs surrounding with double quotes
            /// Eg Sydney, Australia -> "Sydney, Australia"
            /// Also if it contains any double quotes ("), then they need to be replaced with quad quotes[sic] ("")
            /// Eg "Dangerous Dan" McGrew -> """Dangerous Dan"" McGrew"
            /// </summary>
            string MakeValueCsvFriendly(object value)
            {
                if (value == null) return "";
                if (value is INullable && ((INullable)value).IsNull) return "";
                if (value is DateTime)
                {
                    if (((DateTime)value).TimeOfDay.TotalSeconds == 0)
                        return ((DateTime)value).ToString("yyyy-MM-dd");
                    return ((DateTime)value).ToString("yyyy-MM-dd HH:mm:ss");
                }
                string output = value.ToString();
                if (output.Contains(delim) || output.Contains("\""))
                    output = '"' + output.Replace("\"", "\"\"") + '"';
                if (Regex.IsMatch(output, @"(?:\r\n|\n|\r)"))
                    output = string.Join(" ", Regex.Split(output, @"(?:\r\n|\n|\r)"));
                return output;
            }

            /// <summary>
            /// Output all rows as a CSV returning a string
            /// </summary>
            public string Export()
            {
                StringBuilder sb = new StringBuilder();

                // The header
                foreach (string field in fields)
                    sb.Append(field).Append(delim);
                sb.AppendLine();

                // The rows
                foreach (Dictionary<string, object> row in rows)
                {
                    
                    foreach (string field in fields)
                        sb.Append(MakeValueCsvFriendly(row[field])).Append(delim);
                        sb.AppendLine();
                }

                return sb.ToString();
            }

            /// <summary>
            /// Exports to a file
            /// </summary>
            public void ExportToFile(string path)
            {
                File.WriteAllText(path, Export());
            }

            /// <summary>
            /// Exports as raw UTF8 bytes
            /// </summary>
            public byte[] ExportToBytes()
            {
                return Encoding.UTF8.GetBytes(Export());

            }

        }
1

CSV to lista wartości oddzielonych przecinkiem (comma separated values), pozycje listy oddzielone są znakami nowej linii.
U Ciebie separatorem jest średnik, jednocześnie nie sprawdzasz, że wartości zawierają takie średniki.
Zamieniasz znaki nowej linii na spacje, a więc zmieniasz zapisywaną treść. Standard CSV obsługuje znaki nowej linii w wartościach.
Ignorujesz strefę czasową w dacie.
currentRow rzuci wyjątkiem, jeśli nie ma wpisów, czy to działa tak celowo?
Metoda ExportToFile, komentarz "Exports to a file". Serio? Po co komentarze, które nic nie wnoszą?
parsDanychzWiersz_tmp2 - wtf? Mieszanie polskiego z angielskim, pełnych słów ze skrótami, składni camel case ze składnią z podkreśleniami, używanie numerów w zmiennych... Zaprzestań. Nazwij to splittedUserInput.
Na koniec najciekawsze - lista wartości nie przewiduje czegoś takiego, jak klucz (inny niż indeks). Rozumiem, że to Twoja wersja, ale to już nie jest CSV, bo ten format nie przewiduje nagłówków, więc stosując Twój algorytm nie wczytasz prawidłowo "zwykłego" pliku CSV. Idąc dalej - wrzucasz klucze do słownika, przy czym pozwalasz na dodawanie wierszy z różnymi nazwami pól (np. pierwszy wiersz - nazwa "A", wartość "B", drugi wiersz nazwa "a", wartość "b"), więc przy zapisie do pliku będziesz mieć wyjątek, bo będziesz się odwoływać do nieistniejącego pola w pierwszym wierszu ("a"). Wyrzuć te słowniki i użyj listy list, a pierwszy wiersz niech definiuje wszystkie możliwe pola, albo obsłuż opcję różnych pól dla różnych wierszy nadając im puste wartości. To drugie jest słabe, bo przy odczycie będziesz mieć inne dane niż te przy zapisie (czyli wiersz nie miał danej kolumny przy zapisie, a po odczycie będzie już ją mieć z pustą wartością).

Jeśli to Twój kod, to dlaczego nie umiesz go użyć? IMHO będzie wyglądało to tak:

export.AddRow();
export["ta klasa"] = "ssie";
export.AddRow();
export["ta klasa"] = "ssie koszmarnie";

albo

Enumerable.Range(1, 100).ForEach(i => { export.AddRow(); export["indeks"] = i; export["ta klasa"] = "śmierdzi"; });

Nazwy kluczy dla każdego wiersza muszą być identyczne.

0

Dzięki za wyczerpującą odpowiedź.
Poprawiam to po kimś, a nie jestem programista C#, a muszę to dostosować do działania.

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