2011-09-16 58 views
0

現在我通過幫助解決了這個問題後,在我創建的一個小文本文件中從兩個標記之間獲取文本,只用4行進行測試。現在我想創建一個新的文本文件,該文件將包含原始文件的內容,但在每個找到標籤之間的文本的地方我都想看到空格爲空字符串。所以,如果原來的文本文件看起來像現在這樣:indexof和substring的問題

daniel<Text>THISISOUTisthere</Text> 
<Text>hellobye</Text> 
<Text>danielTHISishereandnotthere</Text> 
danie <Text> is THIS here and not THERE</Text> 

因此,新的文件看起來想:

daniel<Text>    </Text> 
<Text>  </Text> 
<Text>       </Text> 
danie <Text>       </Text> 

下面是現在無法正常工作的代碼。我用一些幫助變量,但上線運行這段代碼時,我得到一個錯誤:

string hh = f.Substring(lastIndex, currentIndex); 

錯誤說:索引和長度必須引用位置的字符串中。 參數名:長度

這是完整的代碼,現在不工作:

private void test() 
     { 
      w = new StreamWriter(@"d:\testFile.txt"); 
      int currentLength; 
      int currentIndex; 
      int lastIndex = 0; 
      string startTag = "<Text>"; 
      string endTag = "</Text>"; 
      int startTagWidth = startTag.Length; 
      //int endTagWidth = endTag.Length; 
      index = 0; 
      while (true) 
      { 
       index = f.IndexOf(startTag, index); 
       if (index == -1) 
       { 
        break; 
       } 
       // else more to do - index now is positioned at first character of startTag  
       int start = index + startTagWidth; 
       currentIndex = start; 
       index = f.IndexOf(endTag, start+1); 
       if (index == -1) 
       { 
        break; 
       } 
       // found the endTag  
       string g = f.Substring(start, index - start - 1); 
       currentLength = index - start - 1; 
       string hh = f.Substring(lastIndex, currentIndex); 
       w.WriteLine(hh); 
       lastIndex = currentIndex + currentLength; 
       listBox1.Items.Add(g); 
      } 
     } 

請幫我這個代碼。

+6

**使用XML解析器**。 – SLaks

+0

或HTML解析器,如果你想允許怪癖HTML ... –

+0

@SLaks這將無法正常工作,該文件似乎不是有效的XML –

回答

1

子需要的長度作爲其第二個參數不是一個索引位置,它應該是

string hh = f.Substring(lastIndex, currentIndex-lastIndex); 

另外你斷斬波太多的字符,你想改變currentLength = index - start -1currentLength = index - start

最後使用Writeline將被puttin addtional換行,改爲使用Write

1

一個有趣的選擇,你可以使用正則表達式做替代你:

string input = "daniel<Text>THISISOUTisthere</Text>\n<Text>hellobye</Text>\n<Text>danielTHISishereandnotthere</Text>\ndanie <Text> is THIS here and not THERE</Text>"; 
Regex re = new Regex("(?<=<Text>).*?(?=</Text>)"); 
string output = re.Replace(input, m => new string(' ', m.Length)); 

Console.WriteLine(input); 
Console.WriteLine(); 
Console.WriteLine(output); 

程序輸出:

daniel<Text>THISISOUTisthere</Text> 
<Text>hellobye</Text> 
<Text>danielTHISishereandnotthere</Text> 
danie <Text> is THIS here and not THERE</Text> 

daniel<Text>    </Text> 
<Text>  </Text> 
<Text>       </Text> 
danie <Text>       </Text> 
0

另一個有趣的選擇,因爲我覺得我想試着讓它工作:一個小的自己動手的解析器。

注意:這遠遠不是一個真正的HTML或XML解析器!它只吸引一個標籤(例如<Text>)並且只有沒有任何屬性...

那麼,你需要什麼解析器?對,一個分詞器。在這裏你去:

static IEnumerable<Token> Tokenize(string input, string tag) 
{ 
    int index = 0; 
    int lastIndex = 0; 

    // Define the start and end tag and their common first character 
    char tagChar = '<'; 
    string startTag = tag + '>'; 
    string endTag = '/' + tag + '>'; 

    while (true) 
    { 
     Token token = null; 

     // Search for any new tag token 
     index = input.IndexOf(tagChar, index) + 1; 
     if (index <= 0) 
      break; 

     // Starttag or endtag token found 
     if (input.Substring(index, startTag.Length) == startTag) 
      token = new Token { Start = index - 1, Length = startTag.Length + 1, TypeOfToken = Token.TokenType.StartTag }; 
     else if (input.Substring(index, endTag.Length) == endTag) 
      token = new Token { Start = index - 1, Length = endTag.Length + 1, TypeOfToken = Token.TokenType.EndTag }; 

     // Yield the text right before the tag and the tag itself 
     if (token != null) 
     { 
      yield return new Token { Start = lastIndex, Length = index - lastIndex - 1, TypeOfToken = Token.TokenType.Text }; 
      yield return token; 
      lastIndex = index + token.Length - 1; 
     } 
    } 

    // Yield last text token 
    yield return new Token { Start = lastIndex, Length = input.Length - lastIndex, TypeOfToken = Token.TokenType.Text }; 
} 

class Token 
{ 
    public int Start { get; set; } 
    public int Length { get; set; } 
    public TokenType TypeOfToken { get; set; } 

    public enum TokenType 
    { 
     Text, 
     StartTag, 
     EndTag 
    } 
} 

它甚至有所優化,因爲它僅搜索<並檢查它是否是一個開始或結束標記之後。

有記號化的字符串時,處理的其餘部分很簡單:

static string ProcessString(string input, string tag) 
{ 
    var sb = new StringBuilder(); 

    int depth = 0; 
    foreach (var token in Tokenize(input, tag)) 
    { 
     // Append all tags, but only text tokens with depth level 0 
     if (token.TypeOfToken != Token.TokenType.Text || 
      (token.TypeOfToken == Token.TokenType.Text && depth == 0)) 
      sb.Append(input.Substring(token.Start, token.Length)); 
     else 
      sb.Append(new string(' ', token.Length)); 

     // Increment for each starttag, decrement for each endtag, never smaller than 0 
     depth = Math.Max(0, depth + (token.TypeOfToken == Token.TokenType.StartTag ? 1 : 
            (token.TypeOfToken == Token.TokenType.EndTag ? -1 : 0))); 
    } 

    return sb.ToString(); 
} 

這比正則表達式的解決方案更加靈活了不少,因爲你可以給它更多的語義,像深度。例如調用此:

ProcessString("level0<Tag>level1<Tag>level2</Tag>level1again</Tag>level0again", "Tag"); 

將被加工成這樣:

"level0<Tag>  <Tag>  </Tag>   </Tag>level0again"