/// <summary> /// Loads and parses a csv file. /// </summary> /// <returns>Task.</returns> public async Task ParseCSVFile() { try { EnableControls = false; OnStatusUpdated("Reading CSV file..."); Scrobbles.Clear(); using (ITextFieldParser parser = _parserFactory.CreateParser(CSVFilePath)) { parser.SetDelimiters(Settings.Default.CSVDelimiters.Select(x => new string(x, 1)).ToArray()); string[] fields = null; List <string> errors = new List <string>(); ObservableCollection <ParsedCSVScrobbleViewModel> parsedScrobbles = new ObservableCollection <ParsedCSVScrobbleViewModel>(); await Task.Run(() => { while (!parser.EndOfData) { try { fields = parser.ReadFields(); string dateString = fields[Settings.Default.TimestampFieldIndex]; // check for 'now playing' if (dateString == "" && ScrobbleMode == CSVScrobbleMode.Normal) { continue; } DateTime date = DateTime.Now; if (!DateTime.TryParse(dateString, out date)) { bool parsed = false; // try different formats until succeeded foreach (string format in _formats) { parsed = DateTime.TryParseExact(dateString, format, CultureInfo.CurrentCulture, DateTimeStyles.None, out date); if (parsed) { break; } } if (!parsed && ScrobbleMode == CSVScrobbleMode.Normal) { throw new Exception("Timestamp could not be parsed!"); } } // try to get optional parameters first string album = fields.ElementAtOrDefault(Settings.Default.AlbumFieldIndex); string albumArtist = fields.ElementAtOrDefault(Settings.Default.AlbumArtistFieldIndex); string duration = fields.ElementAtOrDefault(Settings.Default.DurationFieldIndex); TimeSpan time = TimeSpan.FromSeconds(Duration); TimeSpan.TryParse(duration, out time); DatedScrobble parsedScrobble = new DatedScrobble(date.AddSeconds(1), fields[Settings.Default.TrackFieldIndex], fields[Settings.Default.ArtistFieldIndex], album, albumArtist, time); ParsedCSVScrobbleViewModel vm = new ParsedCSVScrobbleViewModel(parsedScrobble, ScrobbleMode); vm.ToScrobbleChanged += ToScrobbleChanged; parsedScrobbles.Add(vm); } catch (Exception ex) { string errorString = "CSV line number: " + parser.LineNumber + ","; foreach (string s in fields) { errorString += s + ","; } errorString += ex.Message; errors.Add(errorString); } } }); if (errors.Count == 0) { OnStatusUpdated("Successfully parsed CSV file. Parsed " + parsedScrobbles.Count + " rows"); } else { OnStatusUpdated("Partially parsed CSV file. " + errors.Count + " rows could not be parsed"); if (MessageBox.Show("Some rows could not be parsed. Do you want to save a text file with the rows that could not be parsed?", "Error parsing rows", MessageBoxButtons.YesNo) == DialogResult.Yes) { SaveFileDialog sfd = new SaveFileDialog() { Filter = "Text Files|*.txt" }; if (sfd.ShowDialog() == DialogResult.OK) { File.WriteAllLines(sfd.FileName, errors.ToArray()); } } } Scrobbles = parsedScrobbles; } } catch (Exception ex) { Scrobbles.Clear(); OnStatusUpdated("Error parsing CSV file: " + ex.Message); } finally { EnableControls = true; } }
/// <summary> /// Loads and parses a csv file. /// </summary> /// <param name="path">Path of the csv file to load.</param> private async void LoadCSVFile(string path) { try { EnableControls = false; OnStatusUpdated("Reading CSV file..."); CSVFilePath = path; Scrobbles.Clear(); TextFieldParser parser = new TextFieldParser(CSVFilePath); parser.HasFieldsEnclosedInQuotes = true; parser.SetDelimiters(","); string[] fields = new string[0]; List<string> errors = new List<string>(); await Task.Run(() => { while (!parser.EndOfData) { try { // csv should be "Artist, Album, Track, Date" fields = parser.ReadFields(); if (fields.Length != 4) throw new Exception("Parsed row has wrong number of fields!"); DateTime date = DateTime.Now; string dateString = fields[3]; // check for 'now playing' if (fields[3] == "" && ScrobbleMode == CSVScrobbleMode.Normal) continue; if (DateTime.TryParse(dateString, out date)) { } else { bool parsed = false; // try different formats until succeeded foreach (string format in Formats) { parsed = DateTime.TryParseExact(dateString, format, CultureInfo.CurrentCulture, DateTimeStyles.None, out date); if (parsed) break; } if (!parsed && ScrobbleMode == CSVScrobbleMode.Normal) throw new Exception("Timestamp could not be parsed!"); } CSVScrobble parsedScrobble = new CSVScrobble(fields[0], fields[1], fields[2], date.AddSeconds(1)); ParsedCSVScrobbleViewModel vm = new ParsedCSVScrobbleViewModel(parsedScrobble, ScrobbleMode); vm.ToScrobbleChanged += ToScrobbleChanged; _dispatcher.Invoke(() => Scrobbles.Add(vm)); } catch (Exception ex) { string errorString = "CSV line number: " + parser.LineNumber + ","; foreach (string s in fields) { errorString += s + ","; } errorString += ex.Message; errors.Add(errorString); } } }); if (errors.Count == 0) OnStatusUpdated("Successfully parsed CSV file. Parsed " + Scrobbles.Count + " rows"); else { OnStatusUpdated("Partially parsed CSV file. " + errors.Count + " rows could not be parsed"); if (MessageBox.Show("Some rows could not be parsed. Do you want to save a text file with the rows that could not be parsed?", "Error parsing rows", MessageBoxButtons.YesNo) == DialogResult.Yes) { SaveFileDialog sfd = new SaveFileDialog(); sfd.Filter = "Text Files|*.txt"; if (sfd.ShowDialog() == DialogResult.OK) File.WriteAllLines(sfd.FileName, errors.ToArray()); } } } catch (Exception ex) { Scrobbles.Clear(); OnStatusUpdated("Error parsing CSV file: " + ex.Message); } finally { EnableControls = true; } }