JavaSE(十二)之IO流的字节流(一)
前面我们学习的了多线程,今天开始要学习IO流了,java中IO流的知识非常重要。但是其实并不难,因为他们都有固定的套路。
一、流的概念
流是个抽象的概念,是对输入输出设备的抽象,Java程序中,对于数据的输入/输出操作都是以"流"的方式进行。设备可以是文件,网络,内存等
流具有方向性,至于是输入流还是输出流则是一个相对的概念,一般以程序为参考,如果数据的流向是程序至设备,我们成为输出流,如果数据的流向是设备至程序称为输入流。
数据以二进制的形式在程序与设备之间流动传输,就想水在管道里流动一样,所以就把这种数据传输的方式称之为输入流输出流二、流的分类
1)按照流的方向分为输入流和输出流
2)按照处理数据的单位不同分为字节流和字符流
字节流读取的最小单位是一个字节(1byte=8bit),而字符流一次可以读取一个字符(1char = 2byte = 16bit)
3)按照功能的不同分为节点流和处理流
节点流是可以"直接"从一个数据源中读写数据的流。
处理流也可以称为功能流或者包装流,它是可以对节点流进行封装的一种流,封装后可以增加节点流的功能。
例如:FileInputStream是一个节点流,可以直接从文件读取数据,而BufferedInputStream可以包装 FileInputStream,使得其有缓冲数据的功能。
4)除了以上三种分类外,还有其他的一些类型的:对象流、缓冲流、压缩流、文件流等等,其实这些都是节点流或者处理流的子分类。当然还可以分出来其他的流类型,如果有这样需要的话。
5)不管流的分类是多么的丰富和复杂,其根源来自于四个基本的父类
字节输入流:InputStream
字节输出流:OutputStream
字符输入流:Reader 这四个父类都是抽象类
字符输出流:Writer
二、字节流中常用节点流
注:java中常用的io流都在java.io包中
1.1、InputStream
1)方法介绍
public abstract int read();
从输入流中读取数据的下一个字节;如果到达流的末尾则返回 -1
public int read(byte[] b){..}
把读到的字节存到字节数组b中,并返回本次读到了多少个字节
public int read(byte[] b,int off,int len){..}
把读到的字节存到字节数组b中,同时指定开始存的位置以及最大字节数,并返回本次读到了多少个字节
public int available(){..}
返回此输入流下一个方法调用可以不受阻塞地从此输入流读取(或跳过)的估计字节数
public long skip(long n){..}
跳过此输入流中数据的 n 个字节
public void close(){..}
关闭此输入流并释放与该流关联的所有系统资源
public boolean markSupported(){..}
测试此输入流是否支持 mark 和 reset 方法
public void mark(int readlimit){..}
在此输入流中标记当前的位置
public void reset(){..}
将此流重新定位到最后一次对此输入流调用mark方法时的位置
1.2、OutputStream
1)方法介绍
public abstract void write(int b);
将指定的字节写入此输出流
public void write(byte[] b){..}
将字节数组b中的所有字节写入此输出流
public void write(byte[] b,int off,int len){..}
将字节数组b中的字节写入此输出流,指定开始位置及最大字节数
public void flush(){..}
刷新此输出流并强制写出所有缓冲的输出字节
public void close(){..}
关闭此输出流并释放与此流有关的所有系统资源
注意:InputStream的子类和OutputStream的子类几乎都是成对出现的,一个负责读数据的工作,一个负责写数据的工作
1.3、System.out和System.in
标准输入流会默认从控制台读取数据
标准输出流会默认把数据输出到控制台
System.out.println(System.in.getClass());
System.out.println(System.out.getClass());
输出结果为:
class java.io.BufferedInputStream
class java.io.PrintStream
System类的部分源码:
public final class System{
//标准输入流
public final static InputStream in = null;
//标准输出流。
public final static PrintStream out = null;
//标准错误输出流
public final static PrintStream err = null;
public static void setIn(InputStream in){..}
public static void setOut(PrintStream out){..}
public static void setErr(PrintStream err){..}
}
在使用流的时候一定要注意它的步骤:
首先想清楚:1.是读是写 2.是字节是字符 3.从哪里读/写(这个非常的重要)比如在这个System.out和System.in中,in从控制台读取数据,out是把数据输出控制台
举例:
对输入流的操作
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import java.io.IOException;
2 import java.io.InputStream;
3 import java.util.Arrays;
4
5 public class InAndOutTest {
6
7 /*
8 * 1.是读还是写
9 * 2.是字节还是字符
10 * 3.从哪读/写
11 */
12 public static void main(String[] args) {
13
14 //1.声明流
15 InputStream in = null;
16
17 try {
18 //2.创建流
19 in = System.in;
20
21 //3.操作流
22
23 /*int data = in.read();
24 System.out.println(data);
25
26 data = in.read();
27 System.out.println(data);
28
29 data = in.read();
30 System.out.println(data);
31
32 data = in.read();
33 System.out.println(data);*/
34
35
36 //h e l l o
37 //104, 101, 108, 108, 111
38 //104, 101, 108, 108, 111, 119, 111, 114, 108, 100
39 /*byte[] b = new byte[10];
40 int len = in.read(b);
41 System.out.println(len);
42 System.out.println(Arrays.toString(b));*/
43 //输入hello
44 //结果:7
45 // [104, 101, 108, 108, 111, 13, 10, 0, 0, 0]
46
47
48 /*int data = -1;
49 while((data=in.read())!=-1){
50 System.out.println(data);
51 }*/
52
53
54
55 /*byte[] b = new byte[10];
56 int len = -1;
57 while((len=in.read(b))!=-1){
58 System.out.println(len+":"+Arrays.toString(b));
59 }*/
60
61
62
63 /*byte[] b = new byte[10];
64 int len = -1;
65
66 len = in.read(b, 4, 5);
67 System.out.println(len+":"+Arrays.toString(b));*/
68 //输入:helloworld
69 //输出:5:[0, 0, 0, 0, 104, 101, 108, 108, 111, 0]
70
71
72 //System.out.println(in.available());
73
74 // long len = in.skip(10);
75 // System.out.println(len);
76
77 //h e l l o w o r l d
78 //104, 101, 108, 108, 111
79 /* System.out.println(in.markSupported());
80 int data = -1;
81 while((data=in.read())!=-1){
82 if(data==101){
83 in.mark(10);
84 }
85 else if(data==111){
86 in.reset();
87 }
88 System.out.println(data);
89 Thread.sleep(1000);
90 }*/
91
92
93 } catch (Exception e) {
94 e.printStackTrace();
95 }finally {
96 //4.关闭流
97 try {
98 if(in!=null)in.close();
99 } catch (IOException e) {
100 e.printStackTrace();
101 }
102 }
103
104
105
106
107 }
108
109 }
对输出流的操作
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import java.io.IOException;
2 import java.io.InputStream;
3 import java.io.OutputStream;
4 import java.text.SimpleDateFormat;
5 import java.util.Date;
6
7 public class InAndOutTest2 {
8
9 /*
10 * 1.是读还是写
11 * 2.是字节还是字符
12 * 3.从哪读/写
13 */
14 public static void main(String[] args) {
15
16 //1.声明流
17 InputStream in = null;
18 OutputStream out = null;
19
20 try {
21 //2.创建流
22 in = System.in;
23 out = System.out;
24
25 //3.操作流
26 // System.out.println(out.getClass());
27 // out.write(97);
28 // out.flush();
29
30 //h e l l o
31 //104, 101, 108, 108, 111
32 // byte[] b = {104,101,108,108,111};
33 // byte[] b = "hello".getBytes();
34 /*
35 byte[] b1 = "你好".getBytes();
36 System.out.println(Arrays.toString(b1));
37
38 byte[] b2 = "你好".getBytes("UTF-8");
39 System.out.println(Arrays.toString(b2));
40
41 byte[] b3 = "你好".getBytes("GBK");
42 System.out.println(Arrays.toString(b3));
43
44 byte[] b4 = "你好".getBytes("unicode");
45 System.out.println(Arrays.toString(b4));
46
47 out.write(b1);
48 out.write(10);
49 out.write(b2);
50 out.write(10);
51 out.write(b3);
52 out.write(10);
53 out.write(b4);
54 out.flush();
55 */
56
57 /*
58 byte[] b = "helloworld".getBytes();
59 out.write(b, 3, 5);
60 out.flush();
61 */
62
63 /*
64 int data = -1;
65 while((data=in.read())!=-1){
66 out.write(data);
67 out.flush();
68 }*/
69
70
71 byte[] b = new byte[10];
72 int len = -1;
73
74 //[98, 121, 101]
75 // System.out.println(Arrays.toString("bye".getBytes()));
76 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
77 while((len=in.read(b))!=-1){
78 if(len==5){
79 String str = new String(b,0,3);
80 if("bye".equals(str)){
81 out.write("欢迎下次再来".getBytes());
82 out.flush();
83 break;
84 }
85 }
86 else if(len==6){
87 String str = new String(b,0,4);
88 if("time".equals(str)){
89 out.write(sdf.format(new Date()).getBytes());
90 out.flush();
91 continue;
92 }
93 }
94 out.write(b,0,len);
95 out.flush();
96 }
97
98 } catch (Exception e) {
99 e.printStackTrace();
100 }finally {
101 //4.关闭流
102 try {
103 if(in!=null)in.close();
104 } catch (IOException e) {
105 e.printStackTrace();
106 }
107 try {
108 if(out!=null)in.close();
109 } catch (IOException e) {
110 e.printStackTrace();
111 }
112 }
113
114
115
116
117 }
118
119 }
1.4、ByteArrayInputStream和ByteArrayOutputStream
这个节点流非常的重要:
ByteArrayInputStream可以从数组中读取字节
ByteArrayOutputStream可以把字节写到对象中的缓冲区里面,其实就是一个字节数组
相关的方法查看API
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import java.io.ByteArrayInputStream;
2 import java.io.ByteArrayOutputStream;
3 import java.io.IOException;
4 import java.io.InputStream;
5 import java.io.OutputStream;
6 import java.util.Arrays;
7
8 public class ByteArrayInputStreamTest {
9 public static void main(String[] args) {
10
11 InputStream in = null;
12 OutputStream out = null;
13
14 try {
15 byte[] buf = "helloworld".getBytes();
16 in = new ByteArrayInputStream(buf);
17 out = new ByteArrayOutputStream();
18
19
20 // System.out.println(Integer.toBinaryString(1000));
21
22 /*int data = -1;
23 while((data=in.read())!=-1){
24 out.write(data);
25 out.flush();
26 }*/
27
28 byte[] b = new byte[20];
29 int len = in.read(b);
30
31 out.write(b, 0, len);
32 out.flush();
33
34 byte[] dataBuf = ((ByteArrayOutputStream)out).toByteArray();
35 System.out.println(Arrays.toString(dataBuf));
36
37
38 } catch (Exception e) {
39 e.printStackTrace();
40 }finally {
41 try {
42 if(in!=null)in.close();
43 } catch (IOException e) {
44 e.printStackTrace();
45 }
46 try {
47 if(out!=null)out.close();
48 } catch (IOException e) {
49 e.printStackTrace();
50 }
51 }
52
53
54 }
55 }
1.5、FileInputStream和FileOutputStream
FileInputStream可以读取文件中的字节
查看api:
long skip(long n) 从输入流中国跳过并丢弃n个字节的数据
int available() 返回下一次对此输入流调用的方法可以不受阻塞地从此输入流读取(或跳过)的估计剩余字节数。
FileOutputStream可以向文件中写进去字节
例子:
从文件中读写到控制台中
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import java.io.FileInputStream;
2 import java.io.IOException;
3 import java.io.InputStream;
4 import java.io.OutputStream;
5
6 public class FileInputStreamTest {
7 public static void main(String[] args) {
8
9 InputStream in = null;
10 OutputStream out = null;
11
12 try {
13
14 String filePath = "src/com/zyh/chap11/b.txt";
15 in = new FileInputStream(filePath);
16 out = System.out;
17
18 System.out.println("in.available() = "+in.available());
19 byte[] b = new byte[512];
20 int len = -1;
21
22 while((len=in.read(b))!=-1){
23 out.write(b, 0, len);
24 }
25 out.flush();
26
27 } catch (Exception e) {
28 e.printStackTrace();
29 }finally {
30 try {
31 if(in!=null)in.close();
32 } catch (IOException e) {
33 e.printStackTrace();
34 }
35 try {
36 if(out!=null)out.close();
37 } catch (IOException e) {
38 e.printStackTrace();
39 }
40 }
41
42 }
43 }
自己建立一个字节数组写到文件中去
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import java.io.FileOutputStream;
2 import java.io.OutputStream;
3
4 public class FileOutputStreamTest {
5
6 public static void main(String[] args) {
7 OutputStream out = null;
8
9 try {
10 String file = "src/com/zyh/ioday02/b.txt";
11 out = new FileOutputStream(file,true);
12
13 byte[] b = "hello".getBytes();
14 // out.write(b);
15 out.write(b, 0, b.length);
16 out.flush();
17
18 } catch (Exception e) {
19 e.printStackTrace();
20 }finally{
21 try {
22 if (out != null)
23 out.close();
24 } catch (Exception e) {
25 e.printStackTrace();
26 }
27 }
28 }
29
30 }
从控制台读写到文件中去
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import java.io.FileOutputStream;
2 import java.io.InputStream;
3 import java.io.OutputStream;
4
5 public class FileOutputStreamTest2 {
6
7 public static void main(String[] args) {
8 InputStream in = null;
9 OutputStream out = null;
10
11 try {
12 in =System.in;
13 String file = "src/com/zyh/ioday02/b.txt";
14 out = new FileOutputStream(file);
15
16 byte[] buf = new byte[1024];
17 int len = -1;
18 while((len=in.read(buf))!=-1){
19 out.write(buf, 0, len);
20 }
21 out.flush();
22
23 } catch (Exception e) {
24 e.printStackTrace();
25 }finally{
26 try {
27 if (in != null)
28 in.close();
29 } catch (Exception e) {
30 e.printStackTrace();
31 }
32 try {
33 if (out != null)
34 out.close();
35 } catch (Exception e) {
36 e.printStackTrace();
37 }
38 }
39 }
40
41 }
读取一个文件内容写到另一个文件中
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import java.io.FileInputStream;
2 import java.io.FileOutputStream;
3 import java.io.IOException;
4 import java.io.InputStream;
5 import java.io.OutputStream;
6
7 public class FileInputStreamAndFileOutputStream {
8
9 public static void main(String[] args) {
10 InputStream in = null;
11 OutputStream out = null;
12
13 try {
14 String filePath1 = "src/com/zyh/ioday02/b.txt";
15 String filePath2 = "src/com/zyh/ioday02/c.txt";
16
17 in = new FileInputStream(filePath1);
18 out = new FileOutputStream(filePath2);
19
20 // in.skip(in.available()/2);
21 byte[] buf = new byte[1024];
22 int len = -1;
23 while((len=in.read(buf))!=-1){
24 out.write(buf,0,len);
25 }
26 out.flush();
27
28 } catch (Exception e) {
29 e.printStackTrace();
30 }finally{
31 if(in!=null)
32 try {
33 in.close();
34 } catch (IOException e) {
35 e.printStackTrace();
36 }
37 if(out!=null)
38 try {
39 out.close();
40 } catch (IOException e) {
41 e.printStackTrace();
42 }
43 }
44
45 }
46
47 }
1.6、PipedInputStream和PipedOutputStream
PipedInputStream管道字节输入流
PipedOutputStream管道字节输出流
注:使用时需要把俩个管道进行对接
在写关于IO流的用法时,一定要知道:
是字节流和还是字符
是输入还是输出
是读还是写(在下面这个例子中,首先PipedOutputStream从一个for循环中得到字节,然后PipedInputStream读到字节,通过System.out输出)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import java.io.IOException;
2 import java.io.PipedInputStream;
3 import java.io.PipedOutputStream;
4
5 public class PipedInputAndOutputStreamTest {
6 public static void main(String[] args) {
7
8 try {
9 PipedInputStream in = new PipedInputStream();
10 PipedOutputStream out = new PipedOutputStream(in);
11
12 Thread t1 = new PipedReadThread(in);
13 Thread t2 = new PipedWriteThread(out);
14
15 t1.start();
16 t2.start();
17
18 } catch (IOException e) {
19 e.printStackTrace();
20 }
21
22 }
23 }
24
25 //负责读取数据的线程
26 class PipedReadThread extends Thread{
27 private PipedInputStream in;
28
29 public PipedReadThread(PipedInputStream in) {
30 this.in = in;
31 }
32
33 @Override
34 public void run() {
35 try {
36 int data = -1;
37 while((data=in.read())!=-1){
38 System.out.write(data);
39 System.out.flush();
40 }
41 System.out.println("data = "+data);
42 } catch (IOException e) {
43 e.printStackTrace();
44 }finally {
45 try {
46 if(in!=null)in.close();
47 } catch (IOException e) {
48 e.printStackTrace();
49 }
50 }
51 }
52 }
53
54 //负责写入数据的线程
55 class PipedWriteThread extends Thread{
56 private PipedOutputStream out;
57
58 public PipedWriteThread(PipedOutputStream out) {
59 this.out = out;
60 }
61
62 @Override
63 public void run() {
64 try {
65 for(int i=97;i<=111;i++){
66 out.write(i);
67 out.flush();
68 Thread.sleep(1000);
69 }
70 } catch (Exception e) {
71 e.printStackTrace();
72 }finally {
73 try {
74 if(out!=null)out.close();
75 } catch (IOException e) {
76 e.printStackTrace();
77 }
78 }
79 }
80 }
1.7、ObjectInputStream和ObjectOutputStream(对象流)
1)序列化和反序列化
Java中的序列化是指把Java对象转换为字节序列的过程
对象---序列化--->01010101
Java中的反序列化是指把字节序列恢复为Java对象的过程
01010101---反序列化--->对象
2)实现序列化和反序列化
使用对象流即可实现对象的序列化和反序列化
2.1)ObjectOutputStream类中的方法可以完成对象的序列化:(注:这俩个对象流都属于字节流)
public final void writeObject(Object obj){..}
构造方法:
protected |
ObjectOutputStream() 为完全重新实现 ObjectOutputStream 的子类提供一种方法,让它不必分配仅由 ObjectOutputStream 的实现使用的私有数据。 |
|
ObjectOutputStream(OutputStream out)
创建写入指定 OutputStream 的 ObjectOutputStream。 |
实例:
首先编写了一个工具类:User
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import java.io.Serializable;
2
3 public class User implements Serializable{
4 private static final long serialVersionUID = 1L;
5
6 private long id;
7 private String name;
8 private int age;
9 private transient double salary;
10
11 public User() {}
12 public User(long id, String name, int age) {
13 this.id = id;
14 this.name = name;
15 this.age = age;
16 }
17
18 public long getId() {
19 return id;
20 }
21 public void setId(long id) {
22 this.id = id;
23 }
24 public String getName() {
25 return name;
26 }
27 public void setName(String name) {
28 this.name = name;
29 }
30 public int getAge() {
31 return age;
32 }
33 public void setAge(int age) {
34 this.age = age;
35 }
36 public double getSalary() {
37 return salary;
38 }
39 public void setSalary(double salary) {
40 this.salary = salary;
41 }
42 @Override
43 public String toString() {
44 return "User [id=" + id + ", name=" + name + ", age=" + age + ", salary=" + salary + "]";
45 }
46 }
将序列化写到文件当中
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import java.io.FileOutputStream;
2 import java.io.IOException;
3 import java.io.ObjectOutputStream;
4
5 public class ObjectOutputStreamTest {
6 public static void main(String[] args) {
7
8 ObjectOutputStream out = null;
9 // ByteArrayOutputStream bos = null;
10 FileOutputStream fos = null;
11 try {
12 String filePath = "src/com/zyh/chap11/obj.txt";
13 fos = new FileOutputStream(filePath);
14 out = new ObjectOutputStream(fos);
15
16 User u = new User(1L,"tom",20);
17 u.setSalary(2000);
18 //序列化
19 out.writeObject(u);
20 out.flush();
21
22 // byte[] array = bos.toByteArray();
23 // System.out.println(Arrays.toString(array));
24
25 } catch (Exception e) {
26 e.printStackTrace();
27 }finally {
28 try {
29 if(fos!=null)fos.close();
30 } catch (IOException e) {
31 e.printStackTrace();
32 }
33 try {
34 if(out!=null)out.close();
35 } catch (IOException e) {
36 e.printStackTrace();
37 }
38 }
39
40 }
41 }
我们查看文件会发现乱码,以为我们序列化之后是字节,当我们把它写到文件中的时候会通过设置的编码解析成字符,所以出现乱码。当然这个不是给我们看的,接下来我们要去做反序列化把它转回对象。
2.2) ObjectInputStream类中的方法可以完成对象的反序列化:
public final Object readObject(){..}
从刚才我们把序列化写到的那个文件中读,进行反序列化
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import java.io.FileInputStream;
2 import java.io.IOException;
3 import java.io.ObjectInputStream;
4
5 public class ObjectInputStreamTest {
6 public static void main(String[] args) {
7
8 ObjectInputStream in = null;
9 FileInputStream fis = null;
10
11 try {
12 String filePath = "src/com/zyh/chap11/obj.txt";
13 fis = new FileInputStream(filePath);
14 in = new ObjectInputStream(fis);
15
16 //反序列化
17 User obj = (User)in.readObject();
18 System.out.println(obj);
19
20 } catch (Exception e) {
21 e.printStackTrace();
22 }finally {
23 try {
24 if(fis!=null)fis.close();
25 } catch (IOException e) {
26 e.printStackTrace();
27 }
28 try {
29 if(in!=null)in.close();
30 } catch (IOException e) {
31 e.printStackTrace();
32 }
33 }
34
35 }
36 }
注意:在我们进行了序列化之后,如果给User类新增一个Salary的属性,然后进行反序列化的时候,会发现报错了(在没有添加serialVersionUID的时候)。会出现两个序列号(没有写序列号系统会有一个默认的)。
当我们设置了serialVersionUID的时候,并且给Salary进行set属性,会发现输出了User对象。
三、字节流常用的处理流
也可以称为功能流或者包装流,因为它是对节点流进行包装的一种流,包装后可以增加节点流的功能。但是处理流本身并不能直接读写数据
3.1、BufferedInputStream和BufferedOutputStream
作用:可以给字节流中的节点流提供代码缓冲区的输入/输出流
我们使用使用BufferedInputStream来读取的时候,明显比FileInputStream本身来读取的时候快很多。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import java.io.BufferedInputStream;
2 import java.io.FileInputStream;
3 import java.io.IOException;
4
5 public class BufferedInputStreamTest {
6
7 @SuppressWarnings("unused")
8 public static void main(String[] args) {
9
10 BufferedInputStream in = null;
11 FileInputStream fis = null;
12
13 try {
14 String filePath = "src/com/zyh/chap11/note.txt";
15 fis = new FileInputStream(filePath);
16
17 in = new BufferedInputStream(fis);
18
19 byte[] b = new byte[256];
20 int len = -1;
21 long start = System.currentTimeMillis();
22 while((len=in.read(b))!=-1){
23
24 }
25 long end = System.currentTimeMillis();
26 System.out.println(end-start+"毫秒");
27 } catch (Exception e) {
28 e.printStackTrace();
29 }finally {
30 try {
31 if(fis!=null)fis.close();
32 } catch (IOException e) {
33 e.printStackTrace();
34 }
35 try {
36 if(in!=null)in.close();
37 } catch (IOException e) {
38 e.printStackTrace();
39 }
40 }
41
42
43 }
44
45 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import java.io.BufferedOutputStream;
2 import java.io.FileOutputStream;
3 import java.io.IOException;
4
5 public class BufferedOutputStreamTest {
6 public static void main(String[] args) {
7
8 BufferedOutputStream out = null;
9 FileOutputStream fos = null;
10
11 try {
12 String filePath = "src/com/zyh/chap11/d.txt";
13 fos = new FileOutputStream(filePath);
14 out = new BufferedOutputStream(fos);
15
16 byte[] b = "test".getBytes();
17
18 out.write(b);
19 out.flush();
20
21 } catch (Exception e) {
22 e.printStackTrace();
23 }finally {
24 try {
25 if(fos!=null)fos.close();
26 } catch (IOException e) {
27 e.printStackTrace();
28 }
29 try {
30 if(out!=null)out.close();
31 } catch (IOException e) {
32 e.printStackTrace();
33 }
34 }
35
36 }
37 }
3.2、DataInputStream和DataOutputStream
可以给字节流中的节点流提供输入/输出java中不同类型的数据
首先我们先来看一下DataOutputStream
构造函数:
DataOutputStream(OutputStream out)
创建一个新的数据输出流,将数据写入指定基础输出流。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import java.io.DataOutputStream;
2 import java.io.FileOutputStream;
3 import java.io.IOException;
4
5 public class DataOutputStreamTest {
6 public static void main(String[] args) {
7
8 DataOutputStream out = null;
9 FileOutputStream fos = null;
10
11 try {
12 String filePath = "src/com/zyh/chap11/d.txt";
13 fos = new FileOutputStream(filePath);
14 out = new DataOutputStream(fos);
15
16 out.writeInt(1);
17 out.writeLong(1000L);
18 out.writeBoolean(false);
19 out.writeDouble(10.5);
20 out.writeFloat(10.5f);
21 out.writeUTF("你好");
22
23 out.flush();
24
25
26 } catch (Exception e) {
27 e.printStackTrace();
28 }finally {
29 try {
30 if(fos!=null)fos.close();
31 } catch (IOException e) {
32 e.printStackTrace();
33 }
34 try {
35 if(out!=null)out.close();
36 } catch (IOException e) {
37 e.printStackTrace();
38 }
39 }
40
41
42 }
43 }
查看文件我们发现乱码了,这是因为我们本来就是就只字节写到文件中去的,所以经过文件的编码解析之后就会乱码。只有其中的“你好”不会,因为我们用UTF-8编写,而文件也是通过UTF-8解析的。通过
DataInputStream来查看。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import java.io.DataInputStream;
2 import java.io.FileInputStream;
3 import java.io.IOException;
4
5 public class DataInputStreamTest {
6 public static void main(String[] args) {
7
8 DataInputStream in = null;
9 FileInputStream fis = null;
10
11 try {
12 String filePath = "src/com/zyh/chap11/d.txt";
13 fis = new FileInputStream(filePath);
14 in = new DataInputStream(fis);
15
16 System.out.println(in.readInt());
17 System.out.println(in.readLong());
18 System.out.println(in.readBoolean());
19 System.out.println(in.readDouble());
20 System.out.println(in.readFloat());
21 System.out.println(in.readUTF());
22
23 // System.out.println(in.read());
24
25 } catch (Exception e) {
26 e.printStackTrace();
27 }finally {
28 try {
29 if(fis!=null)fis.close();
30 } catch (IOException e) {
31 e.printStackTrace();
32 }
33 try {
34 if(in!=null)in.close();
35 } catch (IOException e) {
36 e.printStackTrace();
37 }
38 }
39
40
41 }
42 }
注意:我们要什么写的就要对应着怎么读。所以在开发中我们一般把同一个文件的东西写进去,读出来的时候就很方便了。
同时我们包装流可以包装任何的节点流,比如说ByteArrayOutputStream
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import java.io.ByteArrayOutputStream;
2 import java.io.DataOutputStream;
3 import java.io.IOException;
4 import java.util.Arrays;
5
6 public class DataOutputStreamTest2 {
7 public static void main(String[] args) {
8
9 DataOutputStream out = null;
10 ByteArrayOutputStream bos = null;
11
12 try {
13 bos = new ByteArrayOutputStream();
14 out = new DataOutputStream(bos);
15
16 // out.writeLong(1000L);
17 // out.writeInt(1000);
18 // out.writeBoolean(false);
19 // out.writeChar('中');
20 out.writeFloat(10.5f);
21 out.flush();
22
23 byte[] b = bos.toByteArray();
24 System.out.println(Arrays.toString(b));
25
26 } catch (Exception e) {
27 e.printStackTrace();
28 }finally {
29 try {
30 if(bos!=null)bos.close();
31 } catch (IOException e) {
32 e.printStackTrace();
33 }
34 try {
35 if(out!=null)out.close();
36 } catch (IOException e) {
37 e.printStackTrace();
38 }
39 }
40
41
42 }
43 }
3.3、PrintStream
PrintStream为其他输出流添加了功能,使它们能够方便地打印各种数据值表示形式
常用的System.out中的out变量就是PrintStream类型的
它是在OutputStream下面的,在InputStream中没有和它对应的流,所以在IO中大多数流都是成对出现的。也有极少数单个的。
举例:
我们使用System.out.println()都是往控制台输出的,我们知道System.out中out是一个PrintStream类型的。所以重写里面的println()方法来把它写到文件中.
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import java.io.FileOutputStream;
2 import java.io.PrintStream;
3 import java.text.SimpleDateFormat;
4 import java.util.Date;
5
6 public class PrintStreamTest {
7 static{
8 try {
9 String filePath = "src/com/zyh/chap11/c.txt";
10 PrintStream out = new PrintStream(new FileOutputStream(filePath,true)){
11 private SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
12 @Override
13 public void println(String x) {
14 super.println(sf.format(new Date())+" mylog: "+x);
15 }
16 };
17 System.setOut(out);
18 } catch (Exception e) {
19 e.printStackTrace();
20 }
21 }
22 public static void main(String[] args) {
23 System.out.println("hello world");
24 System.out.println("hello world");
25 System.out.println("hello world");
26 System.out.println("hello world");
27 System.out.println("hello world");
28 System.out.println("hello world");
29 System.out.println("hello world");
30 }
31 }
觉得不错的点个“推荐”哦!