我正在try 理解Java中字符串的字符编码.我在Windows 10上工作,默认的字符编码是windows-1251.8位编码字符.因此对于1个符号,它必须是1个字节.因此,当我为具有6个符号的字符串调用getBytes()时,我期望得到一个6个字节的array.但是下面的代码片段返回12,而不是6.

"Привет".getBytes("windows-1251").length // returns 12

起初,我认为字符的第一个字节必须为零.但与该字符相关的两个字节都具有非零值.有没有人能解释一下,我错过了什么?

下面是我如何测试它的一个示例

import java.nio.charset.Charset;
import java.io.*;
import java.util.HexFormat;

public class Foo
{
    public static void main(String[] args) throws Exception
    {
        System.out.println(Charset.defaultCharset().displayName());
        String s = "Привет";
        System.out.println("bytes count in windows-1251: " + s.getBytes("windows-1251").length);
        printBytes(s.getBytes("windows-1251"), "windows-1251");
    }
    
    public static void printBytes(byte[] array, String name) {
        for (int k = 0; k < array.length; k++) {
            System.out.println(name + "[" + k + "] = " + "0x" +
                byteToHex(array[k]));
        }
    }

static public String byteToHex(byte b) {
      // Returns hex String representation of byte b
      char hexDigit[] = {
         '0', '1', '2', '3', '4', '5', '6', '7',
         '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
      };
      char[] array = { hexDigit[(b >> 4) & 0x0f], hexDigit[b & 0x0f] };
      return new String(array);
   }
}

结果是:

windows-1251
bytes count in windows-1251: 12
windows-1251[0] = 0xd0
windows-1251[1] = 0x9f
windows-1251[2] = 0xd1
windows-1251[3] = 0x80
windows-1251[4] = 0xd0
windows-1251[5] = 0xb8
windows-1251[6] = 0xd0
windows-1251[7] = 0xb2
windows-1251[8] = 0xd0
windows-1251[9] = 0xb5
windows-1251[10] = 0xd1
windows-1251[11] = 0x82

但我期望的是:

windows-1251
bytes count in windows-1251: 6
windows-1251[0] = 0xcf
windows-1251[1] = 0xf0
windows-1251[2] = 0xe8
windows-1251[3] = 0xe2
windows-1251[4] = 0xe5
windows-1251[5] = 0xf2

推荐答案

看起来你编译的时候可能有UTF-8编码的源文件?

HexFormat.of().withPrefix(", ").formatHex("Привет".getBytes("UTF-8"))
==> "d09fd180d0b8d0b2d0b5d182"

如果我将您的代码保存在UTF-8编辑器中并编译+运行:

java -Dfile.encoding=UTF-8 Foo.java
UTF-8
bytes count in windows-1251: 6
windows-1251[0] = 0xcf
windows-1251[1] = 0xf0
windows-1251[2] = 0xe8
windows-1251[3] = 0xe2
windows-1251[4] = 0xe5
windows-1251[5] = 0xf2

然而,如果使用您的默认编码编译并运行该UTF8文件,则这与您的输出相匹配:

java -Dfile.encoding=windows-1251 Foo.java
windows-1251
bytes count in windows-1251: 12
windows-1251[0] = 0xd0
windows-1251[1] = 0x9f
windows-1251[2] = 0xd1
windows-1251[3] = 0x80
windows-1251[4] = 0xd0
windows-1251[5] = 0xb8
windows-1251[6] = 0xd0
windows-1251[7] = 0xb2
windows-1251[8] = 0xd0
windows-1251[9] = 0xb5
windows-1251[10] = 0xd1
windows-1251[11] = 0x82

如果我将我的编辑器字符集更改为WINDOWS-1251,则输出如预期:

java -Dfile.encoding=windows-1251 Foo.java
windows-1251
bytes count in windows-1251: 6
windows-1251[0] = 0xcf
windows-1251[1] = 0xf0
windows-1251[2] = 0xe8
windows-1251[3] = 0xe2
windows-1251[4] = 0xe5
windows-1251[5] = 0xf2

Java相关问答推荐

Java小程序未在MacOS上运行

使用ExecutorService时在ThreadFactory中触发自定义newThread函数

当我用OkHttpClient重写shouldInterceptRequest来发布数据时,Android WebView正在以纯HTML加载URL内容

屏蔽字母数字代码的Java正则表达式

如果一个子类没有构造函数,超类也没有构造函数,那么为什么我可以构造子类的实例呢?

关于泛型的覆盖规则

更新GWT 2.5.1到2.11.0和sencha GXT 3.1.1到4.1时出现错误

如何解释Java中for-each循环中对Iterable的强制转换方法引用?

如何使用带有谓词参数的方法,而不使用lambda表达式

基于接口的投影、原生查询和枚举

虚拟线程应该很快消亡吗?

try 在Android Studio中的infoWindow中使用EditText(Java)

有没有可能在时间范围内得到多种解决方案?

如何在Spring Boot中创建可以将值传递给配置的&Enable&Quot;注释?

Dijkstra搜索算法的实现

JavaFX标签中的奇怪字符

如何从命令行编译包中的所有类?

接受类及其接口的Java类型(矛盾)

由于可为null,无法在kotlin中实现java接口

Java方法参数:括号中的类型声明?