Нужна помощь в разборе строк в Java - PullRequest
2 голосов
/ 01 сентября 2010

Я читаю в CSV-файле на Java и, в зависимости от формата строки в данной строке, я должен сделать что-то другое с ним. В CSV-файле содержатся три разных формата (с использованием случайных чисел):

833 "79, 869" "56-57, 568"

Если это просто одно число (833), я хочу добавить его в свой ArrayList. Если это два числа, разделенные запятой и заключенные в кавычки («79, 869)», я хочу разобрать первое из двух чисел (79) и добавить его в ArrayList. Если это три числа, заключенные в кавычки (где первые два числа разделены чертой, а третье запятой ["56-57, 568"], то я хочу разобрать третье число (568) и добавить это в ArrayList.

У меня проблемы с использованием str.contains (), чтобы определить, содержит ли строка в данной строке тире или нет. Кто-нибудь может предложить мне помощь? Вот что у меня есть:

private static void getFile(String filePath) throws java.io.IOException {
    BufferedReader reader = new BufferedReader(new FileReader(filePath));
    String str;

    while ((str = reader.readLine()) != null) {

        if(str.endsWith("\"")){
            if (str.contains(charDash)){
                System.out.println(str);
            }
        }

    }

}

Спасибо!

Ответы [ 6 ]

1 голос
/ 01 сентября 2010

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

Вы должны создать его, используя ", - в качестве своих токенов, а затем просто запустить его в цикле.

st=new StringTokenizer(line, "\",-", true);

Затем вы настраиваете цикл:

while(st.hasNextToken()) {
    String token=st.nextToken();

Каждый кейс становится своей маленькой частью цикла:

// Use punctuation to set flags that tell you how to interpret the numbers.
if(token == "\"") {
    isQuoted = !isQuoted;
} else if(token == ",") {
    ...        
} else  if(...) {
    ...
} else { // The punctuation has been dealt with, must be a number group
    // Apply flags to determine how to parse this number.
}

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

Полагаю, если вам и всем, с кем вы работаете, действительно удобно с Регулярными выражениями, вы можете заменить это на split и просто перебрать результирующий массив, но я не уверен, как получить split, чтобы вернуть пунктуацию - возможно, это " + "вещь из других ответов, но я никогда не верю, что какой-то персонаж, который я передаю регулярному выражению, не сделает что-то совершенно неожиданное.

1 голос
/ 01 сентября 2010

Следующий код работает для меня (примечание: я написал его без какой-либо оптимизации - он только для целей тестирования):

public static void main(String args[]) {
    ArrayList<String> numbers = GetNumbers();
}

private static ArrayList<String> GetNumbers() {
    String str1 = "833";
    String str2 = "79, 869";
    String str3 = "56-57, 568";

    ArrayList<String> lines = new ArrayList<String>();

    lines.add(str1);
    lines.add(str2);
    lines.add(str3);

    ArrayList<String> numbers = new ArrayList<String>();

    for (Iterator<String> s = lines.iterator(); s.hasNext();) {
        String thisString = s.next();

        if (thisString.contains("-")) {
            numbers.add(thisString.substring(thisString.indexOf(",") + 2));
        } else if (thisString.contains(",")) {
            numbers.add(thisString.substring(0, thisString.indexOf(",")));
        } else {
            numbers.add(thisString);
        }
    }

    return numbers;
}

Вывод:

833
 79
568
1 голос
/ 01 сентября 2010

Я рекомендую использовать версию indexOf, которая на самом деле принимает символ, а не строку, так как этот метод намного быстрее.(Это простой цикл без вложенного цикла.)

Т.е.

  if (str.indexOf('-')!=-1) {
      System.out.println(str);
   }

(Обратите внимание на одинарные кавычки, так что это символ, а не строка.)

Но тогда вам нужно разделить строку и проанализировать отдельные значения.В настоящее время вы проверяете, заканчивается ли вся строка кавычкой, что, вероятно, не то, что вам нужно.

0 голосов
/ 01 сентября 2010

Я думаю, что три регулярных выражения были бы вашей лучшей ставкой - потому что с матчем вы также получаете интересующий вас бит. Я сосу с регулярным выражением, но что-то вроде:

.*\-.*, (.+)

.*, (.+)

и

(.+)

следует сделать трюк (по порядку, потому что окончательный шаблон соответствует чему угодно, включая первые два).

0 голосов
/ 01 сентября 2010

Будет ли это работать?

if(str.contains("-")) {
    System.out.println(str);
} 

Интересно, переменная charDash - это не то, что вы ожидаете.

0 голосов
/ 01 сентября 2010

будет

    if (str.indexOf(charDash.toString()) > -1){
        System.out.println(str);
    }

сделать трюк?

который, кстати, быстрее, чем contains ... потому что он реализует indexOf

...