网络IO与磁盘IO

目录

一.了解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()会返回-1
            while ((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()会返回-1
        while ((i = bai.read()) != -1) {
            System.out.print((char) i);
        }

4.键盘

        //键盘
        //Scanner
        InputStream is = System.in;
        int i = 0;
        //如果没有值 read()会返回-1
        while ((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次IO
                System.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 大小500000kb
    static 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];//设置缓存区大小为1024
            while ((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

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

w7486

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值