Search code examples
c#asp.net-core-mvctext-parsing

Uploading and parsing a csv file in C#/Core MVC


I have the following code that I'm trying to use to parse a CSV file that is being uploaded:

private Dictionary<string, string[]> LoadData(IFormFile file) 
{
    // Verify that the user selected a file
    if (file != null && file.Length > 0) 
    {
        string wwwPath = this.environment.WebRootPath;
        // string contentPath = this.environment.ContentRootPath;

        string path = Path.Combine(wwwPath, "WeeklySchedules");

        if (!Directory.Exists(path)) 
        {
            Directory.CreateDirectory(path);
        }

        string fileName = Path.GetFileName(file.FileName);

        using (FileStream stream = new FileStream(Path.Combine(path, fileName), FileMode.Create)) 
        {
            file.CopyTo(stream);

            // System.Threading.Thread.Sleep(1000);
            using (TextFieldParser parser = new TextFieldParser(Path.Combine(path, fileName))) 
            {
                parser.TextFieldType = FieldType.Delimited;
                parser.SetDelimiters(",");

                Dictionary<string, string[]> parsedData = new Dictionary<string, string[]>();

                while (!parser.EndOfData) 
                {
                    // Process row
                    string[] fields = parser.ReadFields();
                    int count = 0;

                    if (count++ == 0) 
                    {
                        continue;
                    }

                    var pickup = fields[0]; 
                    var pickupDate = fields[1];
                    var dropoff = fields[2];
                    var dropoffDate = fields[3];
                    var driver = fields[7];

                    var pickupTime = DateTime.Parse(pickupDate).ToLongTimeString();
                    // string[] data = 
                }
            }
        }
    }

    return null;
}

You will note that I am passing the path to the uploaded stream to the parser, rather than the stream itself. I tried passing in the stream, but that doesn't work either. When I check in wwwroot/WeeklySchedules, the file is there. But when the parser gets to it, it comes back as empty. I even threw in a Sleep() to see if I was just hitting the file too soon. But that didn't make any difference.

I am getting some weird errors with the original stream, but the file is written, which is puzzling to me.

The errors are:

stream.ReadTimeout = 'stream.ReadTimeout' threw an exception of type 'System.InvalidOperationException'

stream.WriteTimeout = 'stream.WriteTimeout' threw an exception of type 'System.InvalidOperationException'

I've read through a bunch of blog posts and SO questions on the technique for loading/parsing a CSV file, but none of them indicate this as an issue.

Does anyone have any ideas?


Solution

  • Your first file stream is still open in your first using and you try to read it again with TextFieldParser

        private Dictionary<string, string[]> LoadData(IFormFile file)
        {
            // Verify that the user selected a file
            if (file != null && file.Length > 0)
            {
                string wwwPath = this.environment.WebRootPath;
                // string contentPath = this.environment.ContentRootPath;
    
                string path = Path.Combine(wwwPath, "WeeklySchedules");
    
                if (!Directory.Exists(path))
                {
                    Directory.CreateDirectory(path);
                }
    
                string fileName = Path.GetFileName(file.FileName);
    
                using (FileStream stream = new FileStream(Path.Combine(path, fileName), FileMode.Create))
                {
                    file.CopyTo(stream);
                }
    
                // System.Threading.Thread.Sleep(1000);
                using (TextFieldParser parser = new TextFieldParser(Path.Combine(path, fileName)))
                {
                    parser.TextFieldType = FieldType.Delimited;
                    parser.SetDelimiters(",");
    
                    Dictionary<string, string[]> parsedData = new Dictionary<string, string[]>();
    
                    while (!parser.EndOfData)
                    {
                        // Process row
                        string[] fields = parser.ReadFields();
                        int count = 0;
    
                        if (count++ == 0)
                        {
                            continue;
                        }
    
                        var pickup = fields[0];
                        var pickupDate = fields[1];
                        var dropoff = fields[2];
                        var dropoffDate = fields[3];
                        var driver = fields[7];
    
                        var pickupTime = DateTime.Parse(pickupDate).ToLongTimeString();
                        // string[] data = 
                    }
                }
            }
    
            return null;
        }