Click here to Skip to main content
15,895,462 members
Articles / Desktop Programming / Windows Forms

Flexible CSV reader/writer with progress reporting

Rate me:
Please Sign up or sign in to vote.
5.00/5 (3 votes)
3 Aug 2011CPOL4 min read 34.6K   2.9K   38  
Flexible CSV reader/writer with progress reporting and many file format variations.
// Copyright © Transeric Solutions 2011.  All rights reserved.
// Licensed under Code Project Open License (see http://www.codeproject.com/info/cpol10.aspx).
// Author: Eric David Lynch.
using System;
using System.Data;
using System.ComponentModel;
using System.IO;
using Extended.IO.Csv;

namespace CsvTest
{
    /// <summary>
    /// A class for reading a CSV file and reporting progress.
    /// </summary>
    public class CsvFormReader : CsvFormBase
    {
        #region Constructors
        /// <summary>
        /// Constructor for CsvFormReader.
        /// </summary>
        /// <param name="worker">The background worker associated with this instance.</param>
        /// <param name="path">The path for the file.</param>
        /// <param name="hasHeader">A value indicating if the file has a header row.</param>
        /// <param name="endColumnChar">The character that indicates the end of a column.</param>
        public CsvFormReader(
            BackgroundWorker worker,
            string path,
            bool hasHeader,
            char endColumnChar)
            : base(worker, path, hasHeader, endColumnChar)
        {
            // Set text for this instance
            ProgressFormat = "Read {0:#,0} row{1} of file{2}";
            ErrorText = "Error reading file.";

            // Create a CSV reader
            reader = new CsvReader(path);

            // Set the end column character
            reader.EndColumnChar = EndColumnChar;

            // Hook up the RowEnd event
            reader.RowEnd += CsvFormBase_RowEnd;
        }
        #endregion // Constructors

        #region Private data
        /// <summary>
        /// The CSV reader associated with this instance.
        /// </summary>
        private CsvReader reader;

        /// <summary>
        /// The data table most recently read by this reader.
        /// </summary>
        private DataTable table;
        #endregion // Private data

        #region Public methods
        /// <summary>
        /// Get the data table most recently read by this reader.
        /// </summary>
        /// <returns>The data table most recently read by this reader.</returns>
        public DataTable GetTable()
        {
            // Remember the table
            DataTable table = this.table;

            // The caller is responsible for disposing of the table
            this.table = null;

            // Return the table
            return table;
        }

        /// <summary>
        /// Process the file.
        /// </summary>
        public override void ProcessFile()
        {
            // Perform base logic
            base.ProcessFile();

            try
            { // Try to read the table...
                // Read the table
                table = reader.ReadTable(HasHeader);
            } // Try to read the table...
            catch
            { // Catch any exceptions...
                // Dispose of the table and re-throw the exception
                Dispose(ref table);
                throw;
            } // Catch any exceptions...
        }
        #endregion // Public methods

        #region Protected methods
        /// <summary>
        /// Cancel processing by this instance.
        /// </summary>
        protected override void CancelAsync()
        {
            // Let the reader know to stop working
            reader.CancelAsync();
        }

        /// <summary>
        /// Calculate the percentage of progress.
        /// </summary>
        /// <returns>The percentage of progress.</returns>
        protected override int CalculatePercentProgress()
        {
            // Get the underlying stream for the reader
            Stream stream = (Stream)((StreamReader)reader.BaseReader).BaseStream;

            // Get the position and length of stream
            double position = stream.Position;
            double length = stream.Length;

            // Calculate the percentage
            double percent = length == 0D ? 100D : position / length * 100D;

            // Return the percentage
            return (int)percent;
        }
        #endregion // Protected methods

        #region IDisposable Members
        /// <summary>
        /// Dispose of the resources associated with this instance.
        /// </summary>
        public override void Dispose()
        {
            Dispose(ref table);
            Dispose(ref reader);
        }
        #endregion // IDisposable Members
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
United States United States
Eric is a Senior Software Engineer with 30+ years of experience working with enterprise systems, both in the US and internationally. Over the years, he’s worked for a number of Fortune 500 companies (current and past), including Thomson Reuters, Verizon, MCI WorldCom, Unidata Incorporated, Digital Equipment Corporation, and IBM. While working for Northeastern University, he received co-author credit for six papers published in the Journal of Chemical Physics. Currently, he’s enjoying a little time off to work on some of his own software projects, explore new technologies, travel, and write the occasional article for CodeProject or ContentLab.

Comments and Discussions