为什么DataOutputStream.writeChars(str)和String(byte [])使用相同的编码? [英] Why don't DataOutputStream.writeChars(str) and String(byte[]) use the same encoding?

查看:194
本文介绍了为什么DataOutputStream.writeChars(str)和String(byte [])使用相同的编码?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为一个类项目编写一些编组/解组程序,并且在这种情况下对Java的默认行为有点困惑。这里是我的天真子程序,用于从字节流写入和读取字符串:

  protected static void write(DataOutputStream dout, String str)
throws IOException {
dout.writeInt(str.length());
dout.writeChars(str);
}

protected static String readString(DataInputStream din)
throws IOException {
int strLength = 2 * din.readInt(); // b / c每个char有两个字节
byte [] stringHolder = new byte [strLength];
din.read(stringHolder);
return new String(stringHolder);不幸的是,这根本不起作用,因为它是一个非常有用的工具。默认情况下,字符以UTF-16格式写入,但 String(byte [])似乎假定每个字节都包含一个字符,一个0字节的UTF-16,构造函数似乎只是放弃并返回一个空字符串。解决方法是更改​​ readString 以指定它必须使用UTF-16编码:

  protected static String readString(DataInputStream din)
throws IOException {
int strLength = 2 * din.readInt();
byte [] stringHolder = new byte [strLength];
din.read(stringHolder);
return new String(stringHolder,UTF-16);
}

我的问题是,为什么是必要的?由于Java默认使用UTF-16作为字符串,为什么不从字节读取字符时使用UTF-16?或者,为什么不会将字符编码为字节在默认情况下第一?总之,为什么 writeChars()方法和 String(byte [])构造函数并行?

解决方案

问题是你使用底层的 char [] 这是必需的 byte [] ,表示一个字符串的UTF-16表示形式,参见 javadoc

然后,您将使用 String(byte [] bytes)构造函数,它用于读取使用系统默认编码编码的数据,在这种情况下,大概是UTF-8。

事实上, DataOutputStream.writeUTF() DataInputStream.readUTF()函数是专门为此设计的。

如果你想使用底层的 byte [] ,你可以得到的UTF-8表示,使用 String.getBytes(UTF-8),再次,请参阅 javadoc

为了简化问题,您可以使用 ObjectOutputStream 和一个 ObjectInputStream ,并将序列化实际 String 而不是它的 char [] 表示。


I'm writing some marshaling/unmarshaling routines for a class project and am a bit perplexed about Java's default behavior in this case. Here are my "naive" subroutines for writing and reading strings to and from byte streams:

protected static void write(DataOutputStream dout, String str)
        throws IOException{
    dout.writeInt(str.length());
    dout.writeChars(str);
}

protected static String readString(DataInputStream din)
        throws IOException{
    int strLength = 2*din.readInt(); // b/c there are two bytes per char
    byte[] stringHolder = new byte[strLength];
    din.read(stringHolder);
    return new String(stringHolder);
}

Unfortunately, this simply doesn't work; the characters are written in UTF-16 format by default, but String(byte[]) seems to assume that each byte will contain a character, and since ASCII characters all start with a 0 byte in UTF-16, the constructor appears to just give up and return an empty string. The solution is to change readString to specify that it must use UTF-16 encoding:

protected static String readString(DataInputStream din)
        throws IOException{
    int strLength = 2*din.readInt();
    byte[] stringHolder = new byte[strLength];
    din.read(stringHolder);
    return new String(stringHolder, "UTF-16");
}

My question is, why is this necessary? Since Java uses UTF-16 for strings by default, why wouldn't it assume that UTF-16 is being used when reading chars from bytes? Or, alternatively, why wouldn't it just encode the chars as bytes in the first place by default? In short, why don't the default behaviors of the writeChars() method and the String(byte[]) constructor parallel each other?

解决方案

The issue is you are writing using the underlying char[] which is essentialy a byte[] that represents a UTF-16 representation of a string, see the javadoc.
You are then reading using the String(byte[] bytes) constructor, which is designed for reading data encoded with the system default encoding, in your case presumably this is UTF-8.
You need to be consistent, in fact the DataOutputStream.writeUTF() and DataInputStream.readUTF() functions are designed especially for this.
If you want use the underlying byte[] for some reason you can get the UTF-8 representation of the String easily using String.getBytes("UTF-8"), again, see the javadoc.
To simplify matters you could just use an ObjectOutputStream and an ObjectInputStream and that would serialize the actual String to the stream rather than just its char[] representation.

这篇关于为什么DataOutputStream.writeChars(str)和String(byte [])使用相同的编码?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆