2012-11-05 28 views
5

Bu teğet an earlier question of mine.Bir dosyayı normal bir ifade kullanarak okuyun.

ilişkilidir Esasen, bu söz konusu çözüm harika çalıştı, ancak şimdi çok daha büyük bir analizi uygulamasında çalışacak şekilde adapte gerekir. Sadece StreamReader.ReadToEnd()'u kullanmak kabul edilemez, çünkü okuyacağım bazı dosyalar çok, çok büyük. Bir hata olsaydı ve biri temizlemek istemediyse, teorik olarak gigabaytlar büyük olabilir. Açıkçası, bunun sonuna kadar okuyamıyorum.

Ne yazık ki, normal okuma satırları da kabul edilemez, çünkü okuduğum veri satırlarının bir kısmı yığın izleri içerdiğinden, bunların biçimlendirilmesinde açıkça /r/n kullanıyorlar. İdeal olarak, programın bir regex için eşleşene kadar ileri okumasını söylerim, o zaman geri döner. Bunu .net'de yapmak için herhangi bir işlevsellik var mı? Eğer değilse, yazmayı düşündüğüm için bazı önerilerde bulunabilir miyim?

Düzenleme: biraz daha kolay sorumu takip hale getirmek için, burada adapte kodun önemli parçalarından bazılarının bir macun var:

foreach (var fileString in logpath.Select(log => new StreamReader(log)).Select(fileStream => fileStream.ReadToEnd())) 
{ 
    const string junkPattern = @"\[(?<junk>[0-9]*)\] \((?<userid>.{0,32})\)"; 
    const string severityPattern = @"INFO|ERROR|FATAL"; 
    const string datePattern = "^(?=[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2},[0-9]{3})"; 
    var records = Regex.Split(fileString, datePattern, RegexOptions.Multiline); 
    foreach (var record in records.Where(x => string.IsNullOrEmpty(x) == false)) 
    ...... 

sorun forEach yatıyor. .Select(fileStream => fileStream.ReadToEnd()) hafızayı kötü bir şekilde patlatacak, sadece biliyorum. derleyici sizin için yapacak, ama bu sadece daha iyi kod okunabilmesi için, kendiniz yapılmalıdır -

+4

Ve işte bu gibi görevler için RegEx'i kullanmayı umursamamanın başlıca nedenlerinden biri var. Basit bir ayrıştırıcı yazdıysanız, yeni satırları işlemek için basitçe uyarlayabilirsiniz. –

+0

@JonathanWood Tüm kayıtlara sahip olduktan sonra regex'ler tek tek kayıtları ayrıştırmak için harika. Sadece ihtiyacım olan tüm bilgileri dışarı çıkarıyorum ve doğrudan ilgili alanlara gider. Sorun, bu durumda dosya girdisidir, sadece sahip olduğum dosya ile tek bir kayıt verebilecek kadar esnek değil gibi görünüyor. Ama bu sahte görünüyor, değil mi? Bu nadir bir sorun olamaz. – tmesser

+1

Yani yığın izi/r/n. Bu neden okuma çizgisini ortadan kaldırıyor? – Paparazzi

cevap

1

Öncelikle tüm, sınıf bildiriminde için const tanımını hareket etmelidir. @Blam belirtildiği gibi

, böyle çifti StringBuilder ve StreamReader.ReadLine şey kullanmalısınız: Ben senin sorun hakkında bir şeyler anlamadı ise yorumunda bu netleştirmek lütfen

foreach(var filePath in logpath) 
{ 
    var sbRecord = new StringBuilder(); 
    using(var reader = new StreamReader(filePath)) 
    { 
     do 
     { 
      var line = reader.ReadLine(); 
      // check start of the new record lines 
      if (Regex.Match(line, datePattern) && sbRecord.Length > 0) 
      { 
       // your method for log record 
       HandleRecord(sbRecord.ToString()); 
       sbRecord.Clear(); 
       sbRecord.AppendLine(line); 
      } 
      // if no lines were added or datePattern didn't hit 
      // append info about current record 
      else 
      { 
       sbRecord.AppendLine(line); 
      } 
     } while (!reader.EndOfStream) 
    } 
} 

.
Ayrıca, uygulamanızın hızı için hatlarınızın görevlerini zamanlamak için ThreadPool'u kullanabilirsiniz.

+0

Akışı düşük seviyeli bir şekilde ele alan kendi çözümümün şifresini çözdüm, çünkü standart bir belirteç olan bir metin akışını ayrıştıramayacağımı tamamen saçma hissettim. Bununla birlikte, temel olarak başka biri için bu, yapmanız gereken daha az şeydir. – tmesser

+0

@YYY Kodunuzu burada bulabilir misiniz, sadece kayıt için? Bence bu ilginç olurdu. – VMAtm

+0

Bunu yapmayı sevdiğim kadarıyla, yakında bazı bankacılık yazılımlarının bir parçası olacak ve bu yüzden de tescilli bir şirket olacak. Dedim ki, birkaç günlüğüne işten çıkınca gündemdeki şeylerden biri açık kaynak kodlu bir versiyon oluşturmak ve onu githubuma eklemek, böylece çözümü genişletebilirim. Şu anda olduğu gibi, temelde sabit sayıda bayt okuyor ve bir dosya pozisyonunu tutuyoruz; bu, projemizin bağlamında harika çalışıyor ancak iyi bir genel çözüm değil. İlk çalışmamı çoğaltır/sterilize ettikten ve bunu github'a ekledikten sonra bu hırs devam edecektir. – tmesser