2009-06-29 22 views
28

Mientras busco una forma adecuada de recortar el espacio sin interrupciones del HTML analizado, primero me encontré con la espartana definición de java de String.trim() que está al menos documentada correctamente. Quería evitar enumerar explícitamente a los personajes elegibles para recortar, así que asumí que usar métodos respaldados por Unicode en la clase de personaje me haría el trabajo.¿Por qué el espacio non-breaking no es un carácter de espacio en blanco en java?

Fue entonces cuando descubrí que Character.isWhitespace(char) excluye explícitamente de no separación espacios:

Es un carácter de espacio Unicode (SPACE_SEPARATOR, LINE_SEPARATOR o PARAGRAPH_SEPARATOR) pero no es también un espacio de no separación ('\u00A0' , '\u2007', '\u202F').

¿Por qué es eso?

La implementación de corresponding .NET equivalent es menos discriminatoria.

Respuesta

20

Character.isWhitespace(char) es viejo. Realmente viejo. Muchas cosas hechas en los primeros días de Java siguieron las convenciones e implementaciones de C.

Ahora, más de una década después, estas cosas parecen erróneas. Considérelo como evidencia de lo lejos que han llegado las cosas, incluso entre los primeros días de Java y los primeros días de .NET.

Java se esfuerza por ser 100% compatible con versiones anteriores. Así que incluso si el equipo de Java pensó que sería bueno corregir su error inicial y agregar espacios sin interrupciones al conjunto de caracteres que devuelve verdadero de Character.isWhitespace (char), no pueden, porque es casi seguro que exista software que se basa en la implementación actual trabajando exactamente como lo hace.

+3

Con respecto a la compatibilidad con versiones anteriores: estoy de acuerdo, pero no hay ninguna razón para no agregar, por ejemplo, Character.isWhitespaceNew (char) para capturar la situación actual. – Jirka

+13

Por ese camino yace PHP. – Eric

+7

Y en el otro camino se encuentra, bueno, Java. Un lenguaje que abrió el camino para los que lo siguieron (que aprendió de sus errores), pero por qué alguien lo usaría voluntariamente si tuvieran otras opciones está más allá de mi comprensión. – Eloff

2

Parece que el nombre del método (isWhitespace) es inconsistente con su función (para detectar separadores). La funcionalidad "separador" es bastante claro si nos fijamos en la lista completa de los caracteres de la página de Javadoc se citan:

* 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. 

Una función de espacio de no separación se supone que es el espacio visual entre palabras que no esté separada por algoritmos de separación de palabras

7

Yo diría que la implementación de Java es más correcta que la de .NET. El espacio sin interrupción es esencialmente un personaje que no es de espacio en blanco que se parece a uno. Es decir, si tiene las cadenas "foo" y "bar", y coloca cualquier carácter de espacio en blanco tradicional entre ellas, obtendría un salto de palabra. Un espacio sin interrupciones, sin embargo, no rompe las dos.

+4

Un espacio sin interrupciones sigue siendo un límite de palabras. La "ruptura" en "espacio sin interrupción" se refiere a cómo se debe interpretar para los fines de ** línea ** - ruptura, no saltos de palabra. – richardtallent

6

La única vez que se debe tratar un espacio no disruptivo es especialmente con un código diseñado para realizar el ajuste del texto.

Para todos los demás fines, incluidos recuentos de palabras, recorte y división de uso general a lo largo de los límites de las palabras, un espacio sin interrupción sigue siendo el espacio en blanco.

Cualquier argumento de que un espacio no disruptivo solo "se parece" a un espacio pero no está en conflicto con el punto total de Unicode, que representa los caracteres en función de su significado, no cómo se muestran.

Por lo tanto, en mi humilde opinión, la implementación de Java de String.trim() no está funcionando como se esperaba, y la función subyacente Character.isWhitespace() tiene la culpa.

Supongo que los implementadores de Java escribieron isWhitespace() en función de la necesidad de realizar el ajuste del texto dentro de los controles. Deberían haber llamado a esta función isWordWrappingBoundary() o algo más claro, y utilizaron una prueba de espacio en blanco menos restrictiva para trim().

+5

String.trim() está aún más roto que eso. Simplemente recorta los caracteres de control ASCII y ningún espacio en blanco Unicode en absoluto, rompiendo o no. – Thilo

13

Desde Java 5 también hay un método isSpaceChar(int). ¿Eso no hace lo que quieres?

Determina si el carácter especificado (punto de código Unicode) es un carácter de espacio Unicode. Se considera que un carácter es un carácter de espacio si y solo si el estándar Unicode lo especifica como un carácter de espacio. Este método devuelve verdadero si el tipo de categoría general del personaje es cualquiera de los siguientes: ...

+1

No es tanto la existencia de tal método lo que el OP estaba buscando; sino más bien una función de tipo 'trim 'que * usa * ese método para determinar qué quitar. –

+0

Tenga en cuenta que también hay un método 'isSpaceChar (char)' –

+0

El método isSpaceChar() no incluye el espacio en blanco en latín (pestaña, por ejemplo). – zendu

10

tal como fue anunciado anteriormente, isSpaceChar(int) proporcionará la OP con una pista para la respuesta. Parece bastante discretamente documentado, pero este método es realmente useable with regexes. Así :

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

producirá una cadena "X_X_X". Se deja como un ejercicio para que el lector proponga la expresión regular para recortar una cuerda. (Patrón con algunas banderas debe hacer el truco.)

+0

Funciona mejor, necesita más "->" X \ u00A0XX ".replaceAll (" \\ p {javaSpaceChar} "," _ "); – user85155

+0

\ p {javaSpaceChar} no parece estar documentado en ningún lugar. – zendu

+1

@zendu - es, aunque no muy visiblemente: 1) https://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html#jcc: > Categorías que se comportan como el java. lang.Character boolean ismethodname methods (a excepción de los obsoletos) están disponibles a través de la misma sintaxis \ p {prop} donde la propiedad especificada tiene el nombre javamethodname. 2) https://docs.oracle.com/javase/7 /docs/api/java/lang/Character.html#isSpaceChar(char) –

2

También tenga cuidado al utilizar la función de apache commons StringUtils.isBlank() (y las funciones relacionadas) que tiene el mismo comportamiento extraño isWhitespace, es decir, un espacio de no separación se considera que no blanco.

Cuestiones relacionadas