Почему неразрывный пробел не является пробельным символом в Java? - PullRequest
29 голосов
/ 30 июня 2009

При поиске правильного способа обрезать неразрывный пробел из разобранного HTML, я сначала наткнулся на спартанское определение java String.trim(), которое, по крайней мере, должным образом задокументировано. Я хотел избежать явного перечисления символов, подходящих для обрезки, поэтому я предположил, что использование методов с поддержкой Unicode в классе Character сделает эту работу за меня.

Именно тогда я обнаружил, что Character.isWhitespace (char) явно исключает неразрывные пробелы:

Это символ пробела Unicode (SPACE_SEPARATOR, LINE_SEPARATOR или PARAGRAPH_SEPARATOR) , но также не является неразрывным пробелом ('\u00A0', '\u2007', '\u202F' ).

Почему это?

Реализация соответствующего .NET-эквивалента менее разборчива.

Ответы [ 7 ]

21 голосов
/ 30 июня 2009

Character.isWhitespace(char) стар. Действительно старый. Многие вещи, сделанные в первые дни Java, следовали соглашениям и реализациям из C.

Теперь, спустя более десяти лет, эти вещи кажутся ошибочными. Считайте это свидетельством того, как далеко продвинулись дела, даже между первыми днями Java и первыми днями .NET.

Java стремится к 100% обратной совместимости. Поэтому, даже если команда Java подумала, что было бы хорошо исправить свою первоначальную ошибку и добавить неразрывные пробелы в набор символов, который возвращает true из Character.isWhitespace (char), они не могут этого сделать, поскольку почти наверняка существует программное обеспечение, которое полагается, что текущая реализация работает точно так же, как и сейчас.

14 голосов
/ 17 сентября 2009

Начиная с Java 5 также существует метод isSpaceChar(int). Разве это не делает то, что вы хотите?

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

12 голосов
/ 06 июня 2011

Как указано выше, isSpaceChar(int) предоставит ОП трек к ответу. Это выглядит довольно незаметно, но этот метод на самом деле можно использовать с регулярными выражениями . Итак:

    "X\u00A0X X".replaceAll("\\p{javaSpaceChar}", "_");

создаст строку "X_X_X". В качестве упражнения для читателя предложено найти регулярное выражение для обрезки строки. (Шаблон с некоторыми флагами должен сработать.)

7 голосов
/ 30 июня 2009

Я бы сказал, что реализация Java более правильная, чем .NET. Неразрывный пробел по сути является непробельным символом, который выглядит как один. То есть, если у вас есть строки «foo» и «bar», и между ними вставлен любой традиционный символ пробела, вы получите разрыв слова. Однако неразрывный пробел не разбивает их на две части.

6 голосов
/ 30 июня 2009

Единственный раз, когда неразрывный пробел следует обрабатывать специально, - это код, предназначенный для переноса текста в текст.

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

Любой аргумент, что неразрывный пробел просто «выглядит» как пробел, но не противоречит целой точке Unicode, которая представляет символы на основе их значения, а не того, как они отображаются.

Таким образом, IMHO, реализация Java String.trim () на Java не работает должным образом, и основная функция Character.isWhitespace () ошибается.

Я предполагаю, что разработчики Java написали isWhitespace () исходя из необходимости выполнения переноса текста в элементах управления. Они должны были назвать эту функцию isWordWrappingBoundary () или что-то более понятное, и использовать менее строгий тест для пробела для trim ().

2 голосов
/ 20 июля 2011

Также будьте осторожны при использовании функции apache commons StringUtils.isBlank () (и связанных функций), которая имеет такое же странное поведение isWhitespace , то есть считается неразрывный пробел быть непустым.

2 голосов
/ 30 июня 2009

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

* It is a Unicode space character (SPACE_SEPARATOR, LINE_SEPARATOR, or PARAGRAPH_SEPARATOR) but is not also a non-breaking space ('\u00A0', '\u2007', '\u202F').
* It is '\u0009', HORIZONTAL TABULATION.
* It is '\u000A', LINE FEED.
* It is '\u000B', VERTICAL TABULATION.
* It is '\u000C', FORM FEED.
* It is '\u000D', CARRIAGE RETURN.
* It is '\u001C', FILE SEPARATOR.
* It is '\u001D', GROUP SEPARATOR.
* It is '\u001E', RECORD SEPARATOR.
* It is '\u001F', UNIT SEPARATOR. 

Предполагается, что функция неразрывного пробела - это визуальное пространство между словами, которое не разделено алгоритмами переноса.

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