Java IO和Okio

扔物线学习笔记总结

  • 传统I/O
  • NIO
  • Okio

io 通过流,不是直接读

失去方便性,扩展灵活

  • 基本操作小例子,往文件里面输出数据的示例,不直接操作文件,通过“管子”操作

public class Main {
    public static void main(String[] args) {
        File file = new File("./a.txt");
        try {
            FileOutputStream fileOutputStream = new FileOutputStream(file);
            fileOutputStream.write('a');
            fileOutputStream.write('b');
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

FileOutputStream 读写二进制,字符串需要使用Reader,Writer

读写“插管子后”需要关闭,因为读写信息占用内存资源(例如读到哪个字节),需要释放,所以要及时关闭

成功失败都要关闭,传统方式在finally关闭 把变量在外面初始化

Java7开始,放在try后面括号里完成之后自动关闭,原因实现了 Closeable

字符流

相当于把管子插到字节流上

小结

Reader 是字符流

Buffer 是缓存,然后一起与文件交互

文件复制

Android Java FileUtils Kotlin copyto

的表皮下真正的代码

 /**
     * 文件复制
     */
    private static void io5() {

        try (
                InputStream inputStream = new FileInputStream("./a.txt");
                OutputStream outputStream = new FileOutputStream("./b.txt")
        ) {
            byte[] bytes = new byte[1024];
            int read;
            while ((read = inputStream.read(bytes)) != -1) {
                outputStream.write(bytes, 0, read);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

IO 就是内存和外界的交互

常用的File 类

网络交互Socket IO,

做TCP链接,网站针对字符

客户端

 public static void io6() {
        try (
                Socket socket = new Socket("rengwuxian.com", 80);
                BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()))
        ) {
            writer.write("GET / HTTP/1.1\n" + "Host:www.example.com\n\n");
            //发送到网站
            writer.flush();
            //看返回结果
            String message;
            while ((message = reader.readLine())!=null){
                System.out.println(message);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

小结代码

package test.io;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class Main {
    public static void main(String[] args) {
//        io1();
//        io2();
//        io3();
//        io4();
//        io5();
//        io6();
        io7();
    }

    /**
     * 写文件
     */
    private static void io1() {
        File file = new File("./a.txt");
        try (OutputStream fileOutputStream = new FileOutputStream(file);) {
            fileOutputStream.write('a');
            fileOutputStream.write('b');
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 读文件
     */
    private static void io2() {
        File file = new File("./a.txt");
        try (InputStream fileInputStream = new FileInputStream(file)) {
            //读的都是字节
            System.out.println((char) fileInputStream.read());
            System.out.println((char) fileInputStream.read());
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    /**
     * 读文件buffer
     */
    private static void io3() {
        File file = new File("./a.txt");
        try (InputStream fileInputStream = new FileInputStream(file);
             //读的都是字节
             //第二层字节上字符,也可以使用FileReader一步到位 字符流
             Reader reader = new InputStreamReader(fileInputStream);
             //第三层 整行读 再套一层 buffer 增加buffer,一次多读一些defaultCharBufferSize 8*1024
             BufferedReader bufferedReader = new BufferedReader(reader)
        ) {
            System.out.println(bufferedReader.readLine());
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 写文件 buffer 缓冲需要flush
     * 文件与内存交互性能低,所以buffer输出不同步
     * close会自动flush
     */
    private static void io4() {
        File file = new File("./a.txt");
        try (OutputStream fileOutputStream = new FileOutputStream(file);
             OutputStream outputStream = new BufferedOutputStream(fileOutputStream);
        ) {
            outputStream.write('a');
            outputStream.write('p');
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 文件复制
     */
    private static void io5() {

        try (
                InputStream inputStream = new FileInputStream("./a.txt");
                OutputStream outputStream = new FileOutputStream("./b.txt")
        ) {
            byte[] bytes = new byte[1024];
            int read;
            while ((read = inputStream.read(bytes)) != -1) {
                outputStream.write(bytes, 0, read);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * socket客户端
     */
    public static void io6() {
        try (
                Socket socket = new Socket("rengwuxian.com", 80);
                BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()))
        ) {
            writer.write("GET / HTTP/1.1\n" + "Host:www.example.com\n\n");
            //发送到网站
            writer.flush();
            //看返回结果
            String message;
            while ((message = reader.readLine()) != null) {
                System.out.println(message);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * Socket 服务端
     */
    public static void io7() {
        try (
                ServerSocket socketServer = new ServerSocket(80);
                //阻塞等待访问,就一次哦
                Socket socket = socketServer.accept();
                BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()))
        ) {
            //先读后写根据读取内容写入,这里直接写入
            writer.write("HTTP/1.1 200 OK\n" +
                    "Server: nginx/1.14.0 (Ubuntu)\n" +
                    "Date: Sun, 20 Jun 2021 09:17:34 GMT\n" +
                    "Content-Type: text/html\n" +
                    "Content-Length: 612\n" +
                    "Last-Modified: Fri, 11 Oct 2019 04:19:03 GMT\n" +
                    "Connection: keep-alive\n" +
                    "ETag: \"5da002b7-264\"\n" +
                    "Accept-Ranges: bytes\n" +
                    "\n" +
                    "<!DOCTYPE html>\n" +
                    "<html>\n" +
                    "<head>\n" +
                    "<title>Welcome to nginx!</title>\n" +
                    "<style>\n" +
                    "    body {\n" +
                    "        width: 35em;\n" +
                    "        margin: 0 auto;\n" +
                    "        font-family: Tahoma, Verdana, Arial, sans-serif;\n" +
                    "    }\n" +
                    "</style>\n" +
                    "</head>\n" +
                    "<body>\n" +
                    "<h1>Test </h1>\n" +
                    "<p>If you see this page, the nginx web server is successfully installed and\n" +
                    "working. Further configuration is required.</p>\n" +
                    "\n" +
                    "<p>For online documentation and support please refer to\n" +
                    "<a href=\"http://nginx.org/\">nginx.org</a>.<br/>\n" +
                    "Commercial support is available at\n" +
                    "<a href=\"http://nginx.com/\">nginx.com</a>.</p>\n" +
                    "\n" +
                    "<p><em>Thank you for using nginx.</em></p>\n" +
                    "</body>\n" +
                    "</html>\n" +
                    "\n" +
                    "Process finished with exit code 0\n\n");
            //发送到网站
            writer.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

NIO

  • 传统I/O:Stream ;NIO:Channel(双向)
  • NIO的Buffer
    • Buffer可以被操作;强制使用Buffer;Buffer不好用
  • 非阻塞式
    • 只是【支持非阻塞式】,默认式阻塞式
    • 只有网络交互支持非阻塞,文件交互不支持
 /**
     * NIO基本阻塞式读取
     */
    public static void io8(){
        //获取Channel
        try {
            RandomAccessFile file = new RandomAccessFile("./a.txt","r");
            FileChannel channel =file.getChannel();
            ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
            channel.read(byteBuffer);
            //不能直接从ByteBuffer中读
            // capacity 容量 position 位置 limit 限制
//            byteBuffer.limit(byteBuffer.position());
//            byteBuffer.position(0);
            //   byteBuffer.flip(); =   byteBuffer.limit(byteBuffer.position());+   byteBuffer.position(0);
            byteBuffer.flip();
            System.out.println(Charset.defaultCharset().decode(byteBuffer));
            //读取完要归位
            byteBuffer.clear();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

非阻塞

    public static void io9() {
        try {
            ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
            serverSocketChannel.bind(new InetSocketAddress(80));
            //设置使用非阻塞式
            serverSocketChannel.configureBlocking(false);
            Selector selector = Selector.open();
            //注册监听
            serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
            while (true) {
                selector.select();//阻塞了,不过所有Channel都可以往这里注册
                for (SelectionKey key : selector.selectedKeys()){
                    if (key.isAcceptable()){
                        SocketChannel socketChannel = serverSocketChannel.accept();
                        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
                        while ( socketChannel.read(byteBuffer)!=-1){
                            byteBuffer.flip();
                            socketChannel.write(byteBuffer);
                            //读取完要归位
                            byteBuffer.clear();
                        }
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

Okio

  • 也是基于插管,单向 Source和Sink
  • 支持Buffer
    • 可以对Buffer进行操作
    • Buffer很好用
    • 不强制使用Buffer

用法

需要先导入依赖

implementation 'com.squareup.okio:okio:2.4.3'

    public static void io10() {
        File file = new File("./a.txt");
//        try (Source source=Okio.source(file);){
//            Buffer buffer = new Buffer();
//            //Buffer 是个工具 ,read是往buffer里写
//            //source ->buffer ->read
//            source.read(buffer,1024);
//            System.out.println(buffer.readUtf8Line());
//            //不带buffer 不能整行读
//
//        }
        try (BufferedSource source = Okio.buffer(Okio.source(file))) {
            System.out.println(source.readUtf8Line());
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    public static void io11() {
        File src = new File("./a.txt");
        File dest = new File("./c.txt");
        try (  BufferedSource bufferedSource = Okio.buffer(Okio.source(src));
               BufferedSink bufferedSink = Okio.buffer(Okio.sink(dest));
        ){
            bufferedSink.writeAll(bufferedSource);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • io是什么 io是输入输出流,他的作用就是对外部进行数据交互使用的,内部和外部分别表示的是内存以及内存以外的,外部...
    程序猿峰岑阅读 5,450评论 0 1
  • 传统I/O 输入输出概念:这个输入输出相对于内存为主体,输入就是内存从文件中拿数据,输出就是内存从文件中写数据。 ...
    帝王鲨kingcp阅读 5,601评论 0 3
  • 前言 好久没有更新,最近在阅读flutter相关源码。之后会整理一下,把自己的学习源码思考写出来。最近看到了flu...
    yjy239阅读 10,534评论 7 5
  • java nio Java的IO体系:旧IO新IO:nio,用ByteBuffer和FileChannel读写ni...
    则不达阅读 4,298评论 0 2
  • 一、IO java的IO功能都在java.io包下,包括输入输出两种IO流,每种输入输出流又可分为字节流和字符流两...
    落地生涯阅读 3,619评论 0 1