将字节数组转换为字符串然后再转换为字节数组时,为什么长度不同?

Joh*_*ohn 4 java encoding utf-8 decoding

我有以下Java代码:

byte[] signatureBytes = getSignature();

String signatureString = new String(signatureBytes, "UTF8");
byte[] signatureStringBytes = signatureString.getBytes("UTF8");

System.out.println(signatureBytes.length == signatureStringBytes.length); // prints false
Run Code Online (Sandbox Code Playgroud)

问:我可能误解这一点,但我觉得new String(byte[] bytes, String charset)String.getBytes(charset)互为逆运算?

问:作为后续工作,将byte []数组作为String传输的安全方法是什么?

maa*_*nus 8

并非每一个byte[]都是有效的UTF-8.默认情况下,无效序列被固定字符替换,我认为这是长度变化的原因.

尝试Latin-1,它不应该发生,因为它是一个简单的编码,每个byte[]都是有意义的.

对于Windows-1252都不应该发生.那里有未定义的序列(实际上是未定义的字节),但是所有的字符都在一个字节中编码.新的byte[]可能与原始的不同,但它们的长度必须相同.

  • org.apache.commons.codec.binary.Base64永远是你传递任意数据作为字符串的最好朋友:) (3认同)

Ste*_*n C 5

我可能误解了这一点,但我认为新的String(byte [] bytes,String charset)和String.getBytes(charset)是反向操作?

不必要.

如果输入字节数组包含无效UTF-8的序列,则初始转换可能会将它们转换为(例如)问号.然后第二个操作将这些转换为UTF-8编码'?'字符....与原始表示不同.


确实,Unicode中的某些字符具有多个表示形式; 例如,重音字符可以是单个代码点,也可以是基本字符代码点和重音代码点.但是,在字节数组(包含有效的UTF-8)和String之间来回转换应该保留代码点序列.它不执行任何"规范化".


那么将byte []数组作为String传输的安全方法是什么呢?

最安全的替代方法是base64编码字节数组.这具有额外的优点,即字符串中的字符将转换为可以表示拉丁字母和数字的任何字符集/编码.

另一种方法是使用Latin-1而不是UTF-8.然而:

  • 如果数据(例如)被错误地解释为UTF-8,则存在损坏的风险.
  • 如果"字符串"随后嵌入XML中,则此方法不合法.许多控制字符在XML字符集之外,并且不能在XML文档中使用,甚至可以编码为字符实体.