Трудное время с побегом - PullRequest
       12

Трудное время с побегом

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

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

public static String removeBlockedCharacters(String data) {
    if (data==null) {
      return data;
    }
    return data.replaceAll("(?i)[<|>|\u003C|\u003E]", "");
}

У меня есть тестовый файл invalidCharacter.txt с одной строкой в ​​нем:

hello \u003c here < and > there

Я запускаю следующий модульный тест:

@Test
public void testBlockedCharactersRemoval() throws IOException{
    checkEquals(StringUtil.removeBlockedCharacters("a < b > c\u003e\u003E\u003c\u003C"), "a  b  c");
    log.info("Procesing from string directly: " + StringUtil.removeBlockedCharacters("hello \u003c here < and > there"));
    log.info("Procesing from file to string:  " + StringUtil.removeBlockedCharacters(FileUtils.readFileToString(new File("src/test/resources/illegalCharacters.txt"))));
}

Я получаю:

INFO - 2010-09-14 13:37:36,111 - TestStringUtil.testBlockedCharactersRemoval(36) | Procesing from string directly: hello  here  and  there
INFO - 2010-09-14 13:37:36,126 - TestStringUtil.testBlockedCharactersRemoval(37) | Procesing from file to string:  hello \u003c here  and  there

Я ОЧЕНЬ растерялся: как видите, код правильно удаляется«<», «>» и «\ u003c», если я пропущу строку, содержащую эти значения, но она не удалит «\ u003c», если я прочту из файла, содержащего ту же строку.

Мои вопросы, чтобы я перестала терять волосы, это:

  1. Почему я получаю такое поведение?
  2. Как я могу изменить свой код для правильного удаления \ u003c во всех случаях?

Спасибо

Ответы [ 3 ]

5 голосов
/ 14 сентября 2010

привет \ u003c здесь <и> там

\u003c в файле ASCII этого не сделает, вам нужно поместить фактический символ Unicode в текстовый файл в кодировке Unicode.

3 голосов
/ 14 сентября 2010

Когда вы компилируете свой исходный файл, самое первое, что происходит - перед любыми лексами или синтаксическим анализом - это то, что экранирование Unicode, \u003C и \u003E, преобразуется в действительные символы < и >. Итак, ваш код действительно:

return data.replaceAll("(?i)[<|>|<|>]", "");

Когда вы компилируете код для теста со строковым литералом, происходит то же самое; тестовая строка, которую вы написали как:

"a < b > c\u003e\u003E\u003c\u003C"

... действительно:

"a < b > c>><<"

Но когда вы читаете тестовую строку из файла, такое преобразование не происходит; в итоге вы пытаетесь сопоставить последовательность из шести символов \u003c с одним символом <. Если вы действительно хотите сопоставить \u003C и \u003E, ваш код должен выглядеть следующим образом:

return data.replaceAll("(?i)(?:<|>|\\\\u003C|\\\\u003E)", "");
  • Если вы используете один обратный слеш, компилятор Java интерпретирует его как escape-код Unicode и преобразует его в < или >.

  • Если вы используете два обратных слеша, компилятор regex интерпретирует его как escape-код Unicode и думает, что вы хотите match a < или >.

  • Если вы используете три обратных слеша, компилятор Java превращает его в \< или \>, компилятор регулярного выражения игнорирует обратную косую черту и пытается сопоставить < или >.

  • Итак, чтобы соответствовать необработанной escape-последовательности Unicode, вы должны использовать четыре обратных слеша для соответствия one обратной косой черты в escape-последовательности.

Обратите внимание, что я тоже изменил ваши скобки. [<|>] - это класс символов , который соответствует <, | или >; вам нужно чередование .

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

Мне кажется, что проблема не в вашем побеге, а в том, что у вас есть данные в кодировке Юникод, которые вы пытаетесь проанализировать.

Вы пытались использовать версию с двумя аргументами readFileToString, заменив ваш readFileToString(File) вызов на readFileToString(File, Encoding)?

Ресурсы

...