J'ai une chaîne avec Unicode encoding, \uXXXX
et je veux la convertir en lettre normale ( UTF-8 ). Par exemple:
String myString = "\u0048\u0065\u006C\u006C\u006F World";
devraient devenir
"Hello World"
Je sais que lorsque j'imprime la chaîne, il affiche Hello world
. Mon problème est que je lis les noms de fichiers d'un fichier sur une machine Unix, puis je les recherche. Les noms de fichiers sont codés en Unicode et lorsque je recherche les fichiers, je ne les trouve pas, car ils recherchent un fichier avec \uXXXX
dans son nom.
Faire techniquement:
String myString = "\u0048\u0065\u006C\u006C\u006F World";
le convertit automatiquement en "Hello World"
, donc je suppose que vous lisez dans la chaîne à partir d'un fichier. Pour le convertir en "Bonjour", vous devrez analyser le texte dans les chiffres unicodes séparés (prenez le \uXXXX
et récupérez simplement XXXX
), puis exécutez Integer.ParseInt(XXXX, 16)
pour obtenir une valeur hexadécimale, puis définissez la valeur char
personnage.
Edit: Du code pour accomplir ceci:
String str = myString.split(" ")[0];
str = str.replace("\\","");
String[] arr = str.split("u");
String text = "";
for(int i = 1; i < arr.length; i++){
int hexVal = Integer.parseInt(arr[i], 16);
text += (char)hexVal;
}
// Text will now have Hello
Le Apache Commons LangStringEscapeUtils.unescapeJava () peut le décoder correctement.
import org.Apache.commons.lang.StringEscapeUtils;
@Test
public void testUnescapeJava() {
String sJava="\\u0048\\u0065\\u006C\\u006C\\u006F";
System.out.println("StringEscapeUtils.unescapeJava(sJava):\n" + StringEscapeUtils.unescapeJava(sJava));
}
output:
StringEscapeUtils.unescapeJava(sJava):
Hello
Vous pouvez utiliser StringEscapeUtils
de Apache Commons Lang , c'est-à-dire:
String Title = StringEscapeUtils.unescapeJava("\u0048\u0065\u006C\u006C\u006F");
En Java, la conversion du flux d'octets (byte []) dans la chaîne (String) et son retour à la classe String présentent les caractéristiques suivantes:
Le constructeur String (byte [] bytes, String enc)
reçoit le flux d'octets en entrée avec leur codage; si l'encodage est omis, il sera accepté par défaut
getBytes Method (String enc)
renvoie un flux d'octets enregistré dans le codage spécifié; l'encodage peut également être omis.
try {
String myString = "\u0048\u0065\u006C\u006C\u006F World";
byte[] utf8Bytes = myString.getBytes("UTF8");
String text = new String(utf8Bytes,"UTF8");
}
catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
METTRE À JOUR:
Depuis Java 1.7, utilisez StandardCharsets.UTF_8
:
String utf8Text = "\u0048\u0065\u006C\u006C\u006F World";
byte[] bytes = utf8Text.getBytes(StandardCharsets.UTF_8);
String text = new String(bytes, StandardCharsets.UTF_8);
Cette méthode simple fonctionnera dans la plupart des cas, mais trébucherait sur quelque chose comme "u005Cu005C" qui devrait être décodé en chaîne "\ u0048" mais décoderait en fait "H" car le premier passage produirait "\ u0048" est ensuite traité à nouveau par la boucle while.
static final String decode(final String in)
{
String working = in;
int index;
index = working.indexOf("\\u");
while(index > -1)
{
int length = working.length();
if(index > (length-6))break;
int numStart = index + 2;
int numFinish = numStart + 4;
String substring = working.substring(numStart, numFinish);
int number = Integer.parseInt(substring,16);
String stringStart = working.substring(0, index);
String stringEnd = working.substring(numFinish);
working = stringStart + ((char)number) + stringEnd;
index = working.indexOf("\\u");
}
return working;
}
Cela ne ressort pas clairement de votre question, mais je suppose que vous dites que vous avez un fichier où chaque ligne de ce fichier est un nom de fichier. Et chaque nom de fichier ressemble à ceci:
\u0048\u0065\u006C\u006C\u006F
En d'autres termes, les caractères dans le fichier des noms de fichiers sont \
, u
, 0
, 0
, 4
, 8
et ainsi de suite.
Si c'est le cas, ce que vous voyez est attendu. Java ne traduit que les séquences \uXXXX
en chaînes littérales en code source (et lors de la lecture d'objets Properties
stockés). Lorsque vous lisez le contenu de votre fichier, vous obtenez une chaîne composée des caractères \
, u
, 0
, 0
, 4
, 8
et ainsi de suite et not de la chaîne Hello
.
Vous devrez donc analyser cette chaîne pour extraire les éléments 0048
, 0065
, etc., puis les convertir en char
s, créer une chaîne à partir de ces char
s, puis les transmettre à la routine qui ouvre le fichier.
Version plus courte:
public static String unescapeJava(String escaped) {
if(escaped.indexOf("\\u")==-1)
return escaped;
String processed="";
int position=escaped.indexOf("\\u");
while(position!=-1) {
if(position!=0)
processed+=escaped.substring(0,position);
String token=escaped.substring(position+2,position+6);
escaped=escaped.substring(position+6);
processed+=(char)Integer.parseInt(token,16);
position=escaped.indexOf("\\u");
}
processed+=escaped;
return processed;
}
essayer
private static final Charset UTF_8 = Charset.forName("UTF-8");
private String forceUtf8Coding(String input) {return new String(input.getBytes(UTF_8), UTF_8))}
un moyen facile, je sais en utilisant JsonObject:
try {
JSONObject json = new JSONObject();
json.put("string", myString);
String converted = json.getString("string");
} catch (JSONException e) {
e.printStackTrace();
}
J'ai écrit une solution performancée et résistante aux erreurs:
public static final String decode(final String in) {
int p1 = in.indexOf("\\u");
if (p1 < 0)
return in;
StringBuilder sb = new StringBuilder();
while (true) {
int p2 = p1 + 6;
if (p2 > in.length()) {
sb.append(in.subSequence(p1, in.length()));
break;
}
try {
int c = Integer.parseInt(in.substring(p1 + 2, p1 + 6), 16);
sb.append((char) c);
p1 += 6;
} catch (Exception e) {
sb.append(in.subSequence(p1, p1 + 2));
p1 += 2;
}
int p0 = in.indexOf("\\u", p1);
if (p0 < 0) {
sb.append(in.subSequence(p1, in.length()));
break;
} else {
sb.append(in.subSequence(p1, p0));
p1 = p0;
}
}
return sb.toString();
}
StringEscapeUtils de la bibliothèque org.Apache.commons.lang3 est obsolète à partir de 3.6.
Vous pouvez donc utiliser leur nouvelle bibliothèque commons-text :
compile 'org.Apache.commons:commons-text:1.7'
OR
<dependency>
<groupId>org.Apache.commons</groupId>
<artifactId>commons-text</artifactId>
<version>1.7</version>
</dependency>
Exemple de code:
org.Apache.commons.text.StringEscapeUtils.unescapeJava(escapedString);
Voici ma solution ...
String decodedName = JwtJson.substring(startOfName, endOfName);
StringBuilder builtName = new StringBuilder();
int i = 0;
while ( i < decodedName.length() )
{
if ( decodedName.substring(i).startsWith("\\u"))
{
i=i+2;
builtName.append(Character.toChars(Integer.parseInt(decodedName.substring(i,i+4), 16)));
i=i+4;
}
else
{
builtName.append(decodedName.charAt(i));
i = i+1;
}
};
Mises à jour concernant les réponses suggérant d’utiliser The Apache Commons Lang's, StringEscapeUtils.unescapeJava () il est devenu obsolète, le remplacement est Apache Commons Text ' StringEscapeUtils.unescapeJava ()
Deux autres façons de faire serait
//This is what StringBuilder internally does on calling toString() Method
char[] charArray = "\u0048\u0065\u006C\u006C\u006F World".toCharArray();
String output = new String(charArray, 0, charArray.length);
//To do it in single line
String output = new StringBuilder("\u0048\u0065\u006C\u006C\u006F World").toString();
J'ai trouvé que beaucoup de réponses n'abordaient pas la question des "caractères supplémentaires". Voici la bonne façon de le supporter. Pas de bibliothèques tierces, implémentation Java pure.
http://www.Oracle.com/us/technologies/Java/supplementary-142654.html
public static String fromUnicode(String unicode) {
String str = unicode.replace("\\", "");
String[] arr = str.split("u");
StringBuffer text = new StringBuffer();
for (int i = 1; i < arr.length; i++) {
int hexVal = Integer.parseInt(arr[i], 16);
text.append(Character.toChars(hexVal));
}
return text.toString();
}
public static String toUnicode(String text) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < text.length(); i++) {
int codePoint = text.codePointAt(i);
// Skip over the second char in a surrogate pair
if (codePoint > 0xffff) {
i++;
}
String hex = Integer.toHexString(codePoint);
sb.append("\\u");
for (int j = 0; j < 4 - hex.length(); j++) {
sb.append("0");
}
sb.append(hex);
}
return sb.toString();
}
@Test
public void toUnicode() {
System.out.println(toUnicode("????"));
System.out.println(toUnicode("????"));
System.out.println(toUnicode("Hello World"));
}
// output:
// \u1f60a
// \u1f970
// \u0048\u0065\u006c\u006c\u006f\u0020\u0057\u006f\u0072\u006c\u0064
@Test
public void fromUnicode() {
System.out.println(fromUnicode("\\u1f60a"));
System.out.println(fromUnicode("\\u1f970"));
System.out.println(fromUnicode("\\u0048\\u0065\\u006c\\u006c\\u006f\\u0020\\u0057\\u006f\\u0072\\u006c\\u0064"));
}
// output:
// ????
// ????
// Hello World
Solution pour Kotlin:
val result = String(someText.toByteArray())
Kotlin utilise UTF-8 partout comme encodage par défaut
Vous pouvez aussi l'implémenter comme extension pour la classe String:
fun String.unescape(): String {
return String(this.toByteArray())
}
et ensuite utilisez-le simple:
val result = someText.unescape()
;)
En fait, j'ai écrit une bibliothèque Open Source contenant des utilitaires. L'un d'eux consiste à convertir une séquence Unicode en String et inversement. Je l'ai trouvé très utile. Voici la citation de l'article sur cette bibliothèque sur le convertisseur Unicode:
La classe StringUnicodeEncoderDecoder a des méthodes permettant de convertir un Chaîne (dans n'importe quelle langue) en une séquence de caractères Unicode et vice versa. Par exemple, une chaîne "Hello World" sera convertie en
"\ u0048\u0065\u006c\u006c\u006f\u0020\u0057\u006f\u0072\u006c\u0064"
et peut être restauré.
Voici le lien vers l'article complet qui explique quels utilitaires ont la bibliothèque et comment obtenir son utilisation par la bibliothèque. Il est disponible sous forme d'artefact Maven ou de source auprès de Github. C'est très facile à utiliser. Bibliothèque Java Open Source avec filtrage de trace de pile, conversion silencieuse de chaînes Unicode et comparaison de versions