从csv中删除行

本文关键字:删除行 csv | 更新日期: 2023-09-27 18:11:34

我有两个csv文件。在第一个文件中,我有一个用户列表,在第二个文件中,我有一个重复用户列表。我试图删除第一个文件中等于第二个文件的行。

这是我目前为止的代码:

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);
            }

文件1示例:

Modify,ABAMA3C,Allpay - Free State - HO,09072701
Modify,ABCG327,Processing Centre,09085980

文件2示例:

Modify,ABAA323,Group HR Credit Risk & Finance
Modify,ABAB959,Channel Sales & Service,09071036

有什么建议吗?

谢谢。

从csv中删除行

您所要做的就是在下面的代码中更改以下文件路径,然后您将获得一个文件(文件1),其中没有来自文件2的重复用户。编写此代码的想法是,您想要易于理解的东西。当然,还有其他更优雅的解决方案,但我想让它尽可能地为您提供基本的解决方案:

(粘贴到程序的主方法中)

        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();

如果这不是家庭作业,而是一个生产的东西,你可以安装程序集,如果你放下你的骄傲,使用一个VB库,你将节省3个小时的生命:

有很多例外(CR/LF之间的逗号=合法的引号;不同类型的报价;等)这将处理excel将导出/导入的任何内容。

加载从程序中提取的'Person'类的示例代码:

    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

this来正确关闭流:

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);
        }
    }
}

关于删除或比较的真正逻辑的帮助,回答上面El Ronnoco的评论…

你需要关闭流或者使用using子句

sw.Close();
using(StreamWriter sw = new StreamWriter(@"c:'test3.txt"))

您可以使用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);
    }
}
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();
    }
}