java中writebytes是什么编码_Java编码的那些事儿

来上海百度实习也才没多久,这是第三个礼拜吧,接手的项目相当紧迫,而且作为一个实习生我是main coder,不由地带动了极大的工作积极性。这个一开始认为很简单很明了的“小”项目,没想到让我学到了很多东西,今天就讲讲关于Java编码的那些事儿。

Java编码

Unicode是全球标准字符集,是Java所为String采用的编码方式,任何字符用2个字节表示。String实例中保存有一个char[]字符数组。string.getByte()方法可以获得到这个字符串实例在指定编码下的字节数组,注意的是不带参数的getByte方法使用OS默认的字符集,比如GB2312(简体中文)。所以要得到Unicode下的字节数组,需要这样:string.getBytes(“unicode”)(此处注意见下文)。如果使用new String(byte[], Charset)构造,可以将已知编码的字节数组重新拼成一个String实例,即用指定的Charset去组合字节为Unicode字符罢了。同理,不带Charset的String构造使用OS默认字符集。

因此,得到UTF-8的字节数组,按以下步骤:

String str = "梦";

byte[] bytes = str.getBytes("UTF-8"); "使用UTF-8解码字符串得到的UTF-8字节数组"

String str2 = new String(bytes, "utf8"); "按照当初被解码的方式(utf8)重新组成Java String类"

str.equals(str2) == true; "使用大小写不同的编码写法,来区别不同API中参数代表的意义"

所以,str = new String(str.getBytes(Charset), Charset) 什么都没有做,除了新建了个String对象。

但是如果你要获取unicode的字节数组,却有非常多的选择,而且很容易出错。

void echoBytesTest() {

String s = "梦";

echoBytes(s, "Unicode");

echoBytes(s, "UnicodeBig");

echoBytes(s, "UnicodeLittle");

echoBytes(s, "UnicodeBigUnmarked");

echoBytes(s, "UnicodeLittleUnmarked");

echoBytes(s, "UTF-16");

echoBytes(s, "UTF-16BE");

echoBytes(s, "UTF-16LE");

echoBytes(s, "UTF-8");

}

void echoBytes(String s, String encoding) {

byte[] bytes = s.getBytes(encoding);

for (byte b : bytes) {

int i = b & 0xff;

System.out.print(Integer.toHexString(i) + " ");

}

System.out.println();

}

JDK6.0环境下的输出结果如下所示:

Unicode

fe ff 68 a6

BE顺序,带BOM

强烈申明不要使用,JDK相关

UnicodeBig

fe ff 68 a6

BE顺序,带BOM

推荐使用

UnicodeLittle

ff fe a6 68

LE顺序,带BOM

推荐使用

UnicodeBigUnmarked

68 a6

BE顺序,无BOM

推荐使用

UnicodeLittleUnmarked

a6 68

LE顺序,无BOM

推荐使用

UTF-16

fe ff 68 a6

BE顺序,带BOM

不推荐使用,可读性不够高

UTF-16BE

68 a6

BE顺序,无BOM

不推荐使用,可读性不够高

UTF-16LE

a6 68

LE顺序,无BOM

不推荐使用,可读性不够高

UTF-8

e6 a2 a6

无BOM

此为UTF-8字节串,特以此区别

然后要特别说明的是,getBytes(“Unicode”)这种方式是什么样的结果,却是与JDK相关的,JDK5.0使用LE顺序,JDK6.0使用BE顺序!

有点复杂,看官方解释。

为了在读取字节时能知道所采用的字节序,在传输时采用了一个名为 “Zero Width No-Break Space” 的字符(中文译名作“零宽无间断间隔”)用于限定字节序,开头两个字节为 FE FF(即-2 -1) 时为 Big-Endian,为 FF FE(即-1 -2) 时为 Little-Endian。 详见 RFC2781 3.2 节。这个就是传说中的BOM头。

UTF-8不需要 BOM 来表明字节顺序,但可以用 BOM 来表明编码方式。字符 “Zero Width No-Break Space” 的 UTF-8 编码是 EF BB BF。

详见:BOM_百度百科

自我理解很像体系结构中的大端编址和小端编址对吧。不知道Unicode为什么要存在Big-Endian和Little-Endian两种顺序,反正就是存在着呗。

说说项目

就是因为string.getBytes(“Unicode”)的JDK相关性,然后我因为使用了旧版本的JDK导致和大家同样从SVN签出的代码的运行结果却完全不一致,由于完全信任Java的平台无关,没有一点怀疑是JDK源码的原因,整整花了一天的时候排查bug。

第二个是Spring MVC的@ResponseBody默认返回的字符集是ISO-8859-1的西文字符,导致返回客户端为乱码,修改Spring配置的见Spring官方论坛的解决方案,不过貌似试了几种方法都没有起效…其实最简单的方式就是放弃使用Spring提供的Ajax方式,直接使用HttpServletResponse的getWriter().write()方法写字符串或getOutputStream.write()方法直接写字节。

参考引用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用Hutool将Base64编码转换为图片的代码如下: ```java import cn.hutool.core.codec.Base64; import cn.hutool.core.io.FileUtil; public class Base64ToImage { public static void main(String[] args) { // Base64编码字符串 String base64Str = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAKwAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAJgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAIwAAJgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAHgAAIwAAJgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAHAAAHgAAIwAAJgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAHAAAFAAAHgAAIwAAJgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAHAAAAAAAFwAAHgAAIwAAJgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAMgAAHAAAAAAAFwAAHgAAHAAAFAAAFAAAFAAAFAAAFAAAFAAAFAAAFAAAFAAAFAAAFAAAFAAAFAAAFAAAFAAAFAAAFAAAFAAAFwAA"; // 去掉Base64编码字符串的前缀 String base64 = base64Str.substring(base64Str.indexOf(",") + 1); // 将Base64编码字符串解码为字节数组 byte[] bytes = Base64.decode(base64); // 将字节数组写入图片文件 FileUtil.writeBytes(bytes, "test.png"); } } ``` 其,使用`Base64.decode()`方法将Base64编码字符串解码为字节数组,然后使用`FileUtil.writeBytes()`方法将字节数组写入图片文件。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值