如何在Java中将UTF-8表示解析为字符串?

如何在Java中将UTF-8表示解析为字符串?,java,utf-8,ascii,Java,Utf 8,Ascii,给定以下代码: String tmp = new String("\\u0068\\u0065\\u006c\\u006c\\u006f\\u000a"); String result = convertToEffectiveString(tmp); // result contain now "hello\n" JDK是否已经提供了一些这样做的类? 有这样的图书馆吗?(最好在maven下) 我尝试了ByteArrayOutputStream,但没有成功。首先,您只是尝试解析字符串文字,还是

给定以下代码:

String tmp = new String("\\u0068\\u0065\\u006c\\u006c\\u006f\\u000a");

String result = convertToEffectiveString(tmp); // result contain now "hello\n"
JDK是否已经提供了一些这样做的类? 有这样的图书馆吗?(最好在maven下)


我尝试了ByteArrayOutputStream,但没有成功。

首先,您只是尝试解析字符串文字,还是
tmp
将成为用户输入的数据

如果这将是字符串文字(即硬编码字符串),则可以使用Unicode转义对其进行编码。在您的情况下,这只意味着使用单反斜杠而不是双反斜杠:

String result = "\u0068\u0065\u006c\u006c\u006f\u000a";
但是,如果您需要使用Java的字符串解析规则来解析用户输入,一个很好的起点可能是Apache Commons Lang的方法。

我相信一定有更好的方法,但只使用JDK:

public static String handleEscapes(final String s)
{
    final java.util.Properties props = new java.util.Properties();
    props.setProperty("foo", s);
    final java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();
    try
    {
        props.store(baos, null);
        final String tmp = baos.toString().replace("\\\\", "\\");
        props.load(new java.io.StringReader(tmp));
    }
    catch(final java.io.IOException ioe) // shouldn't happen
        { throw new RuntimeException(ioe); }
    return props.getProperty("foo");
}
用于处理反斜杠转义(首先使用反斜杠转义会在属性文件中引起问题的任何内容,然后使用
replace(“\\\\”,“\\”)
来反转原始反斜杠的反斜杠转义)


(免责声明:尽管我测试了我能想到的所有案例,但仍有一些可能是我没有想到的。)

这是可行的,但只适用于ASCII。如果使用ASCCI范围之外的unicode字符,则会出现问题(因为每个字符都被填充到一个字节中,而不是UTF-8允许的完整字)。您可以执行下面的类型转换,因为您知道,如果您保证输入基本上是ASCII(正如您在注释中提到的),UTF-8将不会溢出一个字节

下面是另一个解决方案,它修复了仅使用ASCII字符的问题。这将适用于UTF-8范围内的任何unicode字符,而不是仅适用于该范围前8位的ASCII字符。谢谢deceze的提问。你让我更多地思考问题和解决方案

package sample;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;

public class UnicodeSample {
    public static final int HEXADECIMAL = 16;

    public static void main(String[] args) {

        try {
            String str = "\\u0068\\u0065\\u006c\\u006c\\u006f\\u000a\\u3fff\\uf34c";

            ArrayList<Byte> arrList = new ArrayList<Byte>();
            String codes[] = str.replaceAll("\\\\u"," ").trim().split(" ");

            for (String c : codes) {

                int code = Integer.parseInt(c,HEXADECIMAL);
                byte[] bytes = intToByteArray(code);

                for (byte b : bytes) {
                    if (b != 0) arrList.add(b);
                }
            }

            byte[] utf8 = new byte[arrList.size()];
            for (int i=0; i<arrList.size(); i++) utf8[i] = arrList.get(i);

            str = new String(utf8, "UTF-8");
            System.out.println(str);
        }
        catch (UnsupportedEncodingException e) {
            // handle the exception when
        }
    }

    // Takes a 4 byte integer and and extracts each byte
    public static final byte[] intToByteArray(int value) {
        return new byte[] {
                (byte) (value >>> 24),
                (byte) (value >>> 16),
                (byte) (value >>> 8),
                (byte) (value)
        };
    }
}
包装样品;
导入java.io.UnsupportedEncodingException;
导入java.util.ArrayList;
公共类UnicodeSample{
公共静态final int十六进制=16;
公共静态void main(字符串[]args){
试一试{
字符串str=“\\u0068\\u0065\\u006c\\u006c\\u006f\\u000a\\u3fff\\uf34c”;
ArrayList arrList=新的ArrayList();
字符串代码[]=str.replaceAll(“\\\\u”,”).trim().split(“”);
用于(字符串c:代码){
int code=Integer.parseInt(c,十六进制);
字节[]字节=intToByteArray(代码);
for(字节b:字节){
如果(b!=0),则添加(b);
}
}
字节[]utf8=新字节[arrList.size()];
对于(int i=0;i>>24),
(字节)(值>>>16),
(字节)(值>>>8),
(字节)(值)
};
}
}

这不是UTF-8;这只是一个包含Unicode转义表示的字符串。“UTF-8以外的Unicode字符”是什么?如何将Unicode/UTF-8字符“塞入字节”?我不知道你的意思是否正确,并且表达得不够清楚,但这读起来大错特错。如果在字符串“str”中使用UTF-8以外的其他unicode字符集,则此代码可能无法工作。UTF-8仍然使用8位,而其他unicode字符集可能(可能)使用8位以上(全部16位)。显然,在一般情况下,这段代码是不够的。但在我的例子中,输入保证完全可转换为ASCII。@jmq您的意思是,如果源代码编码的字符集与UTF-8不同(我认为这在Java中并不重要)?因为,虽然我并不真正了解Java,但这些看起来像Unicode代码点,而不是UTF-8特定的字节@jmq-Hmm,您更正的语句更有意义,但是UTF-8将使用多个字节来表示非ASCII字符。这一个正好起作用,因为文本基本上只是ASCII,但对于实际包含“Unicode字符”(即非ASCII字符)的情况,它将失败。
package sample;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;

public class UnicodeSample {
    public static final int HEXADECIMAL = 16;

    public static void main(String[] args) {

        try {
            String str = "\\u0068\\u0065\\u006c\\u006c\\u006f\\u000a\\u3fff\\uf34c";

            ArrayList<Byte> arrList = new ArrayList<Byte>();
            String codes[] = str.replaceAll("\\\\u"," ").trim().split(" ");

            for (String c : codes) {

                int code = Integer.parseInt(c,HEXADECIMAL);
                byte[] bytes = intToByteArray(code);

                for (byte b : bytes) {
                    if (b != 0) arrList.add(b);
                }
            }

            byte[] utf8 = new byte[arrList.size()];
            for (int i=0; i<arrList.size(); i++) utf8[i] = arrList.get(i);

            str = new String(utf8, "UTF-8");
            System.out.println(str);
        }
        catch (UnsupportedEncodingException e) {
            // handle the exception when
        }
    }

    // Takes a 4 byte integer and and extracts each byte
    public static final byte[] intToByteArray(int value) {
        return new byte[] {
                (byte) (value >>> 24),
                (byte) (value >>> 16),
                (byte) (value >>> 8),
                (byte) (value)
        };
    }
}