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();
        }

    }
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,001评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,210评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,874评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,001评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,022评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,005评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,929评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,742评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,193评论 1 309
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,427评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,583评论 1 346
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,305评论 5 342
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,911评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,564评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,731评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,581评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,478评论 2 352

推荐阅读更多精彩内容

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