web-dev-qa-db-ja.com

Unicodeエンコーディングの文字列を文字列に変換する方法

nicode encoding、\uXXXXの文字列があり、それを通常の文字に変換したい( TF-8 )。例えば:

String myString = "\u0048\u0065\u006C\u006C\u006F World";

になるはずです

"Hello World"

文字列を印刷すると、Hello worldと表示されることがわかります。私の問題は、Unixマシン上のファイルからファイル名を読み取ってから検索することです。ファイル名にはUnicodeエンコードが使用されています。ファイルを検索すると、名前に\uXXXXが含まれるファイルが検索されるため、ファイルが見つかりません。

62
SharonBL

技術的に行うこと:

String myString = "\u0048\u0065\u006C\u006C\u006F World";

自動的に"Hello World"に変換するため、何らかのファイルから文字列を読み込んでいると思います。それを "Hello"に変換するには、テキストを個別のUnicode数字に解析する必要があります(\uXXXXを取得してXXXXを取得する)、Integer.ParseInt(XXXX, 16)を実行して16進値を入力し、charに変換して実際の文字を取得します。

編集:これを達成するためのコード:

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
38
NominSim

Apache Commons LangStringEscapeUtils.unescapeJava()は適切にデコードできます。

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
74
Tony

Apache Commons Lang からStringEscapeUtilsを使用できます。つまり:

String Title = StringEscapeUtils.unescapeJava("\u0048\u0065\u006C\u006C\u006F");

23
Pedro Lobito

バイトエンコーディングと文字列

Javaで、文字列(String)内のバイトストリーム(バイト[])を変換してStringクラスに戻すには、次の機能があります。

コンストラクターString (byte [] bytes, String enc)は、コーディングされたバイトの入力ストリームを受け取ります。エンコードが省略された場合、デフォルトで受け入れられます

getBytes Method (String enc)は、指定されたエンコーディングで記​​録されたバイトストリームを返します。エンコードも省略できます。

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();
}

UPDATE:

Java 1.7は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);
16
bigspawn

この単純な方法はほとんどの場合に機能しますが、文字列「\ u0048」にデコードする必要がある「u005Cu005C」のようなものにつまずきますが、最初のパスでは「\ u0048」を作業文字列として実際に「H」をデコードしますその後、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;
}
7
andrew pate

短いバージョン:

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;
}
4
ssuukk

あなたの質問から完全に明確ではありませんが、私はあなたがそのファイルの各行がファイル名であるファイルがあると言っていると仮定しています。そして、各ファイル名は次のようなものです。

\u0048\u0065\u006C\u006C\u006F

つまり、ファイル名のファイル内の文字は、\u0048などです。

もしそうなら、あなたが見ているものが期待されます。 Javaは、ソースコード内の文字列リテラル内の\uXXXXシーケンスのみを変換します(保存されたPropertiesオブジェクトを読み取る場合)。ファイルする内容を読むと、文字\u0048などで構成される文字列があり、not文字列Hello

したがって、その文字列を解析して00480065などの部分を抽出し、それらをcharsに変換し、それらのcharsから文字列を作成してから、その文字列を開くルーチンに渡す必要がありますファイル。

4
QuantumMechanic

試してみる

private static final Charset UTF_8 = Charset.forName("UTF-8");
private String forceUtf8Coding(String input) {return new String(input.getBytes(UTF_8), UTF_8))}
3
haohcraft

jsonObjectを使用して知っている1つの簡単な方法:

try {
    JSONObject json = new JSONObject();
    json.put("string", myString);
    String converted = json.getString("string");

} catch (JSONException e) {
    e.printStackTrace();
}
1
Ashkan Ghodrat

パフォーマンスとエラー防止のソリューションを作成しました。

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();
}
0
neoedmund

Org.Apache.commons.lang3ライブラリのStringEscapeUtilsは、3.6の時点で 非推奨 です。

そのため、代わりに新しい 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>

サンプルコード:

org.Apache.commons.text.StringEscapeUtils.unescapeJava(escapedString);
0

ここに私の解決策があります...

                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;
                    }
                };
0
AndyW58

Apache Commons Langの使用を示唆する回答に関する更新、 StringEscapeUtils.unescapeJava() 非推奨になりました。置換はApache Commons TextStringEscapeUtils.unescapeJava()

0
user7294900

それを行うもう2つの方法は

//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();
0
Manoj Krishna

私は、答えの多くが「補助文字」の問題に対処していないことがわかりました。これをサポートする正しい方法を次に示します。サードパーティのライブラリはありません。純粋なJava実装です。

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
0
lovestackh343

これを実現する別の方法は、 chars() Java 9で導入されたものを利用することです。 サロゲートコードポイント にマップされるcharが解釈されずにパススルーされることを確認する文字。これは次のように使用できます。

String myString = "\u0048\u0065\u006C\u006C\u006F World";
myString.chars().forEach(a -> System.out.print((char)a));
// would print "Hello World"
0
Naman

Kotlinのソリューション:

val result = String(someText.toByteArray())

KotlinはデフォルトのエンコーディングとしてどこでもUTF-8を使用します

また、Stringクラスの拡張として実装することもできます。

fun String.unescape(): String {
    return String(this.toByteArray())
}

そしてそれを簡単に使用します:

val result = someText.unescape()

;)

0
Evgeny Lebedev

実際、私はいくつかのユーティリティを含むオープンソースライブラリを書きました。それらの1つは、Unicodeシーケンスを文字列に変換することです。とても便利だと思いました。以下に、Unicodeコンバータに関するこのライブラリに関する記事の引用を示します。

クラスStringUnicodeEncoderDecoderには、文字列(任意の言語)をUnicode文字のシーケンスに変換したり、その逆を行うことができるメソッドがあります。たとえば、文字列「Hello World」は次のように変換されます

「\ u0048\u0065\u006c\u006c\u006f\u0020\u0057\u006f\u0072\u006c\u0064」

復元される場合があります。

ライブラリのユーティリティとライブラリを使用する方法を説明する記事全体へのリンクがあります。 Mavenアーティファクトとして、またはGithubからソースとして入手できます。使い方はとても簡単です。 スタックトレースフィルタリング、サイレントストリング解析Unicodeコンバーター、バージョン比較を備えたオープンソースJavaライブラリ

0
Michael Gantman