有什么区别
String(s.getBytes("UTF-8"),"UTF-8");
和
String(s.getBytes(),"UTF-8");
在第一个代码示例中,一些特殊字符被解码了,为什么?有什么区别?
如果我对UTF-8
使用双重解码会不会有什么影响?
答案 0 :(得分:5)
来自javadoc:
对于getBytes()
:
使用平台的默认字符集将此字符串编码为字节序列,并将结果存储到新的字节数组中。
getBytes(Charset)
说:
使用给定的字符集将此字符串编码为字节序列,并将结果存储到新的字节数组中。
因此,第二个版本允许您完全控制,第一个调用依赖于该平台的默认字符集。
这就是全部。
答案 1 :(得分:3)
因此,您要询问以下两行:
main()
这两条线都没有做任何有用的事情。第2行甚至比第1行还差;它可能不仅没有用,而且还会出错,具体取决于系统的默认字符编码是什么。
第1行实际上什么也没做。它使用UTF-8字符编码将字符串
import (
"fmt"
"io"
"log"
"os"
"os/exec"
)
var pager io.WriteCloser
func main() {
var cmd *exec.Cmd
cmd, pager = runPager()
defer func() {
pager.Close()
cmd.Wait()
}()
fmt.Fprintln(pager, "Hello, 世界")
}
func runPager() (*exec.Cmd, io.WriteCloser) {
pager := os.Getenv("PAGER")
if pager == "" {
pager = "more"
}
cmd := exec.Command(pager)
out, err := cmd.StdinPipe()
if err != nil {
log.Fatal(err)
}
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Start(); err != nil {
log.Fatal(err)
}
return cmd, out
}
编码为字节,然后立即使用UTF-8将字节解码回字符串。字符串String s1 = new String(s.getBytes("UTF-8"), "UTF-8"); // line 1
String s2 = new String(s.getBytes(), "UTF-8"); // line 2
将始终与原始字符串完全相同;编码和解码就没用了。
第2行的功能取决于系统上使用的默认字符编码。如果默认字符编码为UTF-8,则其与第1行完全相同。如果它与UTF-8不同,则将得到错误解码的字符串。
假设系统的默认字符编码为ISO-8859-1。然后,第2行使用ISO-8859-1对字符串进行编码,然后立即对结果进行解码,就好像它是UTF-8一样-这是错误的。您可能会得到一个字符串,其中包含错误解码的字符,甚至是异常。
阅读您正在使用的方法的API文档,以了解它们的确切作用:
答案 2 :(得分:1)
问题中包含的两个例子都是胡说八道。
Java String
作为UTF-16代码点的数组存储在内存中。
现在将byte[]
标识为UTF-8代码点数组为时已晚
表示数组已经转换为字符串,
如果您收到一个byte []并想将其存储为String, 那么这样做很有意义:
//assume input byte[] kapow
String blammy = new String(kapow, StandardCharsets.UTF_8);
如果您有一个String值,并想将其作为字节写到某处[] 使用UTF-8编码, 那么这很有意义
// assume input String blammy
byte[] kapow = blammy.getBytes(StandardCharsets.UTF_8);
请注意,在两种情况下,我都使用了该方法的(blah,Charset)版本。 做这个。 (blah,“ UTF-8”)版本会引发一个已检查的异常。 (空白,Charset)版本永远不会引发异常,而StandardCharsets类会这样做(从StandardCharsets JavaDoc页面):
标准字符集的常量定义。这些字符集保证可以在Java平台的每种实现中使用。