2011-06-03 14 views

Respuesta

7

En caso de que necesite esto para escribir un archivo .properties, puede simplemente agregar las cadenas en un objeto Propiedades y luego guardarlo en un archivo. Cuidará la conversión.

+0

Bueno, debe asegurarse de guardar el archivo en formato UTF-8 (quizás UTF-16 o UCS-2/4 funcionarán) o tendrá problemas. – ArtB

+7

@ArtB: No, Properties interpreta los archivos de entrada siempre como 'ISO-8859-1' (primera página Unicode) y también los guarda en esa codificación. Por eso necesita los escapes' \ uXXXX' y los crea al guardar. Aunque desde Java La versión 1.6 Properties permite leer la entrada de un objeto Reader para que pueda crear su propio formato de archivo de propiedades basado en UTF-8. – x4u

+0

Oh ... ¿eso no causa problemas con los idiomas que no son de primera página? – ArtB

20

Usted podría utilizar escapeJavaStyleString de org.apache.commons.lang.StringEscapeUtils.

+0

Qué método hace esto? – ehsun7b

+0

Actualizó la respuesta. – sorin

+7

Parece que este método ha sido renombrado ['escapeJava'] (http://commons.apache.org/proper/commons-lang/javadocs/api-3.1/org/apache/commons/lang3/StringEscapeUtils.html#escapeJava% 28java.lang.String% 29) en las versiones 3.x –

11

Hay tres partes en la respuesta

  1. Obtener el Unicode para cada personaje
  2. Determinar si está en el cirílico Página
  3. Convertir a hexadecimal.

Para obtener cada carácter puede iterar a través de la cadena utilizando los métodos charAt() o toCharArray().

for(char c : s.toCharArray()) 

El valor de char es el valor Unicode.

Los personajes son Cyrillic Unicode cualquier carácter en las siguientes gamas:

Cyrillic:   U+0400–U+04FF (1024 - 1279) 
Cyrillic Supplement: U+0500–U+052F (1280 - 1327) 
Cyrillic Extended-A: U+2DE0–U+2DFF (11744 - 11775) 
Cyrillic Extended-B: U+A640–U+A69F (42560 - 42655) 

Si es en este rango es cirílico. Simplemente realice una verificación if. Si está en el rango, use Integer.toHexString() y anteponga "\\u". En su conjunto debe ser algo como esto:

final int[][] ranges = new int[][]{ 
     { 1024, 1279 }, 
     { 1280, 1327 }, 
     { 11744, 11775 }, 
     { 42560, 42655 }, 
    }; 
StringBuilder b = new StringBuilder(); 

for(char c : s.toCharArray()){ 
    int[] insideRange = null; 
    for(int[] range : ranges){ 
     if(range[0] <= c && c <= range[1]){ 
      insideRange = range; 
      break; 
     } 
    } 

    if(insideRange != null){ 
     b.append("\\u").append(Integer.toHexString(c)); 
    }else{ 
     b.append(c); 
    } 
} 

return b.toString(); 

Editar: probablemente debería hacer el cheque c < 128 y revertir los if y los cuerpos else; que probablemente debe escapar de todo lo que no es ASCII. Probablemente fui demasiado literal al leer tu pregunta.

+0

Esta es la respuesta correcta en mi contexto. Sin embargo, creo que "getCharArray()" debería ser "toCharArray". –

+0

@JenS. Gracias, de hecho, el método es de hecho ['toCharArray()'] (http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#toCharArray()). – ArtB

+0

¡Esto no es correcto para todos los caracteres Unicode! p.ej. para el alemán 'Ä', devuelve' \ uC4', no '\ u00c4'. – mik01aj

7

Hay una herramienta de línea de comandos que se incluye con Java llamados native2ascii. Esto convierte archivos Unicode a archivos escapados de ASCII. Descubrí que este es un paso necesario para generar archivos .properties para la localización.

14

también he tenido este problema. Tenía un texto en portugués con algunos caracteres especiales, pero estos personajes ya están en formato Unicode (por ejemplo: \u00e3).

así que quiero convertir a S\u00e3oSão.

lo hice uso de los bienes comunes de Apache StringEscapeUtils. Como dijo @ sorin-sbarnea. Se puede descargar here.

Utilice el método unescapeJava, así:

String text = "S\u00e3o" 
text = StringEscapeUtils.unescapeJava(text); 
System.out.println("text " + text); 

(También existe el método escapeJava, pero éste pone los caracteres Unicode en la cadena.)

Si alguien conoce una solución en Java puro, díganos.

+0

Lo estás haciendo al revés, eso no es lo que OP pidió. – mik01aj

+0

m01 tiene razón, me alegro de que haya respondido así aunque – Danielson

42

hay un JDK tools ejecutado a través de la línea de comandos de la siguiente manera:

native2ascii -encoding utf8 src.txt output.txt 

Ejemplo:

src.txt

بسم الله الرحمن الرحيم 

output.txt

\u0628\u0633\u0645 \u0627\u0644\u0644\u0647 \u0627\u0644\u0631\u062d\u0645\u0646 \u0627\u0644\u0631\u062d\u064a\u0645 

Si desea utilizarlo en la aplicación Java, se puede envolver esta línea de comandos por:

String pathSrc = "./tmp/src.txt"; 
String pathOut = "./tmp/output.txt"; 
String cmdLine = "native2ascii -encoding utf8 " + new File(pathSrc).getAbsolutePath() + " " + new File(pathOut).getAbsolutePath(); 
Runtime.getRuntime().exec(cmdLine); 
System.out.println("THE END"); 

Luego leer el contenido del nuevo archivo.

+3

Puede hacerlo sin iniciar un subproceso, consulte http://stackoverflow.com/a/6017769/115493 – mik01aj

+0

Este [gist] (https://gist.github.com/ulisseslima/d614a31b73947471e04176b0951527bd) envuelve el ejemplo de la línea de comandos en un script Bash para que sea más fácil de usar. – dvlcube

13

Aquí es una versión mejorada del ArtB's answer:

StringBuilder b = new StringBuilder(); 

    for (char c : input.toCharArray()) { 
     if (c >= 128) 
      b.append("\\u").append(String.format("%04X", (int) c)); 
     else 
      b.append(c); 
    } 

    return b.toString(); 

Esta versión se escapa todos los caracteres no ASCII y funciona correctamente para puntos de código Unicode bajas como Ä.

+0

funciona para caracteres multibyte, p. cuando 4-6-8 bytes (2, 3, 4 valores de java ** char **) en una fila representan solo un símbolo? – radistao

0

Probablemente se podría piratear si desde este código JavaScript:

/* convert to \uD83D\uDE4C */ 
function text_to_unicode(string) { 
    'use strict'; 

    function is_whitespace(c) { return 9 === c || 10 === c || 13 === c || 32 === c; } 
    function left_pad(string) { return Array(4).concat(string).join('0').slice(-1 * Math.max(4, string.length)); } 

    string = string.split('').map(function(c){ return "\\u" + left_pad(c.charCodeAt(0).toString(16).toUpperCase()); }).join(''); 

    return string; 
} 


/* convert \uD83D\uDE4C to */ 
function unicode_to_text(string) { 
    var prefix = "\\\\u" 
    , regex = new RegExp(prefix + "([\da-f]{4})","ig") 
    ; 

    string = string.replace(regex, function(match, backtrace1){ 
    return String.fromCharCode(parseInt(backtrace1, 16)) 
    }); 

    return string; 
} 

fuente: iCompile - Yet Another JavaScript Unicode Encode/Decode

3

Commons Apache StringEscapeUtils.escapeEcmaScript(String) devuelve una cadena con caracteres Unicode escapada utilizando la notación \u.

"Art of Beer " -> "Art of Beer \u1F3A8 \u1F37A" 
0

Sólo algunos métodos básicos para que (inspirado de la herramienta native2ascii):

/** 
* Encode a String like äöü to \u00e4\u00f6\u00fc 
* 
* @param text 
* @return 
*/ 
public String native2ascii(String text) { 
    if (text == null) 
     return text; 
    StringBuilder sb = new StringBuilder(); 
    for (char ch : text.toCharArray()) { 
     sb.append(native2ascii(ch)); 
    } 
    return sb.toString(); 
} 

/** 
* Encode a Character like ä to \u00e4 
* 
* @param ch 
* @return 
*/ 
public String native2ascii(char ch) { 
    if (ch > '\u007f') { 
     StringBuilder sb = new StringBuilder(); 
     // write \udddd 
     sb.append("\\u"); 
     StringBuffer hex = new StringBuffer(Integer.toHexString(ch)); 
     hex.reverse(); 
     int length = 4 - hex.length(); 
     for (int j = 0; j < length; j++) { 
      hex.append('0'); 
     } 
     for (int j = 0; j < 4; j++) { 
      sb.append(hex.charAt(3 - j)); 
     } 
     return sb.toString(); 
    } else { 
     return Character.toString(ch); 
    } 
}