0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

java中的IO流与Guava工具

科技绿洲 来源:Java技术指北 作者:Java技术指北 2023-09-25 16:24 次阅读

Guava IO

日常系统交互中,文件的上传下载都是常见的,一般我们会通过jdk提供的IO操作库帮助我们实现。IO指的是数据相对当前操作程序的入与出,将数据通过 输出流从程序输出,或者通过输入流将数据(从文件、网络、数据等)写入到程序,这里的IO指的是基于流作为载体进行数据传输。如果把数据比作合理的水,河就是IO流,也是数据的载体。

Java为我们提供了非常多的操作IO的接口与类,帮助开发者实现不同源间的数据传输,比如硬盘文件、网络传输、应用调用间的数据交互与传递。今天我们来简单了解下Java中的流 以及在Guava工具包中,针对IO操作做了什么样的封装与设计。

分类

在java.io包中有非常多的IO相关接口,我们可以根据流的输出类型、处理对象以及功能将其分为以下几种类型:

  • 按数据流向
    • 输入流 (java.io.InputStream)
      用于实现将数据读入到程序
    • 输出流 (java.io.OutputStream)
      用于实现将数据从程序写出
  • 按操作单位
    • 字节流
      以字节(byte)为单位进行数据的读、写 (其中针对文件也提供了按基础数据类型的读与写DataInpoutStream,也就是按照Java基础类型所占字节数来进行定量字节读取并合并)
    • 字符流
      以字符(char)为单位进行数据的读、写,此时需要注意字符编码

区分:

字节流一般以Stream结尾 字符流一般以Reader或Writer结尾

  • 按操作方式
    • 读 (java.io.Reader)
      主要针对字符流的读取操作
    • 写 (java.io.Writer)
      主要针对字符流的写出操作
  • 按功能
    • 缓存流
      按字节进行数据读写时,通过缓冲批量写入来提高传输效率
    • 转换流
      实现输入/出与读/写方式间的转换

常用的流

  • 操作文件的
    java.io.FileinputStream/FileOutputStream java.io.FileReader/FileWriter
  • 通用的字节流
    java.io.InputStreamReader/outputStreamWriter
  • 缓冲流
    java.io.BufferedReader/BufferedWriter java.io.BufferedInputStream/BufferedOutputStream
  • 数据流
    java.io.DataInpoutStream/DataOutputStream
  • 功能型的
    java.io.PrintWriter/PrintStream
  • 对象序列化相关的
    java.io.ObjectInputStream/ObjectOutputStream

可见,提供的IO对象基本都是成对出现的,用以完成数据的输入输出,实现程序与外部载体间的数据交换

示例

下面我们通过一些常用示例来看看IO的使用的场景与使用方法:

  • 文件复制
  • 文件的合并
  • 读取文件内容为字符串
  • 字节数组转换成流
  • 对象序列化与反序列化
  • 流的转换
  • ......

  • 文件复制
@Test
    public void copyByBytes() throws IOException {
        String root = FileTests.class.getResource("/").getPath();

        FileInputStream fis = new FileInputStream(new File(root,"/start.bat"));
        FileOutputStream fos = new FileOutputStream(root+"/out2.bat");

        byte[] buff = new byte[100];

        int b;
        while ( (b = fis.read(buff))!=-1 ){
            fos.write(buff, 0, b);
        }
        // close
    }
  • 文件合并
@Test
    public void mergeFiles() throws IOException {
        File file1 = new File("E:_projectssuclsblogmy_studyguavaguava-iosrctestjavacomsuclsblogguavaiocategoryFileTests.java");
        File file2 = new File("E:_projectssuclsblogmy_studyguavaguava-iosrctestjavacomsuclsblogguavaiocategoryStreamTests.java");

        Enumeration< InputStream > ins = Collections.enumeration(Arrays.asList(
                new FileInputStream(file1),
                new FileInputStream(file2)
        ));

        SequenceInputStream sequenceInputStream = new SequenceInputStream(ins);

        FileOutputStream fos = new FileOutputStream(root+"/out4");

        byte[] buff = new byte[100];

        int read; // 真实读取到的字节数
        while ( (read = sequenceInputStream.read(buff)) !=-1){
            fos.write(buff, 0, read);
        }

        fos.close();
    }
  • 读取文件内容为字符串
@Test
    public void readStringFromFile() throws IOException {
        FileReader fileReader = new FileReader(new File(this.getClass().getResource("/").getPath(),"/start.bat"));

        StringBuilder stringBuilder = new StringBuilder();

        int i;
        while ( (i = fileReader.read())!=-1 ){
            stringBuilder.append( (char)i ); // 按字符读取
        }

        System.out.println( stringBuilder ); // 文件内容
    }
  • 字节数组转换成流
@Test
    public void bytesToStream(){
        byte [] data = new byte[1024]; // 来源于其他数据源

        ByteArrayInputStream inputStream = new ByteArrayInputStream(data);

        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

        int v;
        while ( (v=inputStream.read())!=-1 ){
            outputStream.write(v);
        }

        System.out.println( Arrays.toString( outputStream.toByteArray() ));
    }
  • 对象序列化与反序列化
@Test
    public void objectToFile() throws IOException {

        Person person = new Person();
        person.setName("张三").setAge(25);

        String root = FileTests.class.getResource("/").getPath();

        FileOutputStream fos = new FileOutputStream(new File(root,"/person"));
        ObjectOutputStream oos = new ObjectOutputStream(fos);

        oos.writeObject(person);
    }

    @Test
    public void fileToObject() throws IOException, ClassNotFoundException {
        String root = FileTests.class.getResource("/").getPath();

        FileInputStream fis = new FileInputStream(new File(root,"/person"));
        ObjectInputStream ois = new ObjectInputStream(fis);

        Person person = (Person) ois.readObject();
        System.out.println( person );
    }
  • 流的转换 将字节流转换成字符流来操作,同样以文件复制为例
@Test
    public void copyByBuffer() throws IOException {
        String root = FileTests.class.getResource("/").getPath();

        FileInputStream fis = new FileInputStream(new File(root,"/start.bat"));
        InputStreamReader isr = new InputStreamReader(fis);
        BufferedReader br = new BufferedReader(isr);

        FileOutputStream fos = new FileOutputStream(root+"/out3.bat");
        OutputStreamWriter osw = new OutputStreamWriter(fos);
        BufferedWriter bw = new BufferedWriter(osw);

        String line;
        while ( (line = br.readLine())!=null ){
            bw.append(line);
            bw.newLine();
            bw.flush();
        }

        // close
    }

关于流的操作非常多,像包括网络通信中、音视频文件处理、流合并等等

Guava中的IO

关于IO的内容并不复杂,上面的那些例子在很多工具库中基本都会提供对应的API方便开发者调用,今天主要看下Guava IO模块针对流的操作提供了什么样的 封装

Files

提供对文件快捷读写方法 其中主要提供了ByteSource、ByteSink、CharSource、CharSink 4个类,分别对应按字节的读写与按字符的读写,

/**
     * 文件复制
     */
    @Test
    public void copy() throws IOException {
        File from = new File(root,"from");
        File to = new File(root,"to");
        Files.copy(from,to);
    }

    /**
     * 文件移动
     */
    @Test
    public void move() throws IOException {
        File from = new File(root,"from");
        File to = new File(root,"to");
        Files.move(from,to);
    }

    /**
     * 按行读取文件
     * @throws IOException
     */
    @Test
    public void readLines() throws IOException {
        File dest = new File(root,"start.bat");
        List< String > lines = Files.readLines(dest, Charset.defaultCharset());
        lines.forEach(System.out::println);
    }

    /**
     * 写入文件
     * @throws IOException
     */
    @Test
    public void writeToFile() throws IOException {
        File dest = new File(root,"demo.txt");
        Files.write("hello world!".getBytes(Charset.defaultCharset()), dest);
    }

    /**
     * 修改文件更新时间
     * @throws IOException
     */
    @Test
    public void touch() throws IOException {
        File dest = new File(root,"demo.txt");
        Files.touch(dest);
    }

    /**
     * 文件的零拷贝
     * @throws IOException
     */
    @Test
    public void map() throws IOException, URISyntaxException {
        File from = new File(root,"from");
        File to = new File(root,"to");
        Files.touch(to);
        
        MappedByteBuffer fromBuff = Files.map(from, MapMode.READ_ONLY, 1024);
        // = >
        FileChannel channel = FileChannel.open(Paths.get(to.toURI()), StandardOpenOption.WRITE);

        channel.write(fromBuff);

        channel.close();
    }

    /**
     * 读文件为字节数组
     * @throws IOException
     */
    @Test
    public void fileAndBytes() throws IOException {
        File dest = new File(root,"start.bat");
        ByteSource byteSource = Files.asByteSource(dest);
        byte[] bytes = byteSource.read();
        System.out.println( bytes );

        // 字节写入文件,实现复制
        File target = new File(root, "start2.bat");
        ByteSink byteSink = Files.asByteSink(target);
        byteSink.write(bytes);
    }

    @Test
    public void wrapper(){
        File dest = new File(root,"start.bat");
        // 作为字节读
        Files.asByteSource(dest);
        // 作为字节写
        Files.asByteSink(dest);

        // 作为字符读
        Files.asCharSource(dest, Charset.defaultCharset());
        // 作为字符写
        Files.asCharSink(dest, Charset.defaultCharset());
    }

其他

管道流

PipedOutputStream PipedInputStream 实现多线程间的数据通信;类似生产消费者模式

@Test
    public void pipe() throws IOException {
        PipedOutputStream pipedOutputStream = new PipedOutputStream();
        PipedInputStream pipedInputStream = new PipedInputStream();
        pipedOutputStream.connect(pipedInputStream);

        new Thread(()- >{
            while (true){
                String date = new Date().toString();
                try {
                    pipedOutputStream.write( date.getBytes(StandardCharsets.UTF_8) );
                    pipedOutputStream.flush();
                    TimeUnit.SECONDS.sleep(2);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        }).start();
        
        new Thread(()- >{
            while (true){
                byte [] buff = new byte[1024];
                try {
                    int read = pipedInputStream.read(buff);
                    TimeUnit.SECONDS.sleep(4);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                System.out.println( new String(buff) );
            }
        }).start();
    }

结束语

在任何编程语言中,数据的IO都是比较常见并相当重要的。Guava作为工具型类库,主要是帮助开发者封装常用、重复的操作,开放出简介的API,不仅能让让代码更加整洁, 同时对开发出稳健程序也是比不可少的。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • IO
    IO
    +关注

    关注

    0

    文章

    434

    浏览量

    39064
  • 数据传输
    +关注

    关注

    9

    文章

    1810

    浏览量

    64442
  • 硬盘
    +关注

    关注

    3

    文章

    1288

    浏览量

    57214
  • JAVA
    +关注

    关注

    19

    文章

    2954

    浏览量

    104511
  • 工具包
    +关注

    关注

    0

    文章

    46

    浏览量

    9522
收藏 人收藏

    评论

    相关推荐

    Java基础的 IO

    java ,程序通常会和其他外部设备进行数据交互,比如写入磁盘,网络发送数据等等,今天我们来学学 java 基础的 IO
    的头像 发表于 10-10 16:16 1747次阅读
    <b class='flag-5'>Java</b><b class='flag-5'>中</b>基础的 <b class='flag-5'>IO</b> <b class='flag-5'>流</b>

    Java的输入输出盘点

    Java分为两种,一种是字节流,另一种是字符,分别由四个抽象类来表示(每种包括输入和输出两种所以一共四个):InputStream
    发表于 07-11 07:56

    Java NIO编程理论基础之Java IO及linux网络IO模型发展

    Java NIO编程理论基础篇——Java IO的发展以及linux网络IO模型
    发表于 07-18 12:40

    浅析javaIO模型

    java IO初识与Linux网络IO模型简介
    发表于 08-05 06:28

    Java 那些最常用的工具类库

    缓存通常用redis的hash,如下:# 设置用户信息hset student name testhset student age 10这种场景下map和bean的互相转换的工具类就特别
    发表于 06-15 17:18

    javaIO和单片机的IO口整体对比

    作为从本科学单片机出身笔者,对IO口独有情钟,这里对javaIO和单片机的IO口整体对比一
    发表于 01-18 08:28

    java与文件实验

    实验10 与文件一、实验目的 1. 理解数据的概念2. 理解Java的层次结构3. 理解文件的概念二、实验要求 1. 掌握字节流
    发表于 09-23 19:04 1901次阅读

    javaio分析

    一、的概念 (stream)的概念源于UNIX管道(pipe)的概念。在UNIX,管道是一条不间断的字节流,用来实现程序或进程间的通信,或读写外围设备、外部文件等。 一个
    发表于 09-27 14:51 0次下载
    <b class='flag-5'>java</b><b class='flag-5'>中</b>的<b class='flag-5'>io</b><b class='flag-5'>流</b>分析

    关于javaio知识总结详解

    一、Java io的开始:文件 1. 我们主要讲的是的本质也是对文件的处理,我们循序渐进一步一步从文件将到流去。 2. java 处理
    发表于 09-28 13:20 0次下载

    理解Java字符与字节流的区别

    JDK称为Java开发包或Java开发工具,是一个编写Java的Applet小程序和应用程序的程序开发环境。JDK是整个Java的核心,包括
    发表于 12-04 10:39 1106次阅读
    理解<b class='flag-5'>Java</b><b class='flag-5'>中</b>字符<b class='flag-5'>流</b>与字节流的区别

    基础:Java IO学习总结

    IO的分类 根据处理数据类型的不同分为:字符和字节流 根据数据流向不同分为:输入流和输出
    发表于 03-08 14:38 2062次阅读

    java数组的三种定义方式_java数组的定义及使用方法(推荐)

    java,数组是一种很常用的工具,本文将介绍来java数组的三种定义方式以及java
    发表于 01-29 09:53 3.2w次阅读

    Guava Collect常见的集合类

    Guava工具的一个子模块,主要对jdk的集合操作添加了一些简易的API,同时也是对Collections工具类的扩展。当然
    的头像 发表于 10-08 11:35 437次阅读

    java的字符分析

    上次聊到了 java 的 字符 Reader ,今天来看看它的好朋友 Writer 字符。 Writer java
    的头像 发表于 10-10 15:38 539次阅读

    Guava这些Map的操作,让我的代码量减少了50%

    Guava是google公司开发的一款Java类库扩展工具包,内含了丰富的API,涵盖了集合、缓存、并发、I/O等多个方面。
    的头像 发表于 10-20 11:30 361次阅读
    <b class='flag-5'>Guava</b><b class='flag-5'>中</b>这些Map的操作,让我的代码量减少了50%