Моделирование String.split с использованием StringTokenizer

Я преобразовываю код из существующего приложения для компиляции с помощью компилятора Java 1.1 для специального оборудования. Это означает, что я не могу использовать String.split(regex) для преобразования существующей строки в массив.

Я создал метод, который должен давать тот же результат, что и String.split(regex), но с ним что-то не так, и я не могу понять, что именно.

Код:

private static String[] split(String delim, String line) {
  StringTokenizer tokens = new StringTokenizer(line, delim, true);
  String previous = "";
  Vector v = new Vector();

  while(tokens.hasMoreTokens()) {
    String token = tokens.nextToken();

    if(!",".equals(token)) {
      v.add(token);
    } else if(",".equals(previous)) {
      v.add("");
    } else {
      previous = token;
    }
  }

  return (String[]) v.toArray(new String[v.size()]);
}

Пример ввода:

РМ^РЕС,0013A2004081937F,,9060,1234FF

Пример вывода:

String line = "RM^RES,0013A2004081937F,,9060,1234FF";
String[] items = split(",", line);

for(String s : items) {
    System.out.println(" [ " + s + " ] ");
}

[ RM^RES ] [ 0013A2004081937F ] [ ] [ ] [ 9060 ] [ ] [ 1234FF ]

Желаемый результат:

[RM^RES] [0013A2004081937F] [] [9060] [1234FF]


Старый код, который я пытаюсь преобразовать:

String line = "RM^RES,0013A2004081937F,,9060,1234FF";
String[] items = line.split(",");

for(String s : items) {
    System.out.println(" [ " + s + " ] ");
}

[RM^RES] [0013A2004081937F] [] [9060] [1234FF]


person JREN    schedule 11.07.2013    source источник
comment
Вероятно, вы захотите заменить ",".equals(...) на delim.equals(...) в методе разделения, если планируете использовать другой разделитель.   -  person Harald K    schedule 11.07.2013
comment
@haraldK Спасибо, это действительно хорошее замечание, чтобы отвлечься от проблемы :)   -  person JREN    schedule 11.07.2013


Ответы (5)


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

private static String[] split(String delim, String line) {

    StringTokenizer tokens = new StringTokenizer(line, delim, true);
    String previous = delim;
    Vector v = new Vector();

    while (tokens.hasMoreTokens()) {
        String token = tokens.nextToken();

        if (!delim.equals(token)) {
            v.add(token);
        } else if (previous.equals(delim)) {
            v.add("");
        }
        previous = token;
    }

    return (String[]) v.toArray(new String[v.size()]);
}
person Andrei Micu    schedule 11.07.2013

Почти все верно. Почти, потому что вы забыли "очистить" значение previous. Попробуй это:

if(!",".equals(token)) {
  v.add(token);
  previous = "";
} else if(",".equals(previous)) {
  v.add("");
  previous = "";
} else {
  previous = token;
}
person Max Adamek    schedule 11.07.2013
comment
Это все еще дает мне неправильный вывод. [ RM^RES ] [ 0013A2004081937F ] [ ] [ 9060 ] [ ] [ 1234FF ] - person JREN; 11.07.2013
comment
попробуйте также ввести previous = token в if{} - person Max Adamek; 11.07.2013
comment
После этого работает, но Андрей М уже дал лучшее решение. Спасибо, в любом случае. - person JREN; 11.07.2013

Как насчет того, чтобы вообще не использовать StringTokenizer:

private static String[] split(String delim, String line) {
    String current = line;
    int index = line.indexOf(delim);
    Vector vector = new Vector();
    while (index != -1) {
        vector.add(current.substring(0, index));
        current = current.substring(index + 1);
        index = current.indexOf(delim);
    }
    vector.add(current);

    return (String[]) vector.toArray(new String[vector.size()]);
}
person mavroprovato    schedule 11.07.2013

Вы можете попробовать это так

 public static void main(String[] args) throws ParseException {
    for (String s : split(",", "RM^RES,0013A2004081937F, ,9060,1234FF")) {
        System.out.print(" [ " + s + " ] ");
    }
  }

private static String[] split(String delim, String line) {
    StringTokenizer tokens = new StringTokenizer(line, delim);
    String[] v = new String[tokens.countTokens()];
    int i = 0;
    while (tokens.hasMoreTokens()) {
        v[i] = tokens.nextToken();
        i++;
    }
    return v;
}
person Ruchira Gayan Ranaweera    schedule 11.07.2013
comment
Это не работает, потому что мой массив также будет содержать разделитель. Это будет выглядеть так: [ RM^RES ] [ , ] [ 0013A2004081937F ] [ , ] [ , ] и т. д. Кроме того, вы изменили мою строку, добавив пробел между запятыми, я не могу изменить ввод, так как это протокол, которому необходимо следовать. - person JREN; 11.07.2013

Я думаю, вы не должны ничего предполагать о базовом разделителе.

    public static String[] split(String line, String delim) {
        Vector v = new Vector();
        final String EMPTY_STRING = "";
        StringTokenizer st = new StringTokenizer(line, delim, true);
        while (st.hasMoreTokens()) {
            String token = st.nextToken();

            if (token.equals(delim)) {
                if (v.isEmpty() || v.size() > 0 && !EMPTY_STRING.equals(v.get(v.size() - 1))) {
                    v.add(EMPTY_STRING);
                }
            } else {
                v.add(token);
            }
        }

        return (String[])v.toArray(new String[v.size()]);
    }
person bsd    schedule 11.07.2013
comment
Это не работает, потому что каждый раз, когда я получаю разделитель, он будет добавлять пустую строку, и мой массив будет выглядеть так: [ RM^RES ] [ ] [ 0013A2004081937F ] [ ] [ ] и т. д. В основном каждая запятая станет пустой ячейкой массива. - person JREN; 11.07.2013