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("\n---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("\n---writeInt----");
		bos.reset();
		dos.writeInt(i);
		System.out.println("DataOutputStream.writeInt(int -100) length=" + bos.toByteArray().length);

		System.out.println("\n------------------");
		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("\n---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("\n---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("\n---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("\n---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








  

  • 23
    点赞
  • 54
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值