Подтвердить что ты не робот

Почему я получаю исключение StringIndexOutOfBoundsException, когда пытаюсь заменить `\\` на `\`?

Мне нужно заменить \\ на \ на Java. Код, который я использую,

System.out.println( (MyConstants.LOCATION_PATH + File.separator + myObject.getStLocation() ).replaceAll("\\\\", "\\") );

Но я не знаю, почему он бросает StringIndexOutOfBoundsException.

В нем говорится String index out of range: 1

В чем может быть причина? Я думаю, это потому, что первый аргумент replaceAll принимает шаблон. Каким может быть возможное решение?


StackTrace

Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 1
    at java.lang.String.charAt(String.java:558)
    at java.util.regex.Matcher.appendReplacement(Matcher.java:696)
    at java.util.regex.Matcher.replaceAll(Matcher.java:806)
    at java.lang.String.replaceAll(String.java:2000)

Найден ответ

asalamon74 разместил код, который мне нужен, но я не знаю, почему он его удалил. В любом случае это так.

Существует bug, уже зарегистрированный в базе данных ошибок Java. (Спасибо за эту ссылку, асаламон.)

yourString.replaceAll("\\\\", "\\\\");

Удивительно, что строка поиска и замены одинакова:), но все же она делает то, что мне нужно.

4b9b3361

Ответ 1

Используйте String.replace вместо replaceAll, чтобы избежать использования регулярного выражения:

String original = MyConstants.LOCATION_PATH + File.seperator 
    + myObject.getStLocation();
System.out.println(original.replace("\\\\", "\\"));

Лично я бы этого не делал, но я создал MyConstants.LOCATION_PATH_FILE как File, а затем вы могли бы написать:

File location = new File(MyConstants.LOCATION_PATH_FILE,
                         myObject.getStLocation());

который будет делать правильную вещь автоматически.

Ответ 2

Ну, я попробовал

    String test = "just a \\ test with some \\\\ and others \\\\ or \\ so";
    String result = test.replaceAll("\\\\", "\\\\");
    System.out.println(test);
    System.out.println(result);
    System.out.println(test.equals(result));

и получил, как ожидалось

just a \ test with some \\ and others \\ or \ so
just a \ test with some \\ and others \\ or \ so
true

Что вам действительно нужно

string.replaceAll("\\\\\\\\", "\\\\");

чтобы получить

just a \ test with some \\ and others \\ or \ so
just a \ test with some \ and others \ or \ so
false

Вы хотите найти: \\ (2 слэша)
который должен быть экранирован в регулярном выражении: \\\\ (4 слэша)
и сбежал в Java: "\\\\\\\\" (8 слэшей)
то же самое для замены...

Ответ 3

Для регулярного выражения, если вы хотите изменить \ на \\, вы должны сделать это:

if (str.indexOf('\\') > -1)
    str = str.replaceAll("\\\\", "\\\\\\\\");
str = "\"" + str + "\"";

Где \\\\ означает \ и \\\\\\\\ означает \\.

Ответ 4

File.seperator уже экранирован, как и любой строковый объект, поэтому вы избегаете их дважды.

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

Ответ 5

Попробуйте это

cadena.replaceAll("\\\\","\\\\\\\\")

Ответ 6

Лучший способ:

str.replace(**'**\\**'**, **'**/**'**); //with char method not String

Ответ 7

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

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

Ответ 8

Я считаю, что вам нужно сделать следующее:

System.out.println( (MyConstants.LOCATION_PATH + File.separator + myObject.getStLocation() ).replaceAll("\\\\\\\\", "\\\\") );

Регулярное выражение String на самом деле представляет собой четыре обратной косой черты, которая является регулярным выражением, которое соответствует двум обратным слэшам.

Строка замены должна быть четырьмя слэшами в соответствии с документацией Java, начиная с: http://java.sun.com/javase/6/docs/api/java/util/regex/Matcher.html#replaceAll(java.lang.String)

Обратите внимание, что обратная косая черта() и знаки доллара ($) в заменяющей строке могут привести к тому, что результаты будут отличаться от того, будут ли они рассматриваться как буквальная строка замены. Знаки доллара могут рассматриваться как ссылки на захваченные подпоследовательности, как описано выше, а обратные косые черты используются для исключения буквенных символов в заменяющей строке.

Ответ 9

final StringBuilder result = new StringBuilder();
final StringCharacterIterator iterator = new StringCharacterIterator(str);
char character =  iterator.current();
while (character != CharacterIterator.DONE )
{
  if (character == '\\\\') {
     result.append("\\");
  }
  else {
    result.append(character);
  }

  character = iterator.next();
}

System.out.print(result);