Java中write(int)和writeInt(int)的区别,writeBytes(String) 和writeChars(String) 区别
本文介绍 Java DataOutputStream 中 write(int)和writeInt(int)的区别,writeBytes(String) 和writeChars(String) 的区别,并介绍 write(string.getBytes()) 与字符编码的基本知识。
相同点
write(int)和writeInt(int) 都是接收int参数
writeBytes(String) 和writeChars(String) 都是接收 String 参数
write(byte[]) 通过string.getBytes() 可以间接接收String
write(int), writeInt(int) 的区别
在java DataOutputStream 中,定义的2个方法 write(int), writeInt(int), 它们接收的参数都是 int,但却有着本质的区别。
write(int)
write(int) 继承自父类OutputStream,接收的虽然是int, 但是它只向输出流里写一个字节。我们知道,在java中,一个int 数子是4个字节组成,write(int) 只写入int的最低位的一个字节,其它3个字节被抛弃。
例如: write(-100),
int -100 的32位二进制码为: 11111111_11111111_11111111_10011100
那么, write(-100),实际上只写了最低的8位到输出流:10011100。
writeInt(int)
writeInt(int),是把整个32位都写入输出流。
那么, write(-100),写了32位到输出流:11111111_11111111_11111111_10011100。
看下面代码:
package io; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; public class IODeamo { public static void main(String[] args) throws Exception { ByteArrayOutputStream bos = new ByteArrayOutputStream(); int i = -100; System.out.println(Integer.toBinaryString(i)); bos.write(i); System.out.println("OutputStream.write(int -100) length=" + bos.toByteArray().length ); bos.reset(); DataOutputStream dos = new DataOutputStream(bos); dos.write(i); System.out.println("DataOutputStream.write(int -100) length=" + bos.toByteArray().length); bos.reset(); dos.writeInt(i); System.out.println("DataOutputStream.writeInt(int -100) length=" + bos.toByteArray().length); } }
输出:
11111111111111111111111110011100 OutputStream.write(int -100) length=1 DataOutputStream.write(int -100) length=1 DataOutputStream.writeInt(int -100) length=4
从上面的输出可以看出,
write(-100) 到字节数组后,字节数组的长度为: 1 (8位)
writeInt(-100)到字节数组后,字节数组的长度为:4 (32位)
writeBytes(String),writeChars(String) ,以及write(string.getBytes()) 的区别
另外2个方法 writeBytes(String), writeChars(String), 它们接收的参数都是 String,另外,writeBytes(byte[]), 可以通过string.getBytes()间接接收 String,那么它们有什么不同呢?writeBytes(String)
writeBytes(String) 依次写入字符串中的每一个字符,并且只写入字符的低8位,高字节被抛弃。
例如,writeBytes(“中国人”),“中国人”这个字符串由3个字符组成。
在java中一个字符,是由2个字节(16位)组成的,我看看字符 ‘中’,‘国’, ‘人’这三个字符 在java中的字符编码:
"中"字符编码:01001110_00101101
"国"字符编码:01010110_11111101
"人"字符编码:01001110_10111010
那么 writeBytes(“中国人”),实际上,就写入了每个字符的低8位("中"的低8为00101101,"国" 的11111101,"人"的10111010),高8位被舍弃。
这样在输出流里一共写了3个字节00101101_11111101_10111010
比如,writeBytes(“ABC”), "ABC"中每个字符对应的java字符编码(java中每个字符都是2字节16位的):
"A"字符编码:00000000_01000001
"B"字符编码:00000000_01000010
"C"字符编码:00000000_01000011
writeBytes(“ABC”),实际写入了三个字节: 01000001_01000010_01000011
在java程序中,如果使用 Integer.toBinaryString("A"),查看"A"字节数据,得到的是7位:"1000001", 它自动把高位的0省略了。
看下面的程序片段(完整的程序,后面给出):
System.out.println(""A"字符编码:" + Integer.toBinaryString("A")); System.out.println(""B"字符编码:" + Integer.toBinaryString("B")); System.out.println(""C"字符编码:" + Integer.toBinaryString("C")); System.out.println(""中"字符编码:" + Integer.toBinaryString("中")); System.out.println(""国"字符编码:" + Integer.toBinaryString("国")); System.out.println(""人"字符编码:" + Integer.toBinaryString("人")); bos.reset(); dos.writeBytes("ABC"); System.out.println("DataOutputStream.writeBytes(String "ABC") length=" + bos.toByteArray().length); System.out.println(showBytes(bos.toByteArray())); bos.reset(); dos.writeBytes("中国人"); System.out.println("DataOutputStream.writeBytes(String "中国人") length=" + bos.toByteArray().length); System.out.println(showBytes(bos.toByteArray()));
"A"字符编码:1000001 "B"字符编码:1000010 "C"字符编码:1000011 "中"字符编码:100111000101101 "国"字符编码:101011011111101 "人"字符编码:100111010111010 DataOutputStream.writeBytes(String "ABC") length=3 01000001_01000010_01000011 DataOutputStream.writeBytes(String "中国人") length=3 00101101_11111101_10111010
writeChars(String)
writeChars(String) 依次写入字符串中的每一个字符,字符的2个字节全部写入。
dos.writeChars("中国人"), 会写入 6个字节。 dos.writeChars("ABC") 同样写入6个字节。
下面的程序片段:
bos.reset(); dos.writeChars("ABC"); System.out.println("DataOutputStream.writeChars(String "ABC") length=" + bos.toByteArray().length); System.out.println(showBytes(bos.toByteArray())); bos.reset(); dos.writeChars("中国人"); System.out.println("DataOutputStream.writeChars(String "中国人") length=" + bos.toByteArray().length); System.out.println(showBytes(bos.toByteArray()));
DataOutputStream.writeChars(String "ABC") length=6 00000000_01000001_00000000_01000010_00000000_01000011 DataOutputStream.writeChars(String "中国人") length=6 01001110_00101101_01010110_11111101_01001110_10111010
write(string.getBytes())
在说说 write(byte[]), 一般使用为: write(string.getBytes())。
同样对应上面的2个字符串 “ABC” 和 "中国人", 可以这样输出:
dos.write("ABC".getBytes());
dos.write("中国人".getBytes());
write(string.getBytes()) 和 writeBytes(string) 有着本质的区别。
无论是 writeBytes(string) ,还是writeChars(String) 都不存在字符编码的转码的问题, 而write(string.getBytes()) 则涉及到字符编码转换问题。
string.getBytes() 方法可以接收一个字符编码,如果不提供,则使用操作系统默认的字符编码(可以使用Charset.defaultCharset()查看)。
我系统系统默认的字符编码是:‘GBK’
也就是,输出操作 dos.write("中国人".getBytes()); 会把 “中国人” 这个字符串的,编码为 ‘GBK’表示的二进制代码,然后写入到输出流。
同样:dos.write("ABC".getBytes()); 会把 “ABC” 这个字符串的,编码为 ‘GBK’表示的二进制代码,然后写入到输出流。
看下面程序片:
System.out.println("defaultCharset:" + Charset.defaultCharset()); bos.reset(); dos.write("ABC".getBytes()); System.out.println("DataOutputStream.writeBytes(byte[] "ABC") length=" + bos.toByteArray().length); System.out.println(showBytes(bos.toByteArray())); bos.reset(); dos.write("中国人".getBytes()); System.out.println("DataOutputStream.writeBytes(byte[] "中国人") length=" + bos.toByteArray().length); System.out.println(showBytes(bos.toByteArray()));
输出为:
defaultCharset:GBK DataOutputStream.writeBytes(byte[] "ABC") length=3 01000001_01000010_01000011 DataOutputStream.writeBytes(byte[] "中国人") length=6 11010110_11010000_10111001_11111010_11001000_11001011
从上面的输出可以看出,
”ABC“ 的 GBK码为:01000001_01000010_01000011, 共3字节
"中国人"对应的GBK码为:
11010110_11010000_10111001_11111010_11001000_11001011,共6字节。
‘GBK’对与ASCII码中的字符,编码为一个字节,同时与ASCII兼容,对于汉字,编码成2个字节。
write(string.getBytes("utf-8"))
我们看看,现在广泛使用的UTF-8编码
dos.write("ABC".getBytes("utf-8"));
dos.write("中国人".getBytes("utf-8"));
Java首先把字符串”ABC“ 和 “中国人”按照UTF-8 编码成字节,然后写入输出流。
bos.reset(); dos.write("ABC".getBytes("utf-8")); System.out.println("DataOutputStream.writeBytes(byte[]<utf-8> "ABC") length=" + bos.toByteArray().length); System.out.println(showBytes(bos.toByteArray())); bos.reset(); dos.write("中国人".getBytes("utf-8")); System.out.println("DataOutputStream.writeBytes(byte[]<utf-8> "中国人") length=" + bos.toByteArray().length); System.out.println(showBytes(bos.toByteArray()));
输出:
DataOutputStream.writeBytes(byte[]<utf-8> "ABC") length=3 01000001_01000010_01000011 DataOutputStream.writeBytes(byte[]<utf-8> "中国人") length=9 11100100_10111000_10101101_11100101_10011011_10111101_11100100_10111010_10111010
可见:
“ABC”对应的UTF-8编码为:01000001_01000010_01000011 共3字节,并且和GBK码,还有ASCII码一致。
“中国人”对应的UTF-8编码为:11100100_10111000_10101101_11100101_10011011_10111101_11100100_10111010_10111010, 一共9个字节。UTF-8中一个中文汉字对应2~3个字节。这里,"中国人"这三个字,每个都刚好对应三个字节。
完整代码
package io; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.nio.charset.Charset; public class IODeamo { public static void main(String[] args) throws Exception { ByteArrayOutputStream bos = new ByteArrayOutputStream(); int i = -100; System.out.println("-100=" + Integer.toBinaryString(i)); System.out.println(" ---write----"); bos.write(i); System.out.println("OutputStream.write(int -100) length=" + bos.toByteArray().length); bos.reset(); DataOutputStream dos = new DataOutputStream(bos); dos.write(i); System.out.println("DataOutputStream.write(int -100) length=" + bos.toByteArray().length); System.out.println(" ---writeInt----"); bos.reset(); dos.writeInt(i); System.out.println("DataOutputStream.writeInt(int -100) length=" + bos.toByteArray().length); System.out.println(" ------------------"); System.out.println(""A"字符编码:" + Integer.toBinaryString("A")); System.out.println(""B"字符编码:" + Integer.toBinaryString("B")); System.out.println(""C"字符编码:" + Integer.toBinaryString("C")); System.out.println(""中"字符编码:" + Integer.toBinaryString("中")); System.out.println(""国"字符编码:" + Integer.toBinaryString("国")); System.out.println(""人"字符编码:" + Integer.toBinaryString("人")); System.out.println("------------------"); System.out.println(" ---writeBytes----"); bos.reset(); dos.writeBytes("ABC"); System.out.println("DataOutputStream.writeBytes(String "ABC") length=" + bos.toByteArray().length); System.out.println(showBytes(bos.toByteArray())); bos.reset(); dos.writeBytes("中国人"); System.out.println("DataOutputStream.writeBytes(String "中国人") length=" + bos.toByteArray().length); System.out.println(showBytes(bos.toByteArray())); System.out.println(" ---writeChars----"); bos.reset(); dos.writeChars("ABC"); System.out.println("DataOutputStream.writeChars(String "ABC") length=" + bos.toByteArray().length); System.out.println(showBytes(bos.toByteArray())); bos.reset(); dos.writeChars("中国人"); System.out.println("DataOutputStream.writeChars(String "中国人") length=" + bos.toByteArray().length); System.out.println(showBytes(bos.toByteArray())); System.out.println("defaultCharset:" + Charset.defaultCharset()); System.out.println(" ---write(string.getBytes())----"); bos.reset(); dos.write("ABC".getBytes()); System.out.println("DataOutputStream.writeBytes(byte[] "ABC") length=" + bos.toByteArray().length); System.out.println(showBytes(bos.toByteArray())); bos.reset(); dos.write("中国人".getBytes()); System.out.println("DataOutputStream.writeBytes(byte[] "中国人") length=" + bos.toByteArray().length); System.out.println(showBytes(bos.toByteArray())); System.out.println(" ---write(string.getBytes(utf-8))----"); bos.reset(); dos.write("ABC".getBytes("utf-8")); System.out.println("DataOutputStream.writeBytes(byte[]<utf-8> "ABC") length=" + bos.toByteArray().length); System.out.println(showBytes(bos.toByteArray())); bos.reset(); dos.write("中国人".getBytes("utf-8")); System.out.println("DataOutputStream.writeBytes(byte[]<utf-8> "中国人") length=" + bos.toByteArray().length); System.out.println(showBytes(bos.toByteArray())); } /** * 格式化 byte[] 的输出,每个byte 如果不足8位,补足8位(前面补0) */ public static String showBytes(byte[] bytes) { StringBuilder sb = new StringBuilder(); for (byte b : bytes) { String intBinStr = Integer.toBinaryString(Byte.toUnsignedInt(b)); intBinStr = "00000000" + intBinStr; intBinStr = intBinStr.substring(intBinStr.length() - 8, intBinStr.length()); sb.append(intBinStr).append("_"); } sb.deleteCharAt(sb.length() - 1); return sb.toString(); } }
输出:
int -100=11111111111111111111111110011100 ---write---- OutputStream.write(int -100) length=1 DataOutputStream.write(int -100) length=1 ---writeInt---- DataOutputStream.writeInt(int -100) length=4 ------------------ "A"字符编码:1000001 "B"字符编码:1000010 "C"字符编码:1000011 "中"字符编码:100111000101101 "国"字符编码:101011011111101 "人"字符编码:100111010111010 ------------------ ---writeBytes---- DataOutputStream.writeBytes(String "ABC") length=3 01000001_01000010_01000011 DataOutputStream.writeBytes(String "中国人") length=3 00101101_11111101_10111010 ---writeChars---- DataOutputStream.writeChars(String "ABC") length=6 00000000_01000001_00000000_01000010_00000000_01000011 DataOutputStream.writeChars(String "中国人") length=6 01001110_00101101_01010110_11111101_01001110_10111010 defaultCharset:GBK ---write(string.getBytes())---- DataOutputStream.writeBytes(byte[] "ABC") length=3 01000001_01000010_01000011 DataOutputStream.writeBytes(byte[] "中国人") length=6 11010110_11010000_10111001_11111010_11001000_11001011 ---write(string.getBytes(utf-8))---- DataOutputStream.writeBytes(byte[]<utf-8> "ABC") length=3 01000001_01000010_01000011 DataOutputStream.writeBytes(byte[]<utf-8> "中国人") length=9 11100100_10111000_10101101_11100101_10011011_10111101_11100100_10111010_10111010
- 上一篇: JS+Thinkphp 中 if的判断
- 下一篇: React组件间信息传递方式