目录
一.了解IO
IO流的分类
IO流的数据来源
1.网络
2.磁盘
3.内存
4.键盘
IO流的原理
二.字节流
1.read方法加缓存数组
2.字节流解决乱码问题
3.缓冲字节流
5.序列化和反序列化
三.字符流
四.网络IO
1.Socket和ServerSocket
2.基于Socket手写实现RPC框架
五.NIO(New IO)
一.了解IO
Java中的IO体系:在Java中I/0流操作的类很多,但是核心体系实际上就只有File、lnputStream、OutputStream、Reader、Writer.
IO流的分类


IO流的数据来源
1.网络
2.磁盘
//磁盘FileInputStream fi = null; //创建管道try {fi = new FileInputStream("d:/111/123.txt"); //存放在磁盘中的文件int i = 0;//如果没有值 read()会返回-1while ((i = fi.read()) != -1) {System.out.print((char) i);}} catch (IOException e) {e.printStackTrace();}
3.内存
//内存String str = "Hello Word"; //数据在内存中存放ByteArrayInputStream bai = new ByteArrayInputStream(str.getBytes());int i = 0;//如果没有值 read()会返回-1while ((i = bai.read()) != -1) {System.out.print((char) i);}
4.键盘
//键盘//ScannerInputStream is = System.in;int i = 0;//如果没有值 read()会返回-1while ((i = is.read()) != -1) {System.out.print((char) i);}}
注意:
流使用完成后一定要关闭!!
我们可以调用close方法手动关闭
也可以把流写在try(创建流){} catch(){}里JVM(java7)可以帮我们自动关闭流,前提是那个流实现了closeable接口
IO流的原理

为了安全,用户的进程不能直接操作底层的硬件,只能委派操作系统去执行。所以IO操作一定要借助内核去完成。
二.字节流
1.read方法加缓存数组
目的:减少磁盘IO
public class ReadBufferDemo {public static void main(String[] args) {FileInputStream fi = null; //创建管道FileOutputStream fo = null;try {//存放在磁盘中的文件 "Hello World"fi = new FileInputStream("d:/111/123.txt");fo = new FileOutputStream("d:/111/123_cp.txt");int i = 0;//创建一个数组 相当于缓存 可以减少 磁盘IO的次数byte[] buffer = new byte[3];//buffer [][0][]->[H][e][l] ->[1][o][ ]->[w][o][r] ->[1][d][r]while ((i = fi.read(buffer)) != -1) {//在这个类例子中,原本需要和磁盘进行11次I0操作,我增加了buffer之后,只需要进行4次IOSystem.out.println(new String(buffer,0,i));}} catch (IOException e) {e.printStackTrace();}//关闭流}
}
2.字节流解决乱码问题
因为中文在UTF-8中占3个字节 所以我们一个一个字节的取一定会乱码,所以我们一次全取出来在输出就可以解决乱码的问题
try(FileInputStream in = new FileInputStream(file);FileOutputStream out = new FileOutputStream(cp_file)) {int len = 0;//因为中文在UTF-8中占3个字节 所以我们一个一个字节的取一定会乱码byte[] buffer = new byte[1024];while ((len = in.read(buffer)) != -1) {System.out.println(new String(buffer,0,len)); }}catch (Exception e) {}
3.缓冲字节流
对比普通字节流和缓冲字节流复制文件test.zip大小约500000kb,所需时间的多少
public class BufferDemo1 {//test.zip 大小500000kbstatic File file = new File("d:/111/test.zip");//普通字节流 加缓冲数组static void in_cp(File file, File cp_file) {try(FileInputStream in = new FileInputStream(file);FileOutputStream out = new FileOutputStream(cp_file)) {int len = 0;byte[] buffer = new byte[1024];//设置缓存区大小为1024while ((len = in.read(buffer)) != -1) {//输出out.write(buffer,0,len);}}catch (Exception e) {}}//缓冲字节流//普通字节流 加缓冲数组static void bin_cp(File file, File cp_file) {try(FileInputStream in = new FileInputStream(file);FileOutputStream out = new FileOutputStream(cp_file);BufferedInputStream bin = new BufferedInputStream(in);BufferedOutputStream bout = new BufferedOutputStream(out)) {int len = 0;byte[] buffer = new byte[1024];while ((len = bin.read(buffer)) != -1) {//输出bout.write(buffer,0,len);}}catch (Exception e) {}}public static void main(String[] args) {long star = System.currentTimeMillis();//普通字节流File cp1_file = new File("d:/111/test1.zip");in_cp(file, cp1_file);System.out.println("普通字节流花费时间"+(System.currentTimeMillis()-star));long star2 = System.currentTimeMillis();//缓冲字节流File cp2_file = new File("d:/111/test2.zip");bin_cp(file, cp2_file);System.out.println("缓冲字节流花费时间"+(System.currentTimeMillis()-star2));}}
结果:
普通字节流花费时间8096
缓冲字节流花费时间1378
因为BufferedInputStream 底层 采用的缓存数组大小为8192
所以我想 试着把普通字节流的缓存数组 设为1024*8 发现他们的执行效率几乎相同
结果:
普通字节流花费时间1457
缓冲字节流花费时间1484
缓冲流的flush()方法的作用:
因为缓冲流的缓冲数组为1024*8,当我们write的时候,只有当缓冲区填满了的时候才会写入,所以为了防止数据没填满缓冲区导致数据没写入,我们可以用到这个flush()方法,顺便提一下close方法里也会调用一次flush相当于刷盘操作。
5.序列化和反序列化
ObjectOutputStream实现序列化对象
static void serialize(Object obj) {//ObjectOutputStream实现对象的序列化try(FileOutputStream fo = new FileOutputStream("d:/111/user");ObjectOutputStream obo = new ObjectOutputStream(fo)) {//把对象写入磁盘 相当于序列化obo.writeObject(obj);} catch (Exception e) {}System.out.println("序列化成功");}
ObjectInputStream实现反序列化对象
static void deserialize(File file) {try(FileInputStream fi = new FileInputStream(file);ObjectInputStream obi = new ObjectInputStream(fi)) {//把对象从磁盘读取 相当于反序列化User user = (User) obi.readObject();System.out.println("反序列化" + user);} catch (Exception e) {}}
test
public static void main(String[] args) {User user = new User("ws", 18);//序列化对象serialize(user);//反序列化deserialize(new File("d:/111/user"));}
结果:
序列化成功
反序列化User{name='ws', age=18}
三.字符流
字符流体系与字节流相似,字符流中特别的就是字符转换流InputStreamRead,他是字节流转换字符流的桥梁,它还可以指定编码格式。
四.网络IO
1.Socket和ServerSocket
模拟客户端与服务端通信
ServerSoket
public class ServerSoketDemo {final static int DEFAULT_PORT = 7486;public static void main(String[] args) {ServerSocket serverSocket = null;try {//创建一个监听serverSocket = new ServerSocket(DEFAULT_PORT);//等待客户端连接 accept()会阻塞 直到获取到客户端才会往下执行Socket socket = serverSocket.accept();System.out.println("客户端" + socket.getPort() +"已连接");//获取字节输入流getInputStream();//转换为缓存字符输入流BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));String msg = null;msg = br.readLine();//接受客户端消息System.out.println("客户端发送消息:" + msg);BufferedWriter bw = new BufferedWriter(new OutputStreamWriter( socket.getOutputStream()));//给客户端发送消息bw.write("我收到你的消息啦~\n");bw.flush();} catch (IOException e) {e.printStackTrace();}}
}
ClienSocket
public class ClienSocketDemo {final static int DEFAULT_PORT = 7486;public static void main(String[] args) {try {Socket socket = new Socket("localhost",DEFAULT_PORT);BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));bw.write("我是客户端:clien-01\n");bw.flush();BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));String msg = br.readLine();System.out.println(msg);} catch (IOException e) {e.printStackTrace();}}
}
结果:


2.BIO阻塞IO

所以 传统的IO在网络的数据传输上有两部分的阻塞,一部分是连接阻塞,一部分是IO阻塞。
可以利用线程池对其进行优化
//创建线程池private final ExecutorService executorService = Executors.newCachedThreadPool();//创建监听ServerSocket serverSocket = null;try {serverSocket = new ServerSocket(port);System.out.println("开启服务");while(true) {final Socket socket = serverSocket.accept(); //连接阻塞System.out.println("客户端" + socket.getPort() +"已连接");//把IO的逻辑交给多线程完成executorService.execute(new ProcessorHandler(service, socket));}} catch (IOException e) {e.printStackTrace();} //关闭serverSocket
2.基于Socket手写实现RPC框架
基于Socket手写RPC框架
五.NIO(New IO)
简述:
NIO 从JDK1.4提出的,本意是New l0,它的出现为了弥补I0的不足,提供了更高效的方式,针对于网络IO,他还可以非阻塞的模式进行网络IO.
详细了解JAVA NIO

















