2013-04-22 4 views
3

Я пытаюсь разобрать значения, разделенные запятыми, заключенные в кавычки, используя только стандартные библиотеки Java (я знаю, что это должно быть возможно)Разбор значений, разделенных запятыми, заключенные в кавычки

В качестве примера file.txt содержит новая линия для каждой строки

"Foo","Bar","04042013","04102013","Stuff" 
"Foo2","Bar2","04042013","04102013","Stuff2" 

Однако, когда я анализирую файл с кодом, которую я написал до сих пор:

import java.io.*; 
import java.util.Arrays; 
public class ReadCSV{ 

    public static void main(String[] arg) throws Exception { 

     BufferedReader myFile = new BufferedReader(new FileReader("file.txt")); 

     String myRow = myFile.readLine(); 
     while (myRow != null){ 
      //split by comma separated quote enclosed values 
      //BUG - first and last values get an extra quote 
      String[] myArray = myRow.split("\",\""); //the problem 

      for (String item:myArray) { System.out.print(item + "\t"); } 
      System.out.println(); 
      myRow = myFile.readLine(); 
     } 
     myFile.close(); 
    } 
} 

Однако outpu т является

"Foo Bar  04042013  04102013  Stuff" 

"Foo2 Bar2 04042013  04102013  Stuff2" 

Вместо

Foo Bar  04042013  04102013  Stuff 

Foo2 Bar2 04042013  04102013  Stuff2 

Я знаю, что пошло не так в Сплите, но я не уверен, как это исправить.

+0

возможно дубликат [Java: Разбиение строки, разделенные запятых, но игнорирующие запятые в кавычках] (http://stackoverflow.com/questions/1757065/java-splitting-a-comma-separated-string-but -ignoring-commas-in-quotes) –

+0

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

+0

не говоря уже о решении было регулярное выражение, которое не должно быть здесь (надеюсь!). Мой желаемый результат не показывает никаких кавычек вообще, тогда как вывод в другом столбце сохраняет кавычки. – sputn1ck

ответ

4

Перед выполнением split просто удалите первую двойную кавычку и последнюю двойную кавычку в переменной myRow, используя нижнюю строку.

myRow = myRow.substring(1, myRow.length() - 1); 

(ОБНОВЛЕНИЕ) Также проверьте, не является ли myRow пустым. В противном случае выше код вызовет исключение. Например, ниже код проверяет, не является ли myRow пустым, а затем удаляет только двойные кавычки из строки.

if (!myRow.isEmpty()) { 
    myRow = myRow.substring(1, myRow.length() - 1); 
} 
+0

ReadCSV.java:13: ошибка: не удается найти символ myRow = myRow .substring (1, myRow.length() - 1); ^ символ: метод подстрока (целое, целая) местоположения: переменная myRow типа строки -ошибка – sputn1ck

+0

использование myRow.substring() вместо myRow.subString () –

+0

@ sputn1ck это должно быть * подстрока * – Maroun

2

Вместо этого, вы можете использовать replaceAll, который, для меня, выглядит более подходящим для этой задачи:

myRow = myRow.replaceAll("\"", "").replaceAll(","," "); 

Это заменит все " ничего (Снимут их), то это ll заменить все , пробелом (конечно, вы можете увеличить количество пробелов).

+0

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

+0

О чем вы говорите? Это решает его проблему. BTW, мои решения ничего не разделяют. – Maroun

+2

только в данном случае. подумайте об этом «foo», «bar», «foo, bar», ваше решение вернет массив с 4 элементами, но есть только три –

1

Проблема в приведенном выше фрагменте кода заключается в том, что вы разбиваете строку на основе ",". на вашем старте линии "foo"," и конец ","stuff" стартовые и конечные котировки не соответствуют ",", поэтому их нет.

так что это определенно не ошибка в java. в вашем случае вам нужно самому справиться с этой частью.

У вас есть несколько вариантов для этого. некоторые из них могут быть похожими ниже. 1. Если вы уверены, что всегда будет начальный " и заканчивается ", вы можете удалить их из строки перед раздачей перед расщеплением. 2. Если начальные " и " являются необязательными, вы можете сначала проверить его с помощью startsWithendsWith, а затем удалить, если существует до разделения.

0

Вы можете просто получить строку, разделенную запятой, а затем удалить первый и последний «». =) надежда Thats ПОЛЕЗНЫЕ не имеют много времени: D

String s = "\"Foo\",\"Bar\",\"04042013\",\"04102013\",\"Stuff\""; 
     String[] bufferArray = new String[10]; 
     String bufferString; 
     int i = 0; 
     System.out.println(s); 

     Scanner scanner = new Scanner(s); 
     scanner.useDelimiter(","); 

     while(scanner.hasNext()) { 
      bufferString = scanner.next(); 
      bufferArray[i] = bufferString.subSequence(1, bufferString.length() - 1).toString(); 
      i++; 
     } 

     System.out.println(bufferArray[0]); 
     System.out.println(bufferArray[1]); 
     System.out.println(bufferArray[2]); 
+1

Что произойдет, если в запятой есть запятая? – rmalchow

+0

, чем синтаксический анализатор не сможет выполнить свою работу. Вы не можете использовать разделитель как действительный символ в строке. Если вы хотите использовать запятую в строке, вы можете использовать две запятые в качестве разделителя или что-то еще. – datosh

+0

@ datosh: вы ** можете ** использовать запятые как допустимые символы ** и ** разделитель. это именно то, для чего нужны цитаты. Внутренние кавычки - это те вещи, которые требуют ускорения, а не запятые. –

4

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

import java.util.ArrayList; 
import java.util.List; 


public class CSV { 

    public static void main(String[] args) { 
     String s = "\"hello, i am\",\"a string\""; 
     String x = s; 
     List<String> l = new ArrayList<String>(); 
     int state = 0; 
     while(x.length()>0) { 
      if(state == 0) { 
       if(x.indexOf("\"")>-1) { 
        x = x.substring(x.indexOf("\"")+1).trim(); 
        state = 1; 
       } else { 
        break; 
       } 
      } else if(state == 1) { 
       if(x.indexOf("\"")>-1) { 
        String found = x.substring(0,x.indexOf("\"")); 
        System.err.println("found: "+found); 
        l.add(found); 
        x = x.substring(x.indexOf("\"")+1).trim(); 
        state = 0; 
       } else { 
        throw new RuntimeException("bad format"); 
       } 
      } else if(state == 2) { 
       if(x.indexOf(",")>-1) { 
        x = x.substring(x.indexOf(",")+1).trim(); 
        state = 0; 
       } else { 
        break; 
       } 
      } 
     } 
     for(String f : l) { 
      System.err.println(f); 
     } 
    } 


} 
0

Это решение менее элегантно, чем String.split() Oneliner. Преимущество состоит в том, что мы избегаем хрупкой манипуляции с строкой, т.е. использование String.substring(). Строка должна заканчиваться ,".

Эта версия обрабатывает пробелы между разделителями. Символы-разделители в кавычках игнорируются, как и ожидалось, как и экранированные кавычки (например, \").

String s = "\"F\\\",\\\"oo\" , \"B,ar\",\"04042013\",\"04102013\",\"St,u\\\"ff\""; 
Pattern p = Pattern.compile("(.*?)\"\\s*,\\s*\""); 
Matcher m = p.matcher(s + ",\""); // String must end with ," 
while (m.find()) { 
    String result = m.group(1); 
    System.out.println(result); 
} 
Смежные вопросы