0
点赞
收藏
分享

微信扫一扫

一、初步认识IO流

JakietYu 2022-01-12 阅读 30

I/O流

IO流的分类:

InputStreamReader:转换流:把字节流转换成字符流,字符流使用更加方便。并且可以指定编码格式。

在这里插入图片描述

案例:读取文件

// 文件中内容为Hello World
public static void main(String[] args) {
    FileInputStream fileInputStream = null;
    try {
        fileInputStream = new FileInputStream("E:/test.txt");
        int i = 0;
        // 终止符号:i=fileInputStream.read(),读取一个字节数据
        // 该方法效率低,读取一个字符就要和磁盘进行交互。
        while ( (i=fileInputStream.read()) != -1 ) {
            System.out.print((char) i);// ASCII码
        }
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        fileInputStream.close();
    }
}

一、IO流数据来源及操作的API

IO流的来源

// 1. 磁盘IO
FileInputStream fileInputStream = new FileInputStream("E:/test.txt");
// 2. 内存,字节数组
String str = "hello word";
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(str.getBytes());
// 3.键盘
// 4.网络(重点),不同的计算机之间进行通讯
Socket socket;
socket.getInputStream();
socket.getOutputStream();

二、本地磁盘文件操作(File)

File类是Java中为文件进行创建、删除、重命名、移动等操作而设计 的一个类。它是属于Java.io包下的类。

例子:

// 把字节流读取到一个缓存中,而没有使用缓冲流。
public static void main(String[] args) throws IOException{
    File file = new File("E:/logo.png");
    FileInputStream fileInputStream = new FileInputStream("E:/logo.png");
    FileOutputStream fileOutputStream = new FileOutputStream("E:/logo_copy.png");
    byte[] buffer = new byte[1024];// 占内存,不是越大越好
    int len = 0;
    while( (len=fileInputStream.read(buffer)) != -1 ) {
        // 方法一:写道磁盘,读取一次和磁盘交互一次,效率低
        fileOutputStream.write(len);
        // 方法二:1024个字节交互一次,效率高
        fileOutputStream.write(buffer, 0, len);
    }
    fileOutputStream.close();
    fileInputStream.close();
}

自动关闭流,Java7的用法:将流放在try()中

流必须实现Closeable接口

OutputStream implements Closeable

public static void main(String[] args) throws IOException{
    File file = new File("E:/logo.png");
    try(
        FileInputStream fileInputStream = new FileInputStream("E:/logo.png");
        FileOutputStream fileOutputStream = new FileOutputStream("E:/logo_copy.png");
    	) {
        byte[] buffer = new byte[1024];
        int len = 0;
        while( (len=fileInputStream.read(buffer)) != -1 ) {
            // 方法一:写道磁盘,读取一次和磁盘交互一次,效率低
            fileOutputStream.write(len);
            // 方法二:1024个字节交互一次,效率高
            fileOutputStream.write(buffer, 0, len);
        }
    }catch (Exception e) {
        
    }
}

1 深入浅出read方法

三、基于缓冲流的输入输出流

缓冲流:

如果输出字符大小,没有达到默认缓冲区大小。那么需要手动触发输出到磁盘操作。flush()
public static void main(String[] args){
    // 将[文件输出流]包装成  ->  缓冲输出流
    BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream("E:/zhukai.txt"));
    bufferedOutputStream.write("Hello World".getBytes());
    // bufferedOutputStream.flush(); // 刷盘操作
    bufferedOutputStream.close(); // 流关闭的时候,也会触发一个刷盘操作
}

四、基于文件的字符输入输出流实践

// 和字节流的读取没有太大的区别
public static void main(String[] args){
    try(FileReader reader = new FileReader("E:/mic.txt")) {
        int i = 0;
        char[] bf = char[1024];
        while( (i=reader.read(bf)) != -1 ) {
            System.out.println(new String(bf, 0, i));
        }
    }catch (Exception e) {
        
    }
}

1. 字符转换流(比较重要)

是字节流 —> 字符流的一个桥梁。

public static void main(String[] args){
    try(InputStream is = new FileInputStream("E:/mic.txt")) {
        InputStreamReader reader = new InputStreamReader(inputStream, "utf-8");
        BufferedReader BufferedReader = new BufferedReader(reader);
        // 转换流特有的方法
        BufferedReader.readLine();
    }catch(Exception e) {
        
    }
}

五、序列化和反序列化,网络传输中使用,socket。

将内存对象,保存在本地磁盘当中:

ObjectOutputStream: 将内存对象写入到磁盘,该对象需要实现序列化接口,serialable.

在socket网络通信中,会用到ObjectOutputStream对象输入输出流。

六、网络IO

在这里插入图片描述

例子:

// 启动一个服务端
public static void main(String[] args){
    final int DEFAULT_PORT = 8080;
    ServerSocket serverSocket = null;
    
    // 绑定一个监听端口
    try {
    	serverSocket = new ServerSocket(DEFAULT_PORT);
        // 这里是一个阻塞操作,等待客户端的链接。
        Socket socket = serverSocket.accept();
        System.out.print("客户端:" + socket.getPort() + "已连接");
        
        // 1. 字符转换流InputStreamReader,字节到字符的转换:new InputStreamReader(socket.getInputStream())
        // 2. 将字符流构建成一个字符缓冲流(更加高效)
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));// 
        String str= bufferedReader.readLine();// 获取客户端输入的一行信息
        System.out.println("收到客户端的请求信息:" + str);
        
        // 服务端也可以写出信息到输入端
        BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamReader(socket.getOutputStream());
        bufferedWriter.write("我已经收到了消息!\n"); 
        bufferedWriter.flush();                                                   
	}catch(IOException e){
        e.printStackTrace();
    }finally {
        bufferedReader.close();
        bufferedWriter.close();
        socket.close();
    }
}
// 客户端
public static void main(String[] args){
    final int DEFAULT_PORT = 8080;
    Socket socket = new Socket("localhost", DEFAULT_PORT);
    BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamReader(socket.getOutputStream());
                                                       
    // 加\n是因为服务端要读一行数据,没有这个符号,服务端会认为一直在读一行,readLine方法会阻塞                                                 
    bufferedWriter.write("我是客户端发送的消息!\n"); 
    bufferedWriter.flush();  
                                                       
    // 读取服务端的返回消息                                                   
    BufferedReader BufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
  	String str= BufferedReader.readLine();
    System.out.println("收到服务端的信息:" + str);                                                   
}

1. 详解网络通信的底层原理

在这里插入图片描述

在这里插入图片描述

// 启动一个服务端
public static void main(String[] args){
    final int DEFAULT_PORT = 8080;
    ServerSocket serverSocket = null;
    
    // 绑定一个监听端口
    try {
    	serverSocket = new ServerSocket(DEFAULT_PORT);
        ExecutorService executorService = Executors.newFixedThreadPool(4);
        while(true) {
            Socket socket = serverSocket.accept(); // 阻塞
            executorService.submit(new ServerSocketThread(socket));// 异步的处理方式,线程池处理。
        }
            
	}catch(IOException e){
        e.printStackTrace();
    }finally {
        流的关闭
    }
}
public class ServerSocketThread implements Runnable{
    Socket socket;
    
    @Override
    public void run() {
        System.out.print("客户端:" + socket.getPort() + "已连接");
        
        // 1. 转换流InputStreamReader,字节到字符的转换:new InputStreamReader(socket.getInputStream())
        // 2. 将字符流构建成一个字符缓冲流(更加高效)
        BufferedReader BufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));// 
        String str= BufferedReader.readLine();// 获取客户端输入的一行信息
        System.out.println("收到客户端的请求信息:" + str);
        
        BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamReader(socket.getOutputStream());
        bufferedWriter.write("我已经收到了消息!\n"); 
        bufferedWriter.flush();          
    }
}

上面这中也是低效的,所以会引出NIO,对于服务器来说线程的数量毕竟是有限的。

七、Socket实现RPC通讯框架


在这里插入图片描述


7. 手写RPC框架:

1. 创建两个工程:

  • rpc-server
  • rpc-client

在这里插入图片描述


2. 工程rpc-server中创建两个模块:

右键工程rpc-server工程,new — module 创建模块

在这里插入图片描述

  • rpc-server-api:是一个被公共依赖的包(接口要公共依赖)。
  • rpc-server-provider:接口的实现,服务的实现可以部署在不同的计算机上面。

3. 整理工程目录

maven中分模块的构建方式:删除src目录

在这里插入图片描述


4. rpc-server-provider实现API的接口

  • rpc-server-provider模块中,先引入rpc-server-api的依赖
  • rpc-server-provider模块中,实现rpc-server-api的接口

在这里插入图片描述


在这里插入图片描述


5. server能够被client远程调用

  • rpc-server-provider需要打包:

在这里插入图片描述


  • rpc-server-provider:install到本地仓库

在这里插入图片描述


6. 工程rpc-client也需要依赖rpc-server-api

  • rpc-client:引入接口依赖

在这里插入图片描述


7. socket实现远程通信

在这里插入图片描述

举报

相关推荐

Stream流初步认识

一、初步认识C++

初步认识指针

Java io流(一)

IO流详解(一)

WebAPI的初步认识

0 条评论