替换csv文件的数据/值

时间:2015-04-07 09:24:40

标签: c# .net linq file csv

我想计算一些字符串的数量并将其存储到csv文件中。我已经尝试过,但我不知道这是否正确,另外还有两个问题。

首先,这是我的方法:

public void CountMacNames(String macName)
{
    string path = @"D:\Counter\macNameCounter.csv";

    if (!File.Exists(path))
    {
        File.Create(path).Close();
    }

    var lines = File.ReadLines(path);

    foreach (var line in lines)
    {
        bool isExists = line.Split(',').Any(x => x == macName);

        if (isExists)
        {
            // macName exists, increment it's value by 1
        }
        else
        {
            // macName does not exists, add macName to CSV file and start counter by 1
            var csv = new StringBuilder();
            var newLine = string.Format("{0},{1}", macName, 1);
            csv.AppendLine(newLine);
            File.WriteAllText(path, csv.ToString());
        }
    }
}

第一个问题是这个IOException:

  

该进程无法访问文件' D:\ Counter \ macNameCounter.csv'   因为它正被另一个进程使用。

第二个问题是,如果csv文件中存在macName,我不知道如何将值递增1(参见第一条评论)

编辑:方法示例" CountMacNames"拨打:

  • CountMacNames(" Cansas&#34);
  • CountMacNames(" Wellback&#34);
  • CountMacNames("牛顿&#34);
  • CountMacNames(" Cansas&#34);
  • CountMacNames(" Princet&#34);

然后,CSV文件应包含:

  • Cansas,2
  • Wellback,1
  • 牛顿,1
  • Princet,1

4 个答案:

答案 0 :(得分:1)

好的,这就是我要做的事情:

public void CountMacNames(String macName)
{
    string path = @"D:\Counter\macNameCounter.csv";

    // Read all lines, but only if file exists
    string[] lines = new string[0];
    if (File.Exists(path))
        lines = File.ReadAllLines(path);

    // This is the new CSV file
    StringBuilder newLines = new StringBuilder();
    bool macAdded = false;

    foreach (var line in lines)
    {
        string[] parts = line.Split(',');
        if (parts.Length == 2 && parts[0].Equals(macName))
        {
            int newCounter = Convert.ToIn32(parts[1])++;
            newLines.AppendLine(String.Format("{0},{1}", macName, newCounter));
            macAdded = true;
        }
        else
        {
            newLines.AppendLine(line.Trim());
        }
    }

    if (!macAdded)
    {
        newLines.AppendLine(String.Format("{0},{1}", macName, 1));
    }

    File.WriteAllText(path, newLines.ToString());
}

此代码执行此操作:

  1. 只有文件存在时才读取所有行 - 否则我们会启动一个新文件
  2. 迭代所有行
  3. 如果2部分行的第一部分等于mac,则将1添加到计数器并将行添加到输出
  4. 如果第一部分不匹配或行格式错误,请将行添加到输出
  5. 如果我们在任何行中找不到mac,请为mac添加一个新行,并使用计数器1
  6. 将文件写回

答案 1 :(得分:0)

您需要读取文件并将其释放,如下所示,以避免IO异常:

 string[] lines = null;
 using (var sr = new System.IO.StreamReader(path))
    lines = sr.ReadToEnd().Split(new string[] {"\r", "\n"}, StringSplitOptions.RemoveEmptyEntries);

至于计数,您只需添加int值,也可以将方法返回类型更改为int

 public int CountMacNames(String macName, String path)
    {
        if (!File.Exists(path))
        {
            File.Create(path).Close();
        }

        string[] lines = null;
        using (var sr = new System.IO.StreamReader(path))
            lines = sr.ReadToEnd().Split(new string[] {"\r", "\n"}, StringSplitOptions.RemoveEmptyEntries);

        return lines.Where(p => p.Split(',').Contains(macName)).Count();
    }

并在调用它的方法内部:

 var path = @"<PATH TO FILE>";
 var cnt = CountMacNames("Canvas", path);
 if (cnt > 0)
 {
     using (var sw = new StreamWriter(path, true, Encoding.Unicode))
          sw.WriteLine(string.Format("Canvas,{0}", cnt));
 }

现在,var res = CountMacNames("Canvas","PATH");将返回2,并且“Canvas,2”或“Newton,1”这些行将被附加到文件中,而不会覆盖它。

答案 2 :(得分:0)

您无法同时读取和写入同一文件(以简单的方式)。 对于小文件,已有答案。

如果您的文件非常大(太大而无法容纳在内存中),则需要采用其他方法:

  1. 逐行读取输入文件
  2. 可以修改当前行
  3. 将行写入临时文件
  4. 如果已完成删除输入文件,则重命名临时文件

答案 3 :(得分:0)

对于第一个问题,您可以将所有行读入内存并在那里工作然后再将其全部写出来,或使用流。

using (FileStream fs = File.Open(filePath, FileMode.Create, FileAccess.ReadWrite)) 
{
    var sw = new StreamWriter(fs);
    var sr = new StreamReader(fs);
    while(!streamReader.EndOfStream)
    {
        var line = sr.ReadLine();
        //Do stuff with line.
        //...
        if (macExists)
        {
           //Increment the number, Note that in here we can only replace characters,
           //We can't insert extra characters unless we rewrite the rest of the file
           //Probably more hassle than it's worth but
           //You could have a fixed number of characters like 000001 or     1

           //Read the number as a string,
           //Int.Parse to get the number
           //Increment it
           //work out the number of bytes in the line.
           //get the stream position
           //seek back to the beginning of the line
           //Overwrite the whole line with the same number of bytes.
        }
        else
        {
            //Append a line, also harder to do with streams like this.
            //Store the current position,
            //Seek to the end of the file,
            //WriteLine
            //Seek back again.
        }
    }
}