将字符串编码为UTF-8


190

我有一个带有“ñ”字符的字符串,并且我有一些问题。我需要将此字符串编码为UTF-8编码。我已经通过这种方式尝试过,但是没有用:

byte ptext[] = myString.getBytes();
String value = new String(ptext, "UTF-8");

如何将该字符串编码为utf-8?


2
目前尚不清楚您到底想做什么。myString是否正确包含ñ字符,并且在将其转换为字节数组时遇到问题(在这种情况下,请参阅Peter和Amir的答案),或者myString已损坏,您正在尝试对其进行修复(在这种情况下,请参阅Joachim的答案)和我)?
Michael Borgwardt

我需要将myString发送到使用utf-8编码的服务器,并且需要将“ñ”字符转换为utf-8编码。
Alex

1
好吧,如果该服务器需要UTF-8,则您需要发送的是字节,而不是字符串。因此,根据彼得的回答,在第一行中指定编码,然后删除第二行。
Michael Borgwardt

@Michael:我同意目前尚不清楚真正的意图。人们似乎试图在字符串和字节之间进行显式转换,而不是让{In,Out}putStream{Read,Writ}ers它们为它们做转换,这似乎有很多问题。我想知道为什么?
tchrist 2011年

1
@Michael:谢谢,我想这很有道理。但这也使它变得比原来需要的难,不是吗?我不太喜欢这种方式的语言,因此请尽量避免使用它们。我认为Java的字符串字符串模型而不是字节模型使事情变得容易得多。Perl和Python也共享“一切都是Unicode字符串”模型。是的,在这三种情况下,如果您仍然可以使用字节,那么在实际中似乎很少需要真正做到这一点:这是非常低级的。另外,如果您知道我的意思,那感觉有点像往错误的方向刷猫。:)
tchrist 2011年

Answers:


140

String Java中的对象使用无法修改的UTF-16编码。

唯一可以使用不同编码的是byte[]。因此,如果您需要UTF-8数据,则需要一个byte[]。如果您有一个String包含意外数据的,则问题出在较早的地方,该错误地将一些二进制数据错误地转换为a String(即,使用了错误的编码)。


92
从技术上讲,byte []没有任何编码。字节数组PLUS编码可以为您提供字符串。
PeterŠtibraný2011年

1
@Peter:是的。但是,将编码附加到它只对有意义byte[],而没有意义String(除非编码是UTF-16,在这种情况下它是有意义的,但仍然是不必要的信息)。
Joachim Sauer

4
String objects in Java use the UTF-16 encoding that can't be modified. 您对此报价有官方消息吗?
艾哈迈德·哈贾尔

@AhmadHajjar docs.oracle.com/javase/10/docs/api/java/lang/…:“Java平台在char数组以及String和StringBuffer类中使用UTF-16表示形式。”
Maxi Gis,

173

怎么样使用

ByteBuffer byteBuffer = StandardCharsets.UTF_8.encode(myString)

请参阅我与彼得的讨论。但是,如果他对这个问题的假设是正确的,则您的解决方案仍然不可行,因为它返回了ByteBuffer。
Michael Borgwardt

8
但是,如何获取编码的String?它返回一个ByteBuffer
Alex

7
@Alex:不可能有UTF-8编码的Java字符串。您需要字节,因此直接使用ByteBuffer(如果您的目标是通过网络集合发送字节缓冲区,则可能是最好的解决方案),或者在其上调用array()以获取字节[]
Michael Borgwardt

2
其他可能有用的方法是使用Guava的Charsets.UTF_8枚举,而不是可能引发UnsupportedEncodingException的String。字符串->字节:myString.getBytes(Charsets.UTF_8)和字节->字符串:new String(myByteArray, Charsets.UTF_8)
laughing_man

24
更好的是使用StandardCharsets.UTF_8。在Java 1.7+中可用。
2014年

81

在Java7中,您可以使用:

import static java.nio.charset.StandardCharsets.*;

byte[] ptext = myString.getBytes(ISO_8859_1); 
String value = new String(ptext, UTF_8); 

它具有getBytes(String)不声明的优点throws UnsupportedEncodingException

如果您使用的是较旧的Java版本,则可以自己声明字符集常量:

import java.nio.charset.Charset;

public class StandardCharsets {
    public static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1");
    public static final Charset UTF_8 = Charset.forName("UTF-8");
    //....
}

2
这是正确的答案。如果有人要使用字符串数据类型,则可以以正确的格式使用它。其余的答案都指向字节格式的类型。
Neeraj Shukla 2015年

在6中工作。谢谢。
Itsik Mauyhas

也为我提供正确答案。但是,有一件事,当我如上所述使用时,德语字符更改为?。所以,我用了这个:byte [] ptext = myString.getBytes(UTF_8); 字符串值=新的String(ptext,UTF_8); 这很好。
法罕·哈菲兹

3
代码示例没有意义。如果您首先转换为ISO-8859-1,则该字节数组不是 UTF-8,因此下一行完全不正确。当然,它将适用于ASCII字符串,但是您也可以制作一个简单的副本:String value = new String(myString);
亚历克西斯威尔克

76

使用byte[] ptext = String.getBytes("UTF-8");代替getBytes()getBytes()使用所谓的“默认编码”,可能不是UTF-8。


9
@Michael:他显然很难从字符串中获取字节。getBytes(encoding)如何遗漏要点?我认为第二行只是检查他是否可以将其转换回去。
PeterŠtibraný11年

1
我将其解释为字符串损坏,并尝试通过转换为字节然后返回(常见的误解)来“修复”它。没有任何实际迹象表明第二行只是在检查结果。
Michael Borgwardt

@Michael,没有,这只是我的解释。您的完全不同。
PeterŠtibraný2011年

1
@Peter:没错,我们需要Alex澄清一下他的真正意思。除非编辑了答案,否则无法取消弃权票
Michael Borgwardt

33

Java字符串内部始终使用UTF-16进行编码-但您确实应该这样考虑:编码是一种在字符串和字节之间进行转换的方法。

因此,如果您遇到编码问题,那么当您有了String时,修复为时已晚。您需要修复从文件,数据库或网络连接创建该字符串的位置。


1
认为字符串在内部编码为UTF-16是一个常见的错误。通常它们是,但是,如果仅仅是String类的实现特定细节。由于无法通过公共API访问字符数据的内部存储,因此特定的String实现可以决定使用任何其他编码。
jarnbjo 2011年

3
@jarnbjo:API明确声明“字符串代表UTF-16格式的字符串”。使用其他任何格式作为内部格式将非常低效,并且我知道的所有实际实现都在内部使用UTF-16。因此,除非您能引用其中一项,否则您将从事非常荒唐的头发拆分。
Michael Borgwardt

区分公共访问和数据结构的内部表示是否荒谬?
jarnbjo 2011年

5
JVM(就与VM完全相关的方面)使用UTF-8进行字符串编码,例如在类文件中。java.lang.String的实现与JVM分离,如果确实需要您认识到答案不正确,则可以使用任何其他编码作为内部表示形式轻松地为您实现该类。在大多数情况下,使用UTF-16作为内部格式在内存消耗方面也非常低效,我不明白为什么嵌入式硬件的Java实现不会针对内存而不是性能进行优化。
jarnbjo 2011年

1
@jarnbjo:再说一次:只要您不能给出JVM的具体示例,其标准API实现内部确实使用UTF-16之外的其他东西来实现String,那么我的说法是正确的。不,由于诸如intern()和常量池之类​​的原因,String类并未真正与JVM分离。
Michael Borgwardt

22

您可以尝试这种方式。

byte ptext[] = myString.getBytes("ISO-8859-1"); 
String value = new String(ptext, "UTF-8"); 

1
我快疯了。感谢您首先获取“ ISO-8859-1”中的字节。
吉安·戈门

2
错了 如果您的字符串包含Unicode字符,则将其转换为8859-1会引发异常,或更糟糕的是,您将得到无效的字符串(可能是不包含代码点为0x100以上的那些字符的字符串)。
亚历克西斯·威尔克

12

过了一会儿,我经历了这个问题,并设法通过以下方式解决了这个问题

首先我需要导入

import java.nio.charset.Charset;

然后我必须声明一个常量来使用UTF-8ISO-8859-1

private static final Charset UTF_8 = Charset.forName("UTF-8");
private static final Charset ISO = Charset.forName("ISO-8859-1");

然后我可以通过以下方式使用它:

String textwithaccent="Thís ís a text with accent";
String textwithletter="Ñandú";

text1 = new String(textwithaccent.getBytes(ISO), UTF_8);
text2 = new String(textwithletter.getBytes(ISO),UTF_8);

1
完美的解决方案。
Tunde bolus。牛鞭:

9
String value = new String(myString.getBytes("UTF-8"));

并且,如果您想读取编码为“ ISO-8859-1”的文本文件,请执行以下操作:

String line;
String f = "C:\\MyPath\\MyFile.txt";
try {
    BufferedReader br = Files.newBufferedReader(Paths.get(f), Charset.forName("ISO-8859-1"));
    while ((line = br.readLine()) != null) {
        System.out.println(new String(line.getBytes("UTF-8")));
    }
} catch (IOException ex) {
    //...
}

2

我使用下面的代码通过指定编码格式来编码特殊字符。

String text = "This is an example é";
byte[] byteText = text.getBytes(Charset.forName("UTF-8"));
//To get original string from byte.
String originalString= new String(byteText , "UTF-8");

2

快速分步指南如何配置NetBeans默认编码UTF-8。结果,NetBeans将以UTF-8编码创建所有新文件。

NetBeans默认编码UTF-8分步指南

  • 转到NetBeans安装目录中的etc文件夹

  • 编辑netbeans.conf文件

  • 查找netbeans_default_options行

  • 在该行内的引号内添加-J-Dfile.encoding = UTF-8

    (例如:netbeans_default_options="-J-Dfile.encoding=UTF-8"

  • 重新启动NetBeans

您将NetBeans设置为默认编码UTF-8。

您的netbeans_default_options可能在引号内包含其他参数。在这种情况下,请在字符串末尾添加-J-Dfile.encoding = UTF-8。用空格将其与其他参数分开。

例:

netbeans_default_options =“-J-client -J-Xss128m -J-Xms256m -J-XX:PermSize = 32m -J-Dapple.laf.useScreenMenuBar = true -J-Dapple.awt.graphics.UseQuartz = true -J-Dsun。 java2d.noddraw = true -J-Dsun.java2d.dpiaware = true -J-Dsun.zip.disableMemoryMapping = true -J-Dfile.encoding = UTF-8”

这是更多详细信息的链接


0

这解决了我的问题

    String inputText = "some text with escaped chars"
    InputStream is = new ByteArrayInputStream(inputText.getBytes("UTF-8"));
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.