2009-05-02 4 views
1

私は、テキストと数が少ないファイルを持っています。私はそれから数字を抽出したいだけです。私はそれについてどうやって行くのですか?ファイルから特定のデータを検索する

私はその分け前のものを使ってみましたが、今までは運がありませんでした。 私のファイルは、このようなものです:+ CMGL = "ALL" + CMGL AT

:5566、 "REC READ"、 "Ufone" 親愛なる顧客、あなたのDAY_BUCKETのサブスクリプションが02/05/09 +に期限切れになりますCMGL:5565、「REC READ」、「+ 923466666666」

は親切に私は別のファイルまたはテキストボックスにそれらを置くことができる私は、このファイルから923466666666 LIKE NUMBERSを抽出する方法を教えてください。

おかげ

+0

を使用してユニットテストを含める... –

答えて

1

ファイルがどれくらい大きいですか?ファイルのサイズが数MB未満の場合は、ファイルの内容を文字列にロードし、コンパイル済みの正規表現を使用して一致を抽出することをお勧めします。

ここでは簡単な例です:

Regex NumberExtractor = new Regex("[0-9]{7,16}",RegexOptions.Compiled); 

    /// <summary> 
    /// Extracts numbers between seven and sixteen digits long from the target file. 
    /// Example number to be extracted: +923466666666 
    /// </summary> 
    /// <param name="TargetFilePath"></param> 
    /// <returns>List of the matching numbers</returns> 
    private IEnumerable<ulong> ExtractLongNumbersFromFile(string TargetFilePath) 
    { 

     if (String.IsNullOrEmpty(TargetFilePath)) 
      throw new ArgumentException("TargetFilePath is null or empty.", "TargetFilePath"); 

     if (File.Exists(TargetFilePath) == false) 
      throw new Exception("Target file does not exist!"); 

     FileStream TargetFileStream = null; 
     StreamReader TargetFileStreamReader = null; 
     string FileContents = ""; 
     List<ulong> ReturnList = new List<ulong>(); 

     try 
     { 
      TargetFileStream = new FileStream(TargetFilePath, FileMode.Open); 
      TargetFileStreamReader = new StreamReader(TargetFileStream); 
      FileContents = TargetFileStreamReader.ReadToEnd(); 

      MatchCollection Matches = NumberExtractor.Matches(FileContents); 

      foreach (Match CurrentMatch in Matches) { 
       ReturnList.Add(System.Convert.ToUInt64(CurrentMatch.Value)); 
      } 

     } 
     catch (Exception ex) 
     { 
      //Your logging, etc... 
     } 
     finally 
     { 
      if (TargetFileStream != null) { 
       TargetFileStream.Close(); 
       TargetFileStream.Dispose(); 
      } 

      if (TargetFileStreamReader != null) 
      { 
       TargetFileStreamReader.Dispose(); 
      } 
     } 

     return (IEnumerable<ulong>)ReturnList; 


    } 

使用例:

List<ulong> Numbers = (List<ulong>)ExtractLongNumbersFromFile(@"v:\TestExtract.txt"); 
2

数字は行の最後にすべてあるなら、あなたは以下の

foreach (string line in File.ReadAllLines(@"c:\path\to\file.txt")) { 
    Match result = Regex.Match(line, @"\+(\d+)""$"); 
    if (result.Success) { 
    var number = result.Groups[1].Value; 
    // do what you want with the number 
    } 
} 
のようなコードを使用することができます
+0

はいすべての数字は行の最後です。 私はそれを試しましたが、 'in'のエラーが発生しました foreach文で型と識別子の両方が必要です もっと具体的に見てください:D –

+0

@Zeeshan、型なしで動作するように更新推論 – JaredPar

2

ここでは、String.Splitを使用した例を示します。 "number"には '+'が含まれているので、実際には数値ではなく文字列として扱う必要があります。私はそれが国際電話のために潜在的に使用される「+」という電話番号であると推測しています。電話番号の場合は、ダッシュや数字のスペース、末尾に追加された内線番号など、「+9234 666-66666 ext 235」などのように注意する必要があります。

とにかく - うまくいけば、この例はSplitを把握するのに便利です。

コード

は、正規表現を使用してのNUnit v2.4.8

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using NUnit.Framework; 
using System.Text.RegularExpressions; 

namespace SO.NumberExtractor.Test 
{ 
    public class NumberExtracter 
    { 
     public List<string> ExtractNumbers(string lines) 
     { 
      List<string> numbers = new List<string>(); 
      string[] seperator = { System.Environment.NewLine }; 
      string[] seperatedLines = lines.Split(seperator, StringSplitOptions.RemoveEmptyEntries); 

      foreach (string line in seperatedLines) 
      { 
       string s = ExtractNumber(line); 
       numbers.Add(s); 
      } 

      return numbers; 
     } 

     public string ExtractNumber(string line) 
     { 
      string s = line.Split(',').Last<string>().Trim('"'); 
      return s; 
     } 

     public string ExtractNumberWithoutLinq(string line) 
     { 
      string[] fields = line.Split(','); 
      string s = fields[fields.Length - 1]; 
      s = s.Trim('"'); 

      return s; 
     } 
    } 

    [TestFixture] 
    public class NumberExtracterTest 
    { 
     private readonly string LINE1 = "AT+CMGL=\"ALL\" +CMGL: 5566,\"REC READ\",\"Ufone\" Dear customer, your DAY_BUCKET subscription will expire on 02/05/09 +CMGL: 5565,\"REC READ\",\"+923466666666\""; 
     private readonly string LINE2 = "AT+CMGL=\"ALL\" +CMGL: 5566,\"REC READ\",\"Ufone\" Dear customer, your DAY_BUCKET subscription will expire on 02/05/09 +CMGL: 5565,\"REC READ\",\"+923466666667\""; 
     private readonly string LINE3 = "AT+CMGL=\"ALL\" +CMGL: 5566,\"REC READ\",\"Ufone\" Dear customer, your DAY_BUCKET subscription will expire on 02/05/09 +CMGL: 5565,\"REC READ\",\"+923466666668\""; 

     [Test] 
     public void ExtractOneLineWithoutLinq() 
     {    
      string expected = "+923466666666"; 

      NumberExtracter c = new NumberExtracter(); 
      string result = c.ExtractNumberWithoutLinq(LINE1); 

      Assert.AreEqual(expected, result);    
     } 

     [Test] 
     public void ExtractOneLineUsingLinq() 
     { 
      string expected = "+923466666666"; 

      NumberExtracter c = new NumberExtracter(); 
      string result = c.ExtractNumber(LINE1); 

      Assert.AreEqual(expected, result); 
     } 

     [Test] 
     public void ExtractMultipleLines() 
     { 
      StringBuilder sb = new StringBuilder(); 
      sb.AppendLine(LINE1); 
      sb.AppendLine(LINE2); 
      sb.AppendLine(LINE3); 

      NumberExtracter ne = new NumberExtracter(); 
      List<string> extractedNumbers = ne.ExtractNumbers(sb.ToString()); 

      string expectedFirst = "+923466666666"; 
      string expectedSecond = "+923466666667"; 
      string expectedThird = "+923466666668"; 

      Assert.AreEqual(expectedFirst, extractedNumbers[0]); 
      Assert.AreEqual(expectedSecond, extractedNumbers[1]); 
      Assert.AreEqual(expectedThird, extractedNumbers[2]); 
     } 
    } 
} 
+1

+1とユニットテストを含む答え! パブリックインターフェイスのList <>では常にIEnumerable <>を返します。http://stackoverflow.com/questions/271710/collectiont-versus-listt-what-should-you-use-on-your-interfaces –