您的位置:首页 > 编程语言 > Java开发

java io系列15之 DataOutputStream(数据输出流)的认知、源码和示例

2014-07-15 09:25 656 查看
本章介绍DataOutputStream。我们先对DataOutputStream有个大致认识,然后再深入学习它的源码,最后通过示例加深对它的了解。

转载请注明出处:/article/4708115.html

DataOutputStream 介绍

DataOutputStream 是数据输出流。它继承于FilterOutputStream。
DataOutputStream 是用来装饰其它输出流,将DataOutputStream和DataInputStream输入流配合使用,“允许应用程序以与机器无关方式从底层输入流中读写基本 Java 数据类型”。

DataOutputStream 源码分析(基于jdk1.7.40)

1 package java.io;
2
3 public class DataOutputStream extends FilterOutputStream implements DataOutput {
4     // “数据输出流”的字节数
5     protected int written;
6
7     // “数据输出流”对应的字节数组
8     private byte[] bytearr = null;
9
10     // 构造函数
11     public DataOutputStream(OutputStream out) {
12         super(out);
13     }
14
15     // 增加“输出值”
16     private void incCount(int value) {
17         int temp = written + value;
18         if (temp < 0) {
19             temp = Integer.MAX_VALUE;
20         }
21         written = temp;
22     }
23
24     // 将int类型的值写入到“数据输出流”中
25     public synchronized void write(int b) throws IOException {
26         out.write(b);
27         incCount(1);
28     }
29
30     // 将字节数组b从off开始的len个字节,都写入到“数据输出流”中
31     public synchronized void write(byte b[], int off, int len)
32         throws IOException
33     {
34         out.write(b, off, len);
35         incCount(len);
36     }
37
38     // 清空缓冲,即将缓冲中的数据都写入到输出流中
39     public void flush() throws IOException {
40         out.flush();
41     }
42
43     // 将boolean类型的值写入到“数据输出流”中
44     public final void writeBoolean(boolean v) throws IOException {
45         out.write(v ? 1 : 0);
46         incCount(1);
47     }
48
49     // 将byte类型的值写入到“数据输出流”中
50     public final void writeByte(int v) throws IOException {
51         out.write(v);
52         incCount(1);
53     }
54
55     // 将short类型的值写入到“数据输出流”中
56     // 注意:short占2个字节
57     public final void writeShort(int v) throws IOException {
58         // 写入 short高8位 对应的字节
59         out.write((v >>> 8) & 0xFF);
60         // 写入 short低8位 对应的字节
61         out.write((v >>> 0) & 0xFF);
62         incCount(2);
63     }
64
65     // 将char类型的值写入到“数据输出流”中
66     // 注意:char占2个字节
67     public final void writeChar(int v) throws IOException {
68         // 写入 char高8位 对应的字节
69         out.write((v >>> 8) & 0xFF);
70         // 写入 char低8位 对应的字节
71         out.write((v >>> 0) & 0xFF);
72         incCount(2);
73     }
74
75     // 将int类型的值写入到“数据输出流”中
76     // 注意:int占4个字节
77     public final void writeInt(int v) throws IOException {
78         out.write((v >>> 24) & 0xFF);
79         out.write((v >>> 16) & 0xFF);
80         out.write((v >>>  8) & 0xFF);
81         out.write((v >>>  0) & 0xFF);
82         incCount(4);
83     }
84
85     private byte writeBuffer[] = new byte[8];
86
87     // 将long类型的值写入到“数据输出流”中
88     // 注意:long占8个字节
89     public final void writeLong(long v) throws IOException {
90         writeBuffer[0] = (byte)(v >>> 56);
91         writeBuffer[1] = (byte)(v >>> 48);
92         writeBuffer[2] = (byte)(v >>> 40);
93         writeBuffer[3] = (byte)(v >>> 32);
94         writeBuffer[4] = (byte)(v >>> 24);
95         writeBuffer[5] = (byte)(v >>> 16);
96         writeBuffer[6] = (byte)(v >>>  8);
97         writeBuffer[7] = (byte)(v >>>  0);
98         out.write(writeBuffer, 0, 8);
99         incCount(8);
100     }
101
102     // 将float类型的值写入到“数据输出流”中
103     public final void writeFloat(float v) throws IOException {
104         writeInt(Float.floatToIntBits(v));
105     }
106
107     // 将double类型的值写入到“数据输出流”中
108     public final void writeDouble(double v) throws IOException {
109         writeLong(Double.doubleToLongBits(v));
110     }
111
112     // 将String类型的值写入到“数据输出流”中
113     // 实际写入时,是将String对应的每个字符转换成byte数据后写入输出流中。
114     public final void writeBytes(String s) throws IOException {
115         int len = s.length();
116         for (int i = 0 ; i < len ; i++) {
117             out.write((byte)s.charAt(i));
118         }
119         incCount(len);
120     }
121
122     // 将String类型的值写入到“数据输出流”中
123     // 实际写入时,是将String对应的每个字符转换成char数据后写入输出流中。
124     public final void writeChars(String s) throws IOException {
125         int len = s.length();
126         for (int i = 0 ; i < len ; i++) {
127             int v = s.charAt(i);
128             out.write((v >>> 8) & 0xFF);
129             out.write((v >>> 0) & 0xFF);
130         }
131         incCount(len * 2);
132     }
133
134     // 将UTF-8类型的值写入到“数据输出流”中
135     public final void writeUTF(String str) throws IOException {
136         writeUTF(str, this);
137     }
138
139     // 将String数据以UTF-8类型的形式写入到“输出流out”中
140     static int writeUTF(String str, DataOutput out) throws IOException {
141         //获取String的长度
142         int strlen = str.length();
143         int utflen = 0;
144         int c, count = 0;
145
146         // 由于UTF-8是1~4个字节不等;
147         // 这里,根据UTF-8首字节的范围,判断UTF-8是几个字节的。
148         for (int i = 0; i < strlen; i++) {
149             c = str.charAt(i);
150             if ((c >= 0x0001) && (c <= 0x007F)) {
151                 utflen++;
152             } else if (c > 0x07FF) {
153                 utflen += 3;
154             } else {
155                 utflen += 2;
156             }
157         }
158
159         if (utflen > 65535)
160             throw new UTFDataFormatException(
161                 "encoded string too long: " + utflen + " bytes");
162
163         // 新建“字节数组bytearr”
164         byte[] bytearr = null;
165         if (out instanceof DataOutputStream) {
166             DataOutputStream dos = (DataOutputStream)out;
167             if(dos.bytearr == null || (dos.bytearr.length < (utflen+2)))
168                 dos.bytearr = new byte[(utflen*2) + 2];
169             bytearr = dos.bytearr;
170         } else {
171             bytearr = new byte[utflen+2];
172         }
173
174         // “字节数组”的前2个字节保存的是“UTF-8数据的长度”
175         bytearr[count++] = (byte) ((utflen >>> 8) & 0xFF);
176         bytearr[count++] = (byte) ((utflen >>> 0) & 0xFF);
177
178         // 对UTF-8中的单字节数据进行预处理
179         int i=0;
180         for (i=0; i<strlen; i++) {
181            c = str.charAt(i);
182            if (!((c >= 0x0001) && (c <= 0x007F))) break;
183            bytearr[count++] = (byte) c;
184         }
185
186         // 对预处理后的数据,接着进行处理
187         for (;i < strlen; i++){
188             c = str.charAt(i);
189             // UTF-8数据是1个字节的情况
190             if ((c >= 0x0001) && (c <= 0x007F)) {
191                 bytearr[count++] = (byte) c;
192
193             } else if (c > 0x07FF) {
194                 // UTF-8数据是3个字节的情况
195                 bytearr[count++] = (byte) (0xE0 | ((c >> 12) & 0x0F));
196                 bytearr[count++] = (byte) (0x80 | ((c >>  6) & 0x3F));
197                 bytearr[count++] = (byte) (0x80 | ((c >>  0) & 0x3F));
198             } else {
199                 // UTF-8数据是2个字节的情况
200                 bytearr[count++] = (byte) (0xC0 | ((c >>  6) & 0x1F));
201                 bytearr[count++] = (byte) (0x80 | ((c >>  0) & 0x3F));
202             }
203         }
204         // 将字节数组写入到“数据输出流”中
205         out.write(bytearr, 0, utflen+2);
206         return utflen + 2;
207     }
208
209     public final int size() {
210         return written;
211     }
212 }


示例代码

关于DataOutStream中API的详细用法,参考示例代码(DataInputStreamTest.java)

1 import java.io.DataInputStream;
2 import java.io.DataOutputStream;
3 import java.io.ByteArrayInputStream;
4 import java.io.File;
5 import java.io.InputStream;
6 import java.io.FileInputStream;
7 import java.io.FileOutputStream;
8 import java.io.IOException;
9 import java.io.FileNotFoundException;
10 import java.lang.SecurityException;
11
12 /**
13  * DataInputStream 和 DataOutputStream测试程序
14  *
15  * @author skywang
16  */
17 public class DataInputStreamTest {
18
19     private static final int LEN = 5;
20
21     public static void main(String[] args) {
22         // 测试DataOutputStream,将数据写入到输出流中。
23         testDataOutputStream() ;
24         // 测试DataInputStream,从上面的输出流结果中读取数据。
25         testDataInputStream() ;
26     }
27
28     /**
29      * DataOutputStream的API测试函数
30      */
31     private static void testDataOutputStream() {
32
33         try {
34             File file = new File("file.txt");
35             DataOutputStream out =
36                   new DataOutputStream(
37                       new FileOutputStream(file));
38
39             out.writeBoolean(true);
40             out.writeByte((byte)0x41);
41             out.writeChar((char)0x4243);
42             out.writeShort((short)0x4445);
43             out.writeInt(0x12345678);
44             out.writeLong(0x0FEDCBA987654321L);
45
46             out.writeUTF("abcdefghijklmnopqrstuvwxyz严12");
47
48             out.close();
49        } catch (FileNotFoundException e) {
50            e.printStackTrace();
51        } catch (SecurityException e) {
52            e.printStackTrace();
53        } catch (IOException e) {
54            e.printStackTrace();
55        }
56     }
57     /**
58      * DataInputStream的API测试函数
59      */
60     private static void testDataInputStream() {
61
62         try {
63             File file = new File("file.txt");
64             DataInputStream in =
65                   new DataInputStream(
66                       new FileInputStream(file));
67
68             System.out.printf("byteToHexString(0x8F):0x%s\n", byteToHexString((byte)0x8F));
69             System.out.printf("charToHexString(0x8FCF):0x%s\n", charToHexString((char)0x8FCF));
70
71             System.out.printf("readBoolean():%s\n", in.readBoolean());
72             System.out.printf("readByte():0x%s\n", byteToHexString(in.readByte()));
73             System.out.printf("readChar():0x%s\n", charToHexString(in.readChar()));
74             System.out.printf("readShort():0x%s\n", shortToHexString(in.readShort()));
75             System.out.printf("readInt():0x%s\n", Integer.toHexString(in.readInt()));
76             System.out.printf("readLong():0x%s\n", Long.toHexString(in.readLong()));
77             System.out.printf("readUTF():%s\n", in.readUTF());
78
79             in.close();
80        } catch (FileNotFoundException e) {
81            e.printStackTrace();
82        } catch (SecurityException e) {
83            e.printStackTrace();
84        } catch (IOException e) {
85            e.printStackTrace();
86        }
87     }
88
89     // 打印byte对应的16进制的字符串
90     private static String byteToHexString(byte val) {
91         return Integer.toHexString(val & 0xff);
92     }
93
94     // 打印char对应的16进制的字符串
95     private static String charToHexString(char val) {
96         return Integer.toHexString(val);
97     }
98
99     // 打印short对应的16进制的字符串
100     private static String shortToHexString(short val) {
101         return Integer.toHexString(val & 0xffff);
102     }
103 }


运行结果

byteToHexString(0x8F):0x8f
charToHexString(0x8FCF):0x8fcf
readBoolean():true
readByte():0x41
readChar():0x4243
readShort():0x4445
readInt():0x12345678
readLong():0xfedcba987654321
readUTF():abcdefghijklmnopqrstuvwxyz严12

结果说明

参考"java io系列14之 DataInputStream(数据输入流)的认知、源码和示例"
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐