I/O流

流的概念和作用

流:代表任何有能力产出数据的数据源对象或者是有能力接受数据的接收端对象

流的本质:数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作。

作用:为数据源和目的地建立一个输送通道

字符流AND字节流

1.按处理数据单位不同分为 字节流、字符流

字节流:每次读取(写出)一个字节,当传输的资源文件有中文时,就会出现乱码,

字符流:每次读取(写出)两个字节,有中文时,使用该流就可以正确传输显示中文。

1字符 = 2字节 、 1字节(byte) = 8位(bit) 、 一个汉字占两个字节长度

2.按功能不同分为 节点流、处理流

节点流:以从或向一个特定的地方(节点)读写数据。如FileInputStream 

处理流:是对一个已存在的流的连接和封装,通过所封装的流的功能调用实现数据读写。如BufferedReader。处理流的构造方法总是要带一个其他的流对象做参数。一个流对象经过其他流的多次包装,

4个基本的抽象流类型,所有的流都继承这四个。

           输入流      输出流

      字节流  InputStream  outputStream

      字符流  Reader      Writer

输入字节流InputStream

BufferedInputStream:缓冲流,对处理流进行装饰,增强,内部会有一个缓存区,用来存放字节,每次都是将缓存区存满然后发送,而不是一个字节或两个字节这样发送。效率更高

DataInputStream:数据输入流,它是用来装饰其它输入流,它“允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型”

FileInputSream:文件输入流。它通常用于对文件进行读取操作

输出字节流OutputStream

ByteArrayOutputStream、FileOutputStream 是两种基本的介质流,它们分别向Byte 数组、和本地文件中写入数据。PipedOutputStream 是向与其它线程共用的管道中写入数据,
ObjectOutputStream 和所有FilterOutputStream 的子类都是装饰流(序列化中使用)。

输入字符流Read

InputStreamReader 是一个连接字节流和字符流的桥梁,它将字节流转变为字符流。

FileReader 可以说是一个达到此功能、常用的工具类,在其源代码中明显使用了将FileInputStream 转变为Reader 的方法。我们可以从这个类中得到一定的技巧。Reader 中各个类的用途和使用方法基本和InputStream 中的类使用一致。

输出字符流Write

OutputStreamWriter 是OutputStream 到Writer 转换的桥梁,它的子类FileWriter 其实就是一个实现此功能的具体类(具体可以研究一SourceCode)。

字节流和字符流使用情况:(重要)

字符流和字节流的使用范围:字节流一般用来处理图像,视频,以及PPT,Word类型的文件。字符流一般用于处理纯文本类型的文件,如TXT文件等,字节流可以用来处理纯文本文件,但是字符流不能用于处理图像视频等非文本类型的文件。

字符流与字节流转换

转换流的作用,文本文件在硬盘中以字节流的形式存储时,通过InputStreamReader读取后转化为字符流给程序处理,程序处理的字符流通过OutputStreamWriter转换为字节流保存。

转换流的特点:

其是字符流和字节流之间的桥梁
可对读取到的字节数据经过指定编码转换成字符
可对读取到的字符数据经过指定编码转换成字节
何时使用转换流?

当字节和字符之间有转换动作时;
流操作的数据需要编码或解码时。
具体的对象体现:

InputStreamReader:字节到字符的桥梁
OutputStreamWriter:字符到字节的桥梁
这两个流对象是字符体系中的成员,它们有转换作用,本身又是字符流,所以在构造的时候需要传入字节流对象进来。

OutputStreamWriter(OutStreamout):将字节流以字符流输出。

InputStreamReader(InputStream in):将字节流以字符流输入

字节流和字符流的区别(重点)

字节流没有缓冲区,是直接输出的,而字符流是输出到缓冲区的。

因此在输出时,字节流不调用colse()方法时,信息已经输出了,

而字符流只有在调用close()方法关闭缓冲区时,信息才输出。

要想字符流在未关闭时输出信息,则需要手动调用flush()方法。

读写单位不同:字节流以字节(8bit)为单位,字符流以字符为单位,根据码表映射字符,一次可能读多个字节。

处理对象不同:字节流能处理所有类型的数据(如图片、avi等),而字符流只能处理字符类型的数据。

结论:只要是处理纯文本数据,就优先考虑使用字符流。除此之外都使用字节流。

总结

inputStream类的功能不足被Scanner解决了

OutputStream类的功能不足被PrintStream解决了

Reader类功能不足被BufferReader解决了

Writer类的功能不足被PrintWriter解决了

输出数据用printStream,printwriter

读取数据用Scanner其次是bufferReader

实现

1.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

/*
调整以下代码完成功能:
Http server 回送一个图片给浏览器客户端。
*/

public class MyWebServer{
public static void main(String args[]) throws IOException {
ServerSocket ss = new ServerSocket(80);//socket实例创建端口为80 本地连接电脑IP ipconfig
System.out.println("waiting for a tcp connection");
Socket s = ss.accept();//接受连接
System.out.println("constructed a tcp connection");
OutputStream oos = s.getOutputStream();//输出流创建
byte[] buf = new byte[1024];//缓存数组流1KB
PrintWriter pw = new PrintWriter(oos, true);//java.io.PrintWriter的构造方法并不局限于一下范例,java.io.PrintWriter构造方法的参数也可以是字节流, 即:
      PrintWriter的构造方法如果第一个参数为流,那么就可以再传入一个boolean型的参数,若该值为true,那么当前PrintWriter就具有了自动行刷新功能,这时每当我们使用println方法写出一行字符串后就会自动调用flush().
pw.println("HTTP/1.1 200 OK");
pw.println("Server: tomcat");
pw.println("Content-Type: image/png");
pw.println("Content-Length: 172032");
pw.println();//让浏览器知道head输出完成,开始正文输出
InputStream is = new FileInputStream("E:\\3.png");//创建字节流从磁盘读取文件
int len = 0;
while (true) {
len = is.read(buf);
if (len == -1) {
break;
}//读取
oos.write(buf, 0, len);//写入
}
}
}

2.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class MyWebServer{
public static void main(String args[]) throws IOException{
ServerSocket ss = new ServerSocket(80);
System.out.println("waiting for a tcp connection");
Socket s = ss.accept();
System.out.println("constructed a tcp connection");
OutputStream oos = s.getOutputStream();
PrintWriter pw = new PrintWriter(oos, true);
pw.println("HTTP/1.1 200 OK");
pw.println("Server: tomcat");
pw.println("Content-Type: image/png");
pw.println("Content-Length: 172032");
pw.println();
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("E:\\4.png"));
BufferedOutputStream bos = new BufferedOutputStream(oos);
byte [] b = new byte[1024];
int len = 0;
//边读边写
while((len=bis.read(b))!=-1){
bos.write(b, 0, len);
bos.flush();
}
s.close();
ss.close();
}
}