Чтение текстового файла и получение строки со значениями даты

#c# #readfile

#c# #readfile

Вопрос:

Есть ли простой способ найти строки, состоящие из даты и времени.

Пока я могу прочитать текстовый файл, и мой следующий шаг — разобрать его, но перед этим, я думаю, мне нужно некоторое руководство, прежде чем я продолжу. Вот мой текущий сценарий чтения:

 List<string> Temp = new List<string>();            
string[] filePaths = Directory.GetFiles(@"C:\Temp\", "*.txt");

foreach (string files in filePaths)
{
    var fileStream = new FileStream(files, FileMode.Open, FileAccess.Read);
    using (var streamReader = new StreamReader(fileStream, Encoding.UTF8))
    {
        Temp.Add(streamReader.ReadToEnd());
    }
}

foreach (string i in Temp)
{
    if (i.Contains("Events"))
    {
        Console.WriteLine(i);        
    }
}
  

Вот образец текстового шаблона, который мне нужно проанализировать, сгенерированный с помощью инструмента.

 "[Output]"
"[Events]"
"Time"  "Duration"  "Severity"  "Event" "Text1" "Text2"


"[Acquisition Settings_1]"
"Data Set"  "DataSet1"
"Data Stream"   "Data"


"[Scan Data (Pressures in Torr)]"
"Time"  "Scan"  "Mass 1"    "Mass 2"    "Mass 3"    
"10/25/2018 4:59:27 PM" 1   5.5816e-008 1.3141e-008 -1.6109e-010    
"10/25/2018 4:59:35 PM" 2   5.5484e-008 1.3403e-008 6.9720e-010 
"10/25/2018 4:59:41 PM" 3   5.5633e-008 1.3388e-008 8.8094e-011 
"10/25/2018 4:59:48 PM" 4   5.7289e-008 1.2343e-008 1.4095e-010 
"10/25/2018 4:59:54 PM" 5   5.2841e-008 1.3219e-008 7.5257e-010 

"10/25/2018 4:59:57 PM" "After Calibration due to marginal data of daily pm3 rga checking"  
"10/25/2018 5:49:51 PM" "RGA Base Pressure
Flat pallet (2018-10-25_011_a1a)"   
"10/25/2018 6:21:53 PM" "PM3 SiNFILL_27A
2018-10-25_011_A4A" 
"10/25/2018 9:51:29 PM" "IBE1 STEP
FULL TAPE
NO PRE-BAKE"    
"10/25/2018 9:58:48 PM" "IBE2 STEP
  

И вот моя цель или ожидаемый результат — получить строку со значением datetime:

 "10/25/2018 4:59:27 PM" 1   5.5816e-008 1.3141e-008 -1.6109e-010    
"10/25/2018 4:59:35 PM" 2   5.5484e-008 1.3403e-008 6.9720e-010 
"10/25/2018 4:59:41 PM" 3   5.5633e-008 1.3388e-008 8.8094e-011 
"10/25/2018 4:59:48 PM" 4   5.7289e-008 1.2343e-008 1.4095e-010 
"10/25/2018 4:59:54 PM" 5   5.2841e-008 1.3219e-008 7.5257e-010 
  

Любое предложение TIA.

Комментарии:

1. (A) Что streamReader.ReadToEnd() делает? (Проверьте свои предположения, заглянув в документацию для StreamReader.ReadToEnd / TextReader.ReadToEnd) (B). Посмотрите, какие методы предоставляет System.IO.File класс (опять же, документация для этого класса даст вам обзор, а также подробную информацию о предоставляемых методах). Некоторые из них могут быть полезны для упрощения вашего кода. (C) Для обработки отдельных строк ознакомьтесь с тем, как вы можете определять строки даты и времени или когда они начинаются и заканчиваются (вы можете выполнять простые сравнения / нахождение строк или пытаться использовать сопоставление шаблонов строк с регулярными выражениями)

2. кажется, если вы разделите с помощью («) символа, вы можете получить строку формы даты в строке[1] . попробуйте / catch проанализировать как дату. если это успешно, сохраните во временной строке всю строку.

Ответ №1:

Вероятно, вы могли бы (ориентировочно) обойтись чем-то вроде этого шаблона. Он учитывает отрицательную расширенную нотацию, а также имеет вкладки в исходном формате (не показан в примере)

 ^""d /d /d  d :d :d  (AM|PM)""s -?d s d .?d e-d 
  

Примечание: Я не собираюсь писать объяснение регулярного выражения, поскольку оно слишком длинное.

Пример

 var pattern = @"^""d /d /d  d :d :d  (AM|PM)""s -?d s d .?d e-d ";
var regex = new Regex(pattern, RegexOptions.Compiled);

var filePaths = Directory.GetFiles(@"C:Temp", "*.txt");

var results = new List<string>();

foreach (var file in filePaths)
{
   var lines = File.ReadLines(@"D:sample.txt").Where(x => regex.IsMatch(x));
   results.AddRange(lines);
}
  

Однако, чтобы сделать еще один шаг вперед, вы могли бы сделать следующее. Это поместит все проанализированные данные в класс.

Дано

 public class ScanData
{
   public DateTime Time { get; set; }
   public int Scan { get; set; }
   public decimal?[] MassResults  { get; set; }

   public static ScanData FromString(string data)
   {
      var split = data.Split('t');

      decimal? Local(string value)
      {
         return decimal.TryParse(value, NumberStyles.Float, null, out var output) ? output : (decimal?)null;
      }

      var scanData = new ScanData()
                     {
                        Time = DateTime.ParseExact(split[0].Trim('"'), "M/d/yyyy h:m:s tt", null),
                        Scan = int.Parse(split[1]),
                        MassResults = split.Skip(2).Select(Local).ToArray()
                     };

      return scanData;
   }

}
  

Пример

 var pattern = @"^""d /d /d  d :d :d  (AM|PM)""s -?d s d .?d e-d ";
var regex = new Regex(pattern, RegexOptions.Compiled);

var filePaths = Directory.GetFiles(@"C:Temp", "*.txt");

var results = new List<ScanData>();

foreach (var file in filePaths)
{
   var lines = File.ReadLines(@"D:sample.txt")
                   .Where(x => regex.IsMatch(x))
                   .Select(x => ScanData.FromString(x));
   results.AddRange(lines);
}
  

Комментарии:

1. Должен ли я сохранять это в виде строки в цикле чтения? Я не вижу никаких выходных данных из моего. Это потому, что я добавляю их в список, а затем зацикливаю его.

2. @Rockn’Roll привет, я не совсем уверен, о чем вы спрашиваете, однако я обновил пример, более соответствующий тому, что вы делаете.

3. Я попробовал предложенный вами код, но список возвращает мне систему. Коллекции. Generic.List`1[Система. Строка].

4. и если я собираюсь зациклить temp, это ничего мне не возвращает

5. могу ли я предоставить вам фактический текстовый файл? размер текстового файла составляет 102 мб. Я просто упрощаю свой образец содержимого, чтобы он соответствовал моему вопросу.