2015-11-29 73 views
2

我有一些C#代碼與文本文件一起工作,而且我似乎無法使用空白或空白(空白)行正常工作。如何正確處理C#中的空白行,空行或空行#

我的代碼:

 while (!file.EndOfStream) 
     { 
      line = file.ReadLine(); 

      bool isComment = (line[0] == '/') && (line[1] == '/'); 
      bool isPoint = (line[0] == '(') && (line[line.Length - 1] == ')'); 
      bool isWhiteSpace = string.IsNullOrEmpty(line); 

      Debug.Log("Comment: " + isComment + ", Point: " + isPoint + ", WhiteSpace: " + isWhiteSpace + "Value: '" + line + "'"); 

      if (!isComment && !isPoint && !isWhiteSpace) { Application.Quit(); } 
      else if (isPoint) 
      { 
       //Strip parenthesis 
       line = line.Remove(line.Length - 1, 1).Remove(0, 1); 

       //break into float array 
       string[] arr = line.Split(','); 

       float xVal = float.Parse(arr[0]); 
       float yVal = float.Parse(arr[1]); 
       float zVal = float.Parse(arr[2]); 

       Vector3 currentVector = new Vector3(xVal, yVal, zVal); 
       results.Add(currentVector); 
      } 
     } 

你可以看到,我正好是做事情的Vector3。如果該行是註釋行或空白行,我希望它什麼都不做。如果它注意到括號,我想讓它假設它是一個Vector3並解析它。最後,如果它不是這些的一條線,我希望它完全停止。這裏是我用記事本創建的示例文本文件:

//This is a comment 
// ... and so is this! 
(0, -1.5, 3) 
(1, 4, 1.23) 

(3, 5, 2) 

請注意,第二個和第三個Vector3之間存在間隙。在這種特殊情況下,該行完全是空的,它不包含空格或任何內容,我只是在記事本中按[Enter] [Enter]。當我的腳本到達這一行時,它似乎觸發了file.EndOfStream boolean ....但它不是文件的結尾!我怎樣才能解決這個問題?我的while循環有更合適的條件嗎?我也嘗試閱讀該行,並檢查它是否爲null,這是一種更爲流行的方法,但這種做法對我的情況並不起作用。

**注: 「文件」 是類型的StreamReader的變量**

+6

一個空字符串和一個完全由空白字符組成的字符串不是一回事。一個新行是一個空白字符,如果您想要檢查空字符串,空字符串或純粹空白字符串,請使用'string.IsNullOrWhitespace'。 –

+0

我認爲它不觸發file.EndOfStream,但它會引發異常,你只是用空的catch塊來吃那個異常。發生這種情況是因爲你首先檢查'line [0]',但如果行是空的,你超出範圍。如果性能不重要,您可以嘗試使用正則表達式。 –

+0

好吧,我不知道這....所以一個「空」行是這樣的:string line =「」; ?我認爲,如果你的定義成立,我永遠不應該在文件中得到一個空行,只有空白或空。我的想法是否正確? – Drifter64

回答

0

大衛是正確的。我正在接近索引超出範圍的例外。下面是我的修正和工作代碼:

 while (!file.EndOfStream) 
     { 
      line = file.ReadLine(); 

      bool isWhiteSpace = false; 
      bool isComment = false; 
      bool isPoint = false; 

      isWhiteSpace = string.IsNullOrEmpty(line); 

      if (!isWhiteSpace) 
      { 
       isComment = (line[0] == '/') && (line[1] == '/'); 
       isPoint = (line[0] == '(') && (line[line.Length - 1] == ')'); 
      } 
      Debug.Log("Comment: " + isComment + ", Point: " + isPoint + ", WhiteSpace: " + isWhiteSpace + "Value: '" + line + "'"); 

      if (!isComment && !isPoint && !isWhiteSpace) { Application.Quit(); } 
      else if (isPoint) 
      { 
       //Strip parenthesis 
       line = line.Remove(line.Length - 1, 1).Remove(0, 1); 

       //break into float array 
       string[] arr = line.Split(','); 

       float xVal = float.Parse(arr[0]); 
       float yVal = float.Parse(arr[1]); 
       float zVal = float.Parse(arr[2]); 

       Vector3 currentVector = new Vector3(xVal, yVal, zVal); 
       results.Add(currentVector); 
      } 
     } 
+0

您可能會將此內容發佈到代碼審查中以提供一些改進建議。 – usr

+0

我知道有一些低效率。我很高興找到更致命的問題。這不是生產代碼,而是供我個人使用的。 – Drifter64

+1

我建議利用CR來學習和個人發展。比改進一段代碼更重要。 – usr

2

這更多的是一種風格的注意,除了一個答案,雖然這也會阻止你看到的問題。

首先,StreamReader當您撥打ReadLine時,您將只在文件結束時收到null結果。你也不會在你的行首和行尾留意空白,大概也不關心完全是空白的行。所以,你可以用它來測試文件的末尾和空行是這樣的:

string line; 
while ((line = file.ReadLine()) != null) 
{ 
    line = line.Trim(); 
    if (line == "") 
     continue; 
} 

接下來你有開始/結束字符一些測試,仍然會導致在某些情況下的問題。具體而言,讀取只有一個字符的行中的第二個字符將導致異常。

而不是使用未經檢驗長度的字符串索引可以使用StartsWithEndsWith方法來做你的測試:

bool isComment = line.StartsWith("//"); 
bool isPoint = line.StartsWith("(") && line.EndsWith(")"); 

最後,在你的代碼解析點值,你認爲任何行以(開始,以)結束,其中至少有2個逗號,並且文本將正確解析。這是一個糟糕的假設。

更好的方式來處理這一切是檢測和處理每一個情況下,你走了,帶着突破至方法解析功能,你可以重複使用

這裏是我的版本:

public class Program 
{ 
    public static void Main() 
    { 
     List<Vector3> results = new List<Vector3>(); 
     using (var file = System.IO.File.OpenText(@"C:\temp\test.txt")) 
     { 
      string line; 
      while ((line = file.ReadLine()?.Trim()) != null) 
      { 
       // skip empty lines and comments 
       if (line == string.Empty || line.StartsWith("//")) 
        continue; 
       // parse all other lines as vectors, exit program on error 
       try 
       { 
        Vector3 vector = ParseVector(line); 
        results.Add(vector); 
       } 
       catch (FormatException e) 
       { 
        Console.WriteLine("Parse error on line: {0}", line); 
        throw; 
       } 
      } 
     } 

     foreach (var v in results) 
      Console.WriteLine("({0},{1},{2})", v.X, v.Y, v.Z); 
    } 

    // parse string in format '(x,y,z)', all as floats 
    // throws FormatException on any error 
    public static Vector3 ParseVector(string text) 
    { 
     if (!text.StartsWith("(") || !text.EndsWith(")")) 
      throw new FormatException(); 
     string[] parts = text.Substring(1, text.Length - 1).Split(','); 
     if (parts.Length != 3) 
      throw new FormatException(); 
     float x = float.Parse(parts[0]); 
     float y = float.Parse(parts[1]); 
     float z = float.Parse(parts[2]); 
     return new Vector3(x, y, z); 
    } 
} 

如果您不想使用異常,則可以返回null或使用TryParse方法使用的模式,返回布爾成功/失敗指示符並使用out參數將結果寫入。在這種情況下,我更喜歡例外。