根据文件名的子字符串从目录中获取文件 - C#

时间:2016-07-01 13:58:10

标签: c#

我有一个C#控制台应用程序,它可以获取目录中的所有文件。以下面的文件名为例,假设我有3个字符串,ref,year1,year2,我怎么能说:

文件名:31596_2015-06-30.pdf

给我所有文件名包含ref的文件和文件名包含年份1和年份2之间的年份? 代码到目前为止:

var files = Directory.EnumerateFiles(sourceDir, "*", SearchOption.TopDirectoryOnly)
                          .Select(Path.GetFileName);

string start_year = null;
string end_year = null;
string ref = null;

// dr is a sql data reader
if (dr.HasRows == true)
{
    while (dr.Read())
    {
        start_year = dr.GetString(1).Substring(7, 4);
        end_year = dr.GetString(2).Substring(7, 4);
        ref = dr.GetString(3);

        foreach(string filename in files)
        {
            if (filename.Contains(ref)) 
            {
                File.Copy(sourceDir + filename, targetDir + filename);
            }
        }

        File.Copy(sourceDir + dr.GetString(0), targetDir + dr.GetString(0));
    }
}

3 个答案:

答案 0 :(得分:3)

我建议提取一个类,比如FileData

public class FileData {
  public bool IsParsed {get; private set; }

  public String FileName {get; private set; }

  public DateTime Date {get; private set; }

  public String Ref {get; private set; }

  public FileData(String path) {
    FileName = path;

    if (String.IsNullOrEmpty(path))
      return;

    int p = path.IndexOf('_');

    if (p < 0)
      return;

    Ref = path.Substring(0, p);

    DateTime dt;

    IsParsed = DateTime.TryParseExact(path.Substring(p + 1), 
      "yyyy-MM-dd", 
      CultureInfo.InvariantCulture, 
      DateTimeStyles.None, 
     out dt);

    Date = dt;
  }
}

通过这样做,你可以放一个简单的 Linq 来获取文件

  var files = Directory
    .EnumerateFiles(sourceDir, "*", SearchOption.TopDirectoryOnly)
    .Select(file => new FileData(file))
    .Where(info => info.IsParsed)
    .Where(info => String.Equals(info.Ref, myRef))
    .Where(info => info.Date.Year >= year1 && info.Date.Year <= year2)
    .Select(info => info.FileName);

答案 1 :(得分:2)

假设您的文件名始终采用帖子中的格式, 你首先需要将年份分开。 一种可能的解决方案可能是:

 string filenameYear = filename.Split('_')[1].Split('-')[0];

然后您可以在if条件中使用此字符串来询问所有三种情况:

if (filename.Contains(_ref) &&
    Convert.ToInt32(filenameYear) > Convert.ToInt32(start_year) &&
    Convert.ToInt32(filenameYear) < Convert.ToInt32(end_year))
{
    // Do what ever you desire

}

在该行:

File.Copy(sourceDir + filename, targetDir + filename);

如果sourceDirtargetDir最后没有\或者开头是filename。这会崩溃。 你可以使用

File.Copy(Path.Combine(sourceDir,filename), Path.combine(targetDir, filename);

避免问题

PS。你应该避免使用ref作为C#中变量的名称。 它保留为keyword

答案 2 :(得分:1)

我喜欢Linq这样的事情。除非您知道读者中的值始终符合您的预期,否则您应该执行一些验证,但这将通过对示例代码进行最少的更改来实现您的既定目标。

    var start_year = (DateTime)dr.GetString(1).Substring(7, 4);
    var end_year = (DateTime)dr.GetString(2).Substring(7, 4);
    ref = dr.GetString(3);

    foreach(string filename in files.Where(x => x.StartsWith(ref) 
                    && (DateTime)x.Substring(7, 4) >= start_year 
                    && (DateTime)x.Substring(7, 4) <= end_year))
    {
        File.Copy(sourceDir + filename, targetDir + filename);
    }