2016-07-01 2 views
2

У меня есть консольное приложение C#, которое получает все файлы в каталоге. Принимая имя файла ниже в качестве примера, и учитывая, что у меня будет 3 строки, реф, Год1, YEAR2, как я мог бы сказать:получить файлы из каталога на основе подстроки имени файла - C#

Имя файла: 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)); 
    } 
} 
+0

См. Edit, dr является datareader – DarkW1nter

+3

ref является ключевым словом, поэтому я бы предложил предложить лучшее имя для этой переменной – Sorceri

ответ

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

Мне нравится 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); 
    } 
2

Если предположить, что ваши имена файлов всегда имеют формат, как в вашем сообщении, вы фи Сначала нужно разделить год на имя. Одним из возможных решений может быть:

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

, то вы можете использовать эту строку в вашем, если условие, чтобы попросить всех трех случаях:

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

Если sourceDir и targetDir не имеет \ в конце или filename в начале. Это сбой. Вы можете использовать

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

, чтобы избежать проблем

пс. вам следует избегать использования ref в качестве имени переменных в C#. зарезервировано как keyword

Смежные вопросы