2015-12-15 7 views
4

Я пытаюсь разобрать csv с помощью java и иметь следующую проблему: второй столбец представляет собой строку (которая также может содержать запятую), заключенную в двойные кавычки, за исключением случаев, когда сама строка содержит двойную кавычку, тогда вся строка заключена в одну цитату. напримерparse csv, не разделяйте в одиночных или двойных кавычках

Линия может Локк, как это:

someStuff,"hello", someStuff 
someStuff,"hello, SO", someStuff 
someStuff,'say "hello, world"', someStuff 
someStuff,'say "hello, world', someStuff 

someStuff заполнители для других элементов, которые также могут включать цитаты в том же стиле

я ищу общий способ разделить строки на запятые UNLESS, заключенные в одиночные или двойные кавычки, чтобы получить второй столбец как String. Со второй колонке я имею в виду поля:

  • привет
  • привет, SO
  • сказать "привет, мир"
  • сказать «привет, мир

Я попытался OpenCSV но не в можно указать только один тип цитаты:

public class CSVDemo { 

public static void main(String[] args) throws IOException { 
    CSVDemo demo = new CSVDemo(); 
    demo.process("input.csv"); 
} 

public void process(String fileName) throws IOException { 
    String file = this.getClass().getClassLoader().getResource(fileName) 
      .getFile(); 
    CSVReader reader = new CSVReader(new FileReader(file)); 
    String[] nextLine; 
    while ((nextLine = reader.readNext()) != null) { 
     System.out.println(nextLine[0] + " | " + nextLine[1] + " | " 
       + nextLine[2]); 
    } 
} 

}

Решение с opencsv терпит неудачу на последней строке, где есть только один двойной кавычки заключены в одинарные кавычки:

someStuff | hello | someStuff 
someStuff | hello, SO | someStuff 
someStuff | 'say "hello, world"' | someStuff 
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 1 
+0

может изменить данные поживаете? '" say \ "привет, мир \" "должен работать в opencsv. –

+0

Данные находятся в файле, поэтому я могу его изменить. Я догадываюсь до разбора ... например, читать строку, изменять/исключать цитату, а затем разделить ее –

ответ

1

Это не кажется, что opencsv поддерживает это из коробки. Вы можете расширить com.opencsv.CSVParser и реализовать собственный алгоритм обработки двух типов котировок. This - это источник метода, который вы бы изменили, и вот заглушка, чтобы вы начали.

class MyCSVParser extends CSVParser{ 
    @Override 
    private String[] parseLine(String nextLine, boolean multi) throws IOException{ 
     //Your algorithm here 
    } 
} 
2

Если вы действительно не можете использовать настоящий синтаксический анализатор CSV, вы можете использовать регулярное выражение. Это, как правило, не очень хорошая идея, так как всегда есть крайние случаи, которые вы не можете обработать, но если форматирование строго, как вы описываете, это может сработать.

public void test() { 
    String[] tests = {"numeStuff,\"hello\", someStuff, someStuff", 
     "numeStuff,\"hello, SO\", someStuff, someStuff", 
     "numeStuff,'say \"hello, world\"', someStuff, someStuff" 
    }; 
    /* Matches a field and a potentially empty separator. 
    * 
    * (- Field Group 
    *  \" - Start with a quote 
    *  [^\"]*? - Non-greedy match on anything that is not a quote 
    *  \" - End with a quote 
    * | - Or 
    *  ' - Start with a strop 
    *  [^']*? - Non-greedy match on anything that is not a strop 
    *  ' - End with a strop 
    * | - Or 
    * [^\"'] - Not starting with a quote or strop 
    * [^,$]*? - Non-greedy match on anything that is not a comma or end-of-line 
    * ) - End field group 
    * (- Separator group 
    * [,$] - Comma separator or end of line 
    * ) - End separator group 
    */ 
    Pattern p = Pattern.compile("(\"[^\"]*?\"|'[^\']*?\'|[^\"'][^,\r\n]*?)([,\r\n]|$)"); 
    for (String t : tests) { 
     System.out.println("Matching: " + t); 
     Matcher m = p.matcher(t); 
     while (m.find()) { 
      System.out.println(m.group(1)); 
     } 
    } 
} 
0

Не похоже, что opencv поддерживает это. Тем не менее, посмотрите на этот предыдущий вопрос и мой ответ, а также другие ответы в случае, если они помогают вы: https://stackoverflow.com/a/15905916/1688441

Ниже приведен пример, пожалуйста, не notInsideComma на самом деле означает «в кавычках». Следующий код может быть расширен для проверки как кавычек, так и двойных кавычек.

public static ArrayList<String> customSplitSpecific(String s) 
{ 
    ArrayList<String> words = new ArrayList<String>(); 
    boolean notInsideComma = true; 
    int start =0, end=0; 
    for(int i=0; i<s.length()-1; i++) 
    { 
     if(s.charAt(i)==',' && notInsideComma) 
     { 
      words.add(s.substring(start,i)); 
      start = i+1;     
     } 
     else if(s.charAt(i)=='"') 
     notInsideComma=!notInsideComma; 
    } 
    words.add(s.substring(start)); 
    return words; 
} 
1

В основном вам нужно только отслеживать ," и ,' (зачистка, что в середине).

Когда вы сталкиваетесь с одним из них, установите соответствующий флаг (например, singleQuoteOpen, doubleQuoteOpen) в значение true, чтобы указать, что они открыты, и вы находитесь в режиме игнорирования-запятой.

Когда вы соответствуете заключительной цитате, сбросьте флаг и продолжайте нарезать элементы.

Чтобы выполнить проверку, остановитесь в каждой запятой (если не в режиме игнорирования-запятой) и посмотрите на следующий символ (если есть, и обрезка).


Примечание: регулярное выражение решение хорошо, а также короче, но менее настраиваемый для краевых случаев (по крайней мере, без больших головных болей).

0

Если использование одинарных и двойных кавычках соответствует каждой строке, можно выбрать соответствующий тип цитаты в строке:

public class CSVDemo { 
    public static void main(String[] args) throws IOException { 
     CSVDemo demo = new CSVDemo(); 
     demo.process("input.csv"); 
    } 

    public void process(String fileName) throws IOException { 
     String file = this.getClass().getClassLoader().getResource(fileName) 
       .getFile(); 

     CSVParser doubleParser = new CSVParser(',', '"'); 
     CSVParser singleParser = new CSVParser(',', '\''); 

     String[] nextLine; 

     try (BufferedReader br = new BufferedReader(new FileReader(file))) { 
      String line; 
      while ((line = br.readLine()) != null) { 
       if (line.contains(",'") && line.contains("',")) { 
        nextLine = singleParser.parseLine(line); 
       } else { 
        nextLine = doubleParser.parseLine(line); 
       } 

       System.out.println(nextLine[0] + " | " + nextLine[1] + " | " 
         + nextLine[2]); 
      } 
     } 
    } 
} 

 Смежные вопросы

  • Нет связанных вопросов^_^