Trishen
Trishen

Reputation: 237

c# Remove rows from csv

I have two csv files. In the first file i have a list of users, and in the second file i have a list of duplicate users. Im trying to remove the rows in the first file that are equal to the second file.

Heres the code i have so far:

StreamWriter sw = new StreamWriter(path3);
        StreamReader sr = new StreamReader(path2);

        string[] lines = File.ReadAllLines(path);

        foreach (string line in lines)
        {
            string user = sr.ReadLine();

            if (line != user) 
            {
                sw.WriteLine(line);

            }

File 1 example:

Modify,ABAMA3C,Allpay - Free State - HO,09072701

Modify,ABCG327,Processing Centre,09085980

File 2 Example:

Modify,ABAA323,Group HR Credit Risk & Finance

Modify,ABAB959,Channel Sales & Service,09071036

Any suggestions?

Thanks.

Upvotes: 3

Views: 9575

Answers (6)

KreepN
KreepN

Reputation: 8598

All you'd have to do is change the following file paths in the code below and you will get a file back (file one) without the duplicate users from file 2. This code was written with the idea in mind that you want something that is easy to understand. Sure there are other more elegant solutions, but I wanted to make it as basic as possible for you:

(Paste this in the main method of your program)

        string line;
        StreamReader sr = new StreamReader(@"C:\Users\J\Desktop\texts\First.txt");

        StreamReader sr2 = new StreamReader(@"C:\Users\J\Desktop\texts\Second.txt");

        List<String> fileOne = new List<string>();
        List<String> fileTwo = new List<string>();

        while (sr.Peek() >= 0)
        {
            line = sr.ReadLine();
            if(line != "")
            {
                fileOne.Add(line);
            }
        }
        sr.Close();
        while (sr2.Peek() >= 0)
        {
            line = sr2.ReadLine();
            if (line != "")
            {
                fileTwo.Add(line);
            }
        }
        sr2.Close();
        var t = fileOne.Except(fileTwo);

        StreamWriter sw = new StreamWriter(@"C:\Users\justin\Desktop\texts\First.txt");

        foreach(var z in t)
        {
            sw.WriteLine(z);
        }
        sw.Flush();

Upvotes: 4

user645280
user645280

Reputation:

using(var sw = new StreamWriter(path3))
using(var sr = new StreamReader(path))
{
    string []arrRemove = File.ReadAllLines(path2);
    HashSet<string> listRemove = new HashSet<string>(arrRemove.Count);
    foreach(string s in arrRemove)
    {
        string []sa = s.Split(',');
        if( sa.Count < 2 ) continue;
        listRemove.Add(sa[1].toUpperCase());
    }

    string line = sr.ReadLine();
    while( line != null )
    {
        string []sa = line.Split(',');
        if( sa.Count < 2 )
            sw.WriteLine(line);
        else if( !listRemove.contains(sa[1].toUpperCase()) )
            sw.WriteLine(line);
        line = sr.ReadLine();
    }
}

Upvotes: 0

FastAl
FastAl

Reputation: 6280

If this is not homework, but a production thing, and you can install assemblies, you'll save 3 hours of your life if you swallow your pride and use a piece of the VB library:

There are many exceptions (CR/LF between commas=legal in quotes; different types of quotes; etc.) This will handle anything excel will export/import.

Sample code to load a 'Person' class pulled from a program I used it in:

    Using Reader As New Microsoft.VisualBasic.FileIO.TextFieldParser(CSVPath)

        Reader.TextFieldType = Microsoft.VisualBasic.FileIO.FieldType.Delimited
        Reader.Delimiters = New String() {","}
        Reader.TrimWhiteSpace = True
        Reader.HasFieldsEnclosedInQuotes = True

        While Not Reader.EndOfData
            Try
                Dim st2 As New List(Of String)
                st2.addrange(Reader.ReadFields())
                If iCount > 0 Then ' ignore first row = field names
                    Dim p As New Person
                    p.CSVLine = st2
                    p.FirstName = st2(1).Trim
                    If st2.Count > 2 Then
                        p.MiddleName = st2(2).Trim
                    Else
                        p.MiddleName = ""
                    End If
                    p.LastNameSuffix = st2(0).Trim
                    If st2.Count >= 5 Then
                        p.TestCase = st2(5).Trim
                    End If
                    If st2(3) > "" Then
                        p.AccountNumbersFromCase.Add(st2(3))
                    End If
                    While p.CSVLine.Count < 15
                        p.CSVLine.Add("")
                    End While
                    cases.Add(p)
                End If
            Catch ex As Microsoft.VisualBasic.FileIO.MalformedLineException
                MsgBox("Line " & ex.Message & " is not valid and will be skipped.")
            End Try
            iCount += 1
        End While
    End Using

Upvotes: 2

Matthew Whited
Matthew Whited

Reputation: 22433

You can use LINQ...

class Program
{
    static void Main(string[] args)
    {
        var fullList = "TextFile1.txt".ReadAsLines();
        var removeThese = "TextFile2.txt".ReadAsLines();

        //Change this line if you need to change the filter results.
        //Note: this assume you are wanting to remove results from the first 
        //      list when the entire record matches.  If you want to match on 
        //      only part of the list you will need to split/parse the records 
        //      and then filter your results.
        var cleanedList = fullList.Except(removeThese);

        cleanedList.WriteAsLinesTo("result.txt");
    }
}
public static class Tools
{
    public static IEnumerable<string> ReadAsLines(this string filename)
    {
        using (var reader = new StreamReader(filename))
            while (!reader.EndOfStream)
                yield return reader.ReadLine();
    }

    public static void WriteAsLinesTo(this IEnumerable<string> lines, string filename)
    {
        using (var writer = new StreamWriter(filename) { AutoFlush = true, })
            foreach (var line in lines)
                writer.WriteLine(line);
    }
}

Upvotes: 0

Mohamed Abed
Mohamed Abed

Reputation: 5113

You need to close the streams or utilize using clause

sw.Close();

using(StreamWriter sw = new StreamWriter(@"c:\test3.txt"))

Upvotes: 0

Davide Piras
Davide Piras

Reputation: 44605

this to close the streams properly:

using(var sw = new StreamWriter(path3))
using(var sr = new StreamReader(path2))
{
    string[] lines = File.ReadAllLines(path);

    foreach (string line in lines)
    {
        string user = sr.ReadLine();

        if (line != user)
        {
            sw.WriteLine(line);
        }
    }
}

for help on the real logic of removal or compare, answer the comment of El Ronnoco above...

Upvotes: 0

Related Questions