/// <summary> /// Loads the specified stream in the CSV-like UTF8 format it was written by the <see cref="Save(Stream)"/> method. /// </summary> /// <param name="stream">The stream.</param> /// <returns>The loaded index from the specified stream.</returns> public static VideoSeekIndex Load(Stream stream) { var separator = new[] { ',' }; var trimQuotes = new[] { '"' }; var result = new VideoSeekIndex(null, -1); using (var reader = new StreamReader(stream, Encoding.UTF8, true)) { var state = 0; while (reader.EndOfStream == false) { var line = reader.ReadLine()?.Trim() ?? string.Empty; if (state == 0 && line == SectionHeaderText) { state = 1; continue; } if (state == 1 && line == SectionHeaderFields) { state = 2; continue; } if (state == 2 && !string.IsNullOrWhiteSpace(line)) { var parts = line.Split(separator, 2); if (parts.Length >= 2) { if (int.TryParse(parts[0], out var index)) { result.StreamIndex = index; } result.MediaSource = parts[1] .Trim(trimQuotes) .ReplaceOrdinal("\"\"", "\""); } state = 3; } if (state == 3 && line == SectionDataText) { state = 4; continue; } if (state == 4 && line == SectionDataFields) { state = 5; continue; } if (state == 5 && !string.IsNullOrWhiteSpace(line)) { if (VideoSeekIndexEntry.FromCsvString(line) is VideoSeekIndexEntry entry) { result.Entries.Add(entry); } } } } return(result); }