2013-11-20 150 views
0

我讀文件一行一行到刺痛,使用line.indexOf('"', 1)substring() 它分解成小串,但這種方式不檢測是否前"\或不那麼它不反應逃逸字符。我該如何解決這個問題?轉義字符

(我不能只用line.split('"')職高"都在開始和字符串的結束,也沒有其他字符分割,導致我的任務不會允許這樣做。)

整個閱讀部分是:

while ((line = bufferedReader.readLine()) != null) { 
     System.out.println(line); 
     while(line.length()>0){ 
      if(line.charAt(0) == ',' || line.charAt(0) == ' '){ 
       line = line.substring(1); 
      } 
      else{ 
       if(line.indexOf(',') != -1){ 
        if (line.charAt(0) == '"'){ 
        pabaiga = line.indexOf("\"", 1); 
        zodis = line.substring(0, pabaiga+1); 
        line = line.substring(pabaiga+1); 
        duomenys.add(zodis); 
        } 
        else{ 
         pabaiga = line.indexOf(','); 
         zodis = line.substring(0, pabaiga); 
         line = line.substring(pabaiga); 
         duomenys.add(zodis); 
        } 
       } 
       else{ 
        zodis = line; 
        line = line.substring(line.length()); 
        duomenys.add(zodis); 
       } 
      } 
      for(String elem : duomenys){ 
      System.out.println(elem); 
      } 
duomenys.removeAll(duomenys); 
     } 

我不允許使用分隔符作爲分隔符,因爲在字符串中間可能有一個,使用\,在文本文件中不是一個選項。所以我建議確定一個sting元素爲「文本」,但如果它包含另一個「或\」在中間,我目前的代碼不起作用。

,如果我的從文本文件中的行是"start \"title\" end", 10, 20, "text"
刺痛數組應該包含

  • [0] "start "title" end"
  • [1] 10
  • [2] 20
  • [3] "text"
+1

請提供一個輸入的例子,我想你可以'拆分',因爲它需要一個正則表達式 –

+0

使用正則表達式來解決你的問題你可以定義一個正則表達式否定式t只在前面的字符不是反斜槓時才匹配(\) – sjkm

+0

請[[edit]]用幾個輸入和預期輸出示例來編寫問題,因爲現在你的問題不太清楚你想要實現什麼。 – Pshemo

回答

-1

如果你想在最後一個索引就用lastindexof

.lastindexOf("\"", 1) 

只是

pabaiga = line.lastindexOf("\"", 1); 
+0

OP希望找到沒有**'\\'前面第一個''**的索引,即第一個_unescaped_引用,這並不能解決這個問題 –

+0

@BoristheSpider我認爲他正在尋找第二個「以便他能找到線路的盡頭。糾正我,如果我錯了OP – user1210093

+0

鮑里斯蜘蛛說只是我想要的,我編輯我的問題,也許它現在更清潔 – user2542809

0

更換

pabaiga = line.indexOf("\"", 1); 

您可以先在動態大小組件您的令牌存儲像List。要用你的標記填充這個列表,你需要迭代你的句子中的每個字符,如果它不是,,那麼將其添加到tokenBuilder中,但是如果該逗號是在報價之外,那麼將tokenBuilder的當前值添加到你的標記列表中。這裏是示例代碼。

String line = "\"start \\\"title\\\" end\", 10, 20, \"text\""; 

List<String> tokens = new ArrayList<>(); 
StringBuilder tokenBuilder = new StringBuilder(); 

boolean insideQuote = false; 
char ch, prev = ' '; 

for (int i = 0; i < line.length(); i++) { 
    ch = line.charAt(i); 
    if (ch == '"' && prev != '\\') {// normal " (without \ before) 
     insideQuote = !insideQuote; // starts or ends quotation 
    } 
    // commas that are outside quote or last character in line 
    // should invoke adding non-empty builder to list 
    if (ch == ',' && !insideQuote || i == line.length() - 1) { 
     if (tokenBuilder.length() > 0) { 
      tokens.add(tokenBuilder.toString().trim()); 
      tokenBuilder.delete(0, tokenBuilder.capacity()); 
     } 

    } 
    // add every character to builder except \ that are inside 
    // quotes and have " after it 
    else if (!(ch == '\\' && i + 1 < line.length() 
      && line.charAt(i + 1) == '"' && insideQuote)) { 
     tokenBuilder.append(ch); 
    } 
    prev = ch;//in next loop previous character should be our current one 
} 

String[] array = tokens.toArray(new String[tokens.size()]); 

for (String s : array) 
    System.out.println(">" + s); 

輸出:

>"start "title" end" 
>10 
>20 
>"text 
+0

,這就是問題所在,它可能是字符串中間的一個逗號,如果它在雙引號之間,它應該被視爲字符串的一部分。 – user2542809

+0

@ user2542809檢查我更新的答案。 – Pshemo

0

你可以(在http://ideone.com/TTtlZV在線例子)使用此:

import java.util.*; 
import java.lang.*; 
import java.io.*; 

/* Name of the class has to be "Main" only if the class is public. */ 
class Ideone 
{ 
public static void main (String[] args) throws java.lang.Exception 
    { 
     boolean inQuoted = false; 

     List<String> parts = new ArrayList<String>(); 
     String s = "\"start \\\"title\\\" end\", 10, 20, \"text\""; 
     StringBuilder current = new StringBuilder(); 
     for(int i=0; i<s.length(); i++){ 
      char c = s.charAt(i); 
      char cPrev = (i == 0 ? (char)0 : s.charAt(i-1)); 

      if(c == '"' && cPrev != '\\'){ 
       inQuoted = !inQuoted; 
      } 

      if(c == ',' && !inQuoted){ 
       if(current.length() > 0){ 
        parts.add(current.toString()); 
        current = new StringBuilder(); 
       } 
      } 
      else { 
       int length = current.length(); 
       if(length > 1 && c == '"' && current.charAt(length-1) == '\\'){ 
        current.deleteCharAt(length-1); 
       } 
       current.append(c); 
      } 
     } 
     if(current.length() > 0){ 
      parts.add(current.toString()); 
     } 

     System.out.println(parts); 
    } 
} 

它不會處理雙轉義。例如

\\ 「

如果我運行該程序的輸出是:

[ 」啓動\「 標題\」 結束」,10,20, 「文本」 ]