2012-08-03 80 views
0

我有一個文件是保存爲文本文件的SQL Server結果集。使用C#從文本文件中提取字段名稱和最大長度

這裏的文件是什麼樣子的樣本:

RWS_DMP_ID  RV1_DMP_NUM  CUS_NAME 
3192   3957    THE ACME COMPANY       
3192   3957    THE ACME COMPANY       
3192   3957    THE ACME COMPANY 

我想創建一個C#程序,讀取這個文件,並創建數據如下表:

 Field  MaxSize 
    -----  ------- 
RWS_DMP_ID 17 
RV1_DMP_NUM 17 
CUS_NAME 42 

這是字段名稱及其最大長度的列表。最大長度是在下一個字段開始之前的空間字段的開始。

順便說一句,我不關心代碼的性能。這很少使用文件處理實用程序。

我解決了這個用下面的代碼:

objFile = new StreamReader(strPath + strFileName); 
      strLine = objFile.ReadLine(); 
      intLineCnt = 0; 
      while (strLine != null) 
      { 
       intLineCnt++; 

       if (intLineCnt <= 3) 
       {      
        if (intLineCnt == 1) 
        { 
         strWords = SplitWords(strLine); 
         intNumberOfFields = strWords.Length; 
         foreach (char c in strLine) 
         { 
          if (bolNewField == true) 
          { 
           bolFieldEnd = false; 
           bolNewField = false; 
          } 
          if (bolFieldEnd == false) 
          { 
           if (c == ' ') 
           { 
            bolFieldEnd = true; 
           } 
          } 
          else 
          { 
           if (c != ' ') 
           { 
            if (intFieldCnt < strWords.Length) 
            { 
             strProcessedData[intFieldCnt, 0] = strWords[intFieldCnt]; 
             strProcessedData[intFieldCnt, 1] = (intCharCnt - 1).ToString(); 
            } 
            intFieldCnt++; 
            intCharCnt = 1; 
            bolNewField = true; 
           } 
          } 
          if (bolNewField == false) 
          { 
           intCharCnt++; 
          } 
         } 
         strProcessedData[intFieldCnt, 0] = strWords[intFieldCnt]; 
         strProcessedData[intFieldCnt, 1] = intCharCnt.ToString();        
        } 
        else if (intLineCnt == 3) 
        { 
         intLine2Cnt= 0; 
         intTotalLength = 0; 
         while(intLine2Cnt < intNumberOfFields) 
         { 
          intSize = Convert.ToInt32(strProcessedData[intLine2Cnt, 1]); 
          if (intSize + intTotalLength > strLine.Length) 
          { 
           intSize = strLine.Length - intTotalLength; 
          } 
          strField = strLine.Substring(intTotalLength, intSize); 
          strField = strField.Trim(); 
          strProcessedData[intLine2Cnt, intLineCnt - 1] = strField; 
          intTotalLength = intTotalLength + intSize + 1;         

          intLine2Cnt++; 
         } 
        }      
       } 
       strLine = objFile.ReadLine(); 
      }`enter code here` 

我知道,這個代碼是一個完整的破解工作。我正在尋找更好的方法來解決這個問題。

有沒有更好的方法來解決這個問題?

感謝

+0

yes!你需要將代碼分解成3部分。第一個進程/將數據加載到具有3個屬性文件的結構中,這裏是列。然後你可以使用LINQ按照事物分組。最後你必須保存結果。 – Ankush 2012-08-03 21:23:07

+0

@Ankush我只是想把這個分成三部分而頭痛。 – codingguy3000 2012-08-06 19:49:36

+0

我誤解了這個問題。我以爲你在做聚合。讓我想想... – Ankush 2012-08-06 19:53:41

回答

0

我不知道如何高效存儲,這是,但我認爲這是一個有點清潔(假設你的字段都是用製表符分隔):

var COL_DELIMITER = new[] { '\t' }; 
string[] lines = File.ReadAllLines(strPath + strFileName); 

// read the field names from the first line 
var fields = lines[0].Split(COL_DELIMITER, StringSplitOptions.RemoveEmptyEntries).ToList(); 

// get a 2-D array of the columns (excluding the header row) 
string[][] columnsArray = lines.Skip(1).Select(l => l.Split(COL_DELIMITER)).ToArray(); 

// dictionary of columns with max length 
var max = new Dictionary<string, int>(); 

// for each field, select all columns, and take the max string length 
foreach (var field in fields) 
{ 
    max.Add(field, columnsArray.Select(row => row[fields.IndexOf(field)]).Max(col => col.Trim().Length)); 
} 

// output per requirment 
Console.WriteLine(string.Join(Environment.NewLine, 
     max.Keys.Select(field => field + " " + max[field]) 
    )); 
+0

真的很慢的代碼。 – 2012-08-03 22:57:07

+0

@FengYuan是的,授予緩慢,但速度並不總是最重要的考慮因素。 – McGarnagle 2012-08-03 23:08:32

+0

在這種情況下,速度緩慢。 – codingguy3000 2012-08-06 21:00:08

0
void MaximumWidth(StreamReader reader) 
    { 
     string[] columns = null; 
     int[] maxWidth = null; 

     string line; 

     while ((line = reader.ReadLine()) != null) 
     { 
      string[] cols = line.Split('\t'); 

      if (columns == null) 
      { 
       columns = cols; 
       maxWidth = new int[cols.Length]; 
      } 
      else 
      { 
       for (int i = 0; i < columns.Length; i++) 
       { 
        int width = cols[i].Length; 

        if (maxWidth[i] < width) 
        { 
         maxWidth[i] = width; 
        } 
       } 
      } 
     } 

     // ... 
    } 
+0

它不是製表符分隔只是一堆空間。 – codingguy3000 2012-08-06 18:43:28

0

這裏是什麼我想出了。最重要的是使用IndexOf字符串函數。

class Program 
    { 
     static void Main(string[] args) 
     { 
      String strFilePath; 
      String strLine; 
      Int32 intMaxLineSize; 

      strFilePath = [File path and name];        
      StreamReader objFile= null; 

      objFile = new StreamReader(strFilePath); 

      intMaxLineSize = File.ReadAllLines(strFilePath).Max(line => line.Length); 

      //Get the first line 
      strLine = objFile.ReadLine(); 

      GetFieldNameAndFieldLengh(strLine, intMaxLineSize); 


      Console.WriteLine("Press <enter> to continue."); 
      Console.ReadLine(); 
     } 
     public static void GetFieldNameAndFieldLengh(String strLine, Int32 intMaxSize) 
     {    
      Int32 x;    
      string[] fields = null; 
      string[,] strFieldSizes = null; 
      Int32 intFieldSize; 

      fields = SplitWords(strLine); 


      strFieldSizes = new String[fields.Length, 2]; 
      x = 0; 

      foreach (string strField in fields) 
      { 
       if (x < fields.Length - 1) 
       { 
        intFieldSize = strLine.IndexOf(fields[x + 1]) - strLine.IndexOf(fields[x]);      
       } 
       else 
       { 
        intFieldSize = intMaxSize - strLine.IndexOf(fields[x]); 
       } 
       strFieldSizes[x, 0] = fields[x]; 
       strFieldSizes[x, 1] = intFieldSize.ToString(); 
       x++; 
      } 
      Console.ReadLine(); 


     } 

     static string[] SplitWords(string s) 
     { 
      return Regex.Split(s, @"\W+"); 
     } 
    } 
相關問題