34

I have my following code to read values from CSV file and do some processing. I would like to skip the first row of the input CSV file as it contains header text but I'd want to add it back after the processing is done.

List<string> values = new List<string>();
using (StreamReader sr = new StreamReader(filePath))
{
    while (sr.Peek() != -1)
    {
        string line = sr.ReadLine();
        List<string> lineValues = line.Split(',').ToList();
        var tempMinInt = 1;
        var tempValue = 1;
        var tempValInt = Convert.ToInt32(lineValues[4]);
        if (lineValues[3] == "1876")
        {
            if (tempValInt % 60 != 0)
            {
                tempMinInt = (tempValInt / 60) + 1;
                tempValue = tempMinInt * 30;
            }
            else
            {
                tempMinInt = tempValInt / 60;
                tempValue = tempMinInt * 30;
            }
        }
        else if (lineValues[3] == "1875")
        {
            if (tempValInt != 0)
            {
                tempValue = 500;
            }
            else
                tempValue = 0;
        }

        if (lineValues[3] == "1876")
        {
            values.Add(string.Join(",", lineValues) + "," + "0" + "," + "30" + "," + tempValue.ToString());
        }
        else if (lineValues[3] == "1875")
        {
            values.Add(string.Join(",", lineValues) + "," + "1" + "," + "500" + "," + tempValue.ToString());
        }

    }
}

Sample input csv looks like this:

id, datetime, msisdn, num, duration
33083,2011-12-19 05:17:57+06:30,98590149,1875,258
33084,2011-12-19 05:22:28+06:30,98590149,1875,69
33085,2011-12-19 05:23:45+06:30,98590149,1875,151
33086,2011-12-19 05:30:21+06:30,98590149,1875,58
33087,2011-12-19 06:44:19+06:30,949826259,1875,66

And I'd like to have my output like this:

id, datetime, msisdn, num, duration, type, ammount, total
33083,2011-12-19 05:17:57+06:30,98590149,1875,258,1,500,500
33084,2011-12-19 05:22:28+06:30,98590149,1875,69,1,500,500
33085,2011-12-19 05:23:45+06:30,98590149,1875,151,1,500,500
33086,2011-12-19 05:30:21+06:30,98590149,1875,58,1,500,500

6 Answers 6

82

Just read it first before you get into the loop. I'd do this:

using (StreamReader sr = new StreamReader(filePath))
{
    string headerLine = sr.ReadLine();
    string line;
    while ((line = sr.ReadLine()) != null)
    {
         ...
    }
}

(I don't like using Peek, personally.)

Then when you write out the output, start with headerLine.

As of C# 7, pattern matching makes this more pleasant:

using (StreamReader sr = new StreamReader(filePath))
{
    string headerLine = sr.ReadLine();
    while (sr.ReadLine() is string line)
    {
          ...
    }
}
Sign up to request clarification or add additional context in comments.

5 Comments

I rarely, if ever use Peek, but just curious...why don't you like using Peek?
@Justin: I tend to worry that there's a possibility of the data changing when you next read it - it feels cleaner to "read once and act" than to "read, check, then read again" and assume that the two reads will have the same results. It's entirely possible that the buffering details of whatever abstraction is in use (StreamReader in this case) can guarantee the result of Peek is consistent with the next read, but it feels cleaner not to have to worry about that.
Downvoting this because gdoron's suggestion below of not allocating a variable is so much less disturbing than having a dangling variable and I want his response to rise.
@ChuckNeuros: That's a choice, I guess... I've added in a nicer version (IMO) using pattern matching, although that still introduces the variable into the parent scope. Personally I'm less bothered by that than something that genuinely makes a difference at execution time (calling Peek and then ReadLine) but each to their own. I'd be very surprised to see enough votes cast on answers to a 12-year-old question to change the answer order though...
@JonSkeet ROFL... Yeah, and I'm not sure how my answer is "better", it's just a matter of style and taste.
23

Just read the first line and do nothing with it...

List<string> values = new List<string>();
using (StreamReader sr = new StreamReader(filePath))
{
    sr.ReadLine();
    while (sr.Peek() != -1)
    {
        string line = sr.ReadLine();
        List<string> lineValues = line.Split(',').ToList();

        //***//
    }
}

1 Comment

Oh yes this is so much more pleasant than having a pointless variable allocated!!! More upvotes, please. Even if the compiler is smart enough to instantly destroy it, having an unused variable is ugly and confusing.
6

Something like this:

bool isFirst=true;
using (StreamReader sr = new StreamReader(filePath))
{
    while (sr.Peek() != -1)
    {
        if(isFirst)
        {
            isFirst=false;
            continue;
        }
    }
}

Comments

2

I recommend, to use technique to handle such situation,

                int row = 0;
                using (StreamReader sr = new StreamReader(filePath))

                {
                   While(reader.Read()) //Each row of the file
                    {
                        row++;
                        if(row==1)
                        {
                            continue;
                        }
               }
... code..
}

Comments

1

You could read the first line before your while loop and store it, or you could use a counter / boolean field to check where in the file you are.

Comments

-1
When lineNumber is 1, it will skip the execution part and not process anything from first row.   


string doWork = string.Empty;

   var lineNumber = 1;

   using (StreamReader reader = new StreamReader(fileLocation))
            {
                while (!reader.EndOfStream)
                {
                    var line = reader.ReadLine();

                    var docLine = line.Split(',');

                    if (!String.IsNullOrEmpty(line.ToString()))
                    {
                        if (lineNumber != 0)
                        {
                            if (lineNumber > 1)
                            {
                                doWork = "Excecuting";
                            }
                        }
                        lineNumber++;
                    }
                }
            }

1 Comment

Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.