/// <summary> /// Saves this <see cref="CsvTable"/> on disk with the specified path and with compression /// if specified. /// </summary> /// <param name="path">Path of the .csv to save to.</param> /// <param name="compression">Whether to compress the file or not.</param> /// /// <exception cref="ArgumentNullException"><paramref name="path"/> is null.</exception> /// <exception cref="ArgumentException"> /// <paramref name="compression"/> is not either <see cref="CsvTableCompression.Compressed"/> or <see cref="CsvTableCompression.Uncompressed"/> /// </exception> /// <exception cref="ObjectDisposedException"><see cref="CsvTable"/> object was disposed.</exception> public void Save(string path, CsvTableCompression compression) { if (_disposed) { throw new ObjectDisposedException(null, "Cannot access CsvTable object because it was disposed."); } if (path == null) { throw new ArgumentNullException("path"); } if (compression < CsvTableCompression.Compressed || compression > CsvTableCompression.Uncompressed) { throw new ArgumentException("Unexpected compression type.", "compression"); } // Write column names. var builder = new StringBuilder(); for (int i = 0; i < Table.Columns.Count - 1; i++) { builder.Append(Columns[i].ColumnName + ","); } builder.AppendLine(Columns[Columns.Count - 1].ColumnName); // Write column types. for (int i = 0; i < Table.Columns.Count; i++) { // Append "\r\n"(new line) if last in array else append ",". var format = i == Table.Columns.Count - 1 ? "{0}\r\n" : "{0},"; var dataType = Table.Columns[i].DataType; if (dataType == typeof(int)) { builder.AppendFormat(format, "int"); } else { builder.AppendFormat(format, dataType.Name); } } // Write all rows. for (int i = 0; i < Table.Rows.Count; i++) { builder.AppendLine(string.Join(",", Table.Rows[i].ItemArray)); } // Compress it if specified. if (compression == CsvTableCompression.Compressed) { using (var inStream = new MemoryStream(Encoding.UTF8.GetBytes(builder.ToString()))) using (var outStream = (MemoryStream)CompressInternal(inStream)) { File.WriteAllBytes(path, outStream.ToArray()); } } else if (compression == CsvTableCompression.Uncompressed) { File.WriteAllText(path, builder.ToString()); } }
/// <summary> /// Reads the specified .csv file from a byte array and decompresses it if specified. /// </summary> /// <param name="bytes">Bytes of the .csv file.</param> /// <param name="compression">Whether the .csv file is compressed or not.</param> /// <exception cref="ArgumentNullException"><paramref name="bytes"/> is null.</exception> /// <exception cref="CsvException">Unexpected data type in CSV table.</exception> /// <exception cref="ObjectDisposedException"><see cref="CsvTable"/> object was disposed.</exception> public void Load(byte[] bytes, CsvTableCompression compression) { CheckDisposed(); if (bytes == null) { throw new ArgumentNullException("bytes"); } var stream = new MemoryStream(bytes); LoadInternal(stream, compression); }
/// <summary> /// Reads the specified .csv file from disk and decompresses it if specified. /// </summary> /// <param name="path">Path to the .csv file.</param> /// <param name="compression">Compression kind of the table.</param> /// <exception cref="ArgumentNullException"><paramref name="path"/> is null.</exception> /// <exception cref="CsvException">Unexpected data type in CSV table.</exception> /// <exception cref="ObjectDisposedException"><see cref="CsvTable"/> object was disposed.</exception> public void Load(string path, CsvTableCompression compression) { CheckDisposed(); if (path == null) { throw new ArgumentNullException("path"); } var fileStream = new FileStream(path, FileMode.Open); LoadInternal(fileStream, compression); }
/// <summary> /// Initializes a new instance of the <see cref="CsvTable"/> class and decompresses /// the specified .csv file if compressed, then reads file and parses it. /// </summary> /// <param name="path">Path to the .csv file.</param> /// <param name="compression">Compression kind of the table.</param> /// <exception cref="ArgumentNullException"><paramref name="path"/> is null.</exception> /// <exception cref="CsvException">Unexpected data type in CSV table.</exception> public CsvTable(string path, CsvTableCompression compression) { if (path == null) { throw new ArgumentNullException("path"); } _disposed = false; // Set file name without the extension as the table name. var tableName = Path.GetFileNameWithoutExtension(path); _table = new DataTable(tableName); var fileStream = new FileStream(path, FileMode.Open); LoadInternal(fileStream, compression); }
// Loads the specified CSV file stream and compression kind, into the DataTable. private void LoadInternal(Stream stream, CsvTableCompression compression) { // Detect compression if it compression is to Auto. if (compression == CsvTableCompression.Auto) { compression = DetectCompression(stream); } // If we detected that the CSV file is compressed or it was already specified, // we decompress it. if (compression == CsvTableCompression.Compressed) { var newStream = DecompressInternal(stream); stream.Seek(0, SeekOrigin.Begin); // Just in case uncompressed data is smaller than compressed data. stream.SetLength(newStream.Length); newStream.CopyTo(stream); } // stream will be disposed as well when reader is disposed. using (var reader = (TextReader) new StreamReader(stream)) { stream.Seek(0, SeekOrigin.Begin); var strTable = ParseTable(reader); // First row of CSV files are the property names. var rowNames = strTable[0]; if (rowNames == null) { throw new CsvException("CSV file does not contain the names row, that is, the first row."); } // Second row of the CSV files are the property types. var rowTypes = strTable[1]; if (rowTypes == null) { throw new CsvException("CSV file does not contain the types row, that is, the second row."); } // Width of table is determined by the first row. var tableWidth = rowNames.Length; // Set the columns of the DataTable according the first and second row SetColumns(rowNames, rowTypes); // i = 2, because we want to skip the first 2 rows. for (int i = 2; i < strTable.Length; i++) { // Raw string row from the file. var row = strTable[i]; // DataRow that we'll add to the Table. var tableRow = Table.NewRow(); Table.Rows.Add(tableRow); for (int j = 0; j < row.Length; j++) { var column = row[j]; // If the string is null (should not happen) or empty, // we set its table value to be DBNull.Value. if (string.IsNullOrEmpty(column)) { tableRow[j] = DBNull.Value; } else { tableRow[j] = column; } } } } }