0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

java中的IO流與Guava工具

科技綠洲 ? 來源:Java技術(shù)指北 ? 作者:Java技術(shù)指北 ? 2023-09-25 16:24 ? 次閱讀

Guava IO

日常系統(tǒng)交互中,文件的上傳下載都是常見的,一般我們會(huì)通過jdk提供的IO操作庫幫助我們實(shí)現(xiàn)。IO指的是數(shù)據(jù)相對當(dāng)前操作程序的入與出,將數(shù)據(jù)通過 輸出流從程序輸出,或者通過輸入流將數(shù)據(jù)(從文件、網(wǎng)絡(luò)、數(shù)據(jù)等)寫入到程序,這里的IO指的是基于流作為載體進(jìn)行數(shù)據(jù)傳輸。如果把數(shù)據(jù)比作合理的水,河就是IO流,也是數(shù)據(jù)的載體。

Java為我們提供了非常多的操作IO的接口與類,幫助開發(fā)者實(shí)現(xiàn)不同源間的數(shù)據(jù)傳輸,比如硬盤文件、網(wǎng)絡(luò)傳輸、應(yīng)用調(diào)用間的數(shù)據(jù)交互與傳遞。今天我們來簡單了解下Java中的流 以及在Guava工具包中,針對IO操作做了什么樣的封裝與設(shè)計(jì)。

分類

在java.io包中有非常多的IO相關(guān)接口,我們可以根據(jù)流的輸出類型、處理對象以及功能將其分為以下幾種類型:

  • 按數(shù)據(jù)流向
    • 輸入流 (java.io.InputStream)
      用于實(shí)現(xiàn)將數(shù)據(jù)讀入到程序
    • 輸出流 (java.io.OutputStream)
      用于實(shí)現(xiàn)將數(shù)據(jù)從程序?qū)懗?/li>
  • 按操作單位
    • 字節(jié)流
      以字節(jié)(byte)為單位進(jìn)行數(shù)據(jù)的讀、寫 (其中針對文件也提供了按基礎(chǔ)數(shù)據(jù)類型的讀與寫DataInpoutStream,也就是按照J(rèn)ava基礎(chǔ)類型所占字節(jié)數(shù)來進(jìn)行定量字節(jié)讀取并合并)
    • 字符流
      以字符(char)為單位進(jìn)行數(shù)據(jù)的讀、寫,此時(shí)需要注意字符編碼

區(qū)分:

字節(jié)流一般以Stream結(jié)尾 字符流一般以Reader或Writer結(jié)尾

  • 按操作方式
    • 讀 (java.io.Reader)
      主要針對字符流的讀取操作
    • 寫 (java.io.Writer)
      主要針對字符流的寫出操作
  • 按功能
    • 緩存流
      按字節(jié)進(jìn)行數(shù)據(jù)讀寫時(shí),通過緩沖批量寫入來提高傳輸效率
    • 轉(zhuǎn)換流
      實(shí)現(xiàn)輸入/出與讀/寫方式間的轉(zhuǎn)換

常用的流

  • 操作文件的
    java.io.FileinputStream/FileOutputStream java.io.FileReader/FileWriter
  • 通用的字節(jié)流
    java.io.InputStreamReader/outputStreamWriter
  • 緩沖流
    java.io.BufferedReader/BufferedWriter java.io.BufferedInputStream/BufferedOutputStream
  • 數(shù)據(jù)流
    java.io.DataInpoutStream/DataOutputStream
  • 功能型的
    java.io.PrintWriter/PrintStream
  • 對象序列化相關(guān)的
    java.io.ObjectInputStream/ObjectOutputStream

可見,提供的IO對象基本都是成對出現(xiàn)的,用以完成數(shù)據(jù)的輸入輸出,實(shí)現(xiàn)程序與外部載體間的數(shù)據(jù)交換

示例

下面我們通過一些常用示例來看看IO的使用的場景與使用方法:

  • 文件復(fù)制
  • 文件的合并
  • 讀取文件內(nèi)容為字符串
  • 字節(jié)數(shù)組轉(zhuǎn)換成流
  • 對象序列化與反序列化
  • 流的轉(zhuǎn)換
  • ......

  • 文件復(fù)制
@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; // 真實(shí)讀取到的字節(jié)數(shù)
        while ( (read = sequenceInputStream.read(buff)) !=-1){
            fos.write(buff, 0, read);
        }

        fos.close();
    }
  • 讀取文件內(nèi)容為字符串
@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 ); // 文件內(nèi)容
    }
  • 字節(jié)數(shù)組轉(zhuǎn)換成流
@Test
    public void bytesToStream(){
        byte [] data = new byte[1024]; // 來源于其他數(shù)據(jù)源

        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 );
    }
  • 流的轉(zhuǎn)換 將字節(jié)流轉(zhuǎn)換成字符流來操作,同樣以文件復(fù)制為例
@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
    }

關(guān)于流的操作非常多,像包括網(wǎng)絡(luò)通信中、音視頻文件處理、流合并等等

Guava中的IO

關(guān)于IO的內(nèi)容并不復(fù)雜,上面的那些例子在很多工具庫中基本都會(huì)提供對應(yīng)的API方便開發(fā)者調(diào)用,今天主要看下Guava IO模塊針對流的操作提供了什么樣的 封裝

Files

提供對文件快捷讀寫方法 其中主要提供了ByteSource、ByteSink、CharSource、CharSink 4個(gè)類,分別對應(yīng)按字節(jié)的讀寫與按字符的讀寫,

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

    /**
     * 文件移動(dòng)
     */
    @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);
    }

    /**
     * 修改文件更新時(shí)間
     * @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();
    }

    /**
     * 讀文件為字節(jié)數(shù)組
     * @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 );

        // 字節(jié)寫入文件,實(shí)現(xiàn)復(fù)制
        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");
        // 作為字節(jié)讀
        Files.asByteSource(dest);
        // 作為字節(jié)寫
        Files.asByteSink(dest);

        // 作為字符讀
        Files.asCharSource(dest, Charset.defaultCharset());
        // 作為字符寫
        Files.asCharSink(dest, Charset.defaultCharset());
    }

其他

管道流

PipedOutputStream PipedInputStream 實(shí)現(xiàn)多線程間的數(shù)據(jù)通信;類似生產(chǎn)消費(fèi)者模式

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

結(jié)束語

在任何編程語言中,數(shù)據(jù)的IO都是比較常見并相當(dāng)重要的。Guava作為工具型類庫,主要是幫助開發(fā)者封裝常用、重復(fù)的操作,開放出簡介的API,不僅能讓讓代碼更加整潔, 同時(shí)對開發(fā)出穩(wěn)健程序也是比不可少的。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報(bào)投訴
  • IO
    IO
    +關(guān)注

    關(guān)注

    0

    文章

    434

    瀏覽量

    39049
  • 數(shù)據(jù)傳輸
    +關(guān)注

    關(guān)注

    9

    文章

    1792

    瀏覽量

    64411
  • 硬盤
    +關(guān)注

    關(guān)注

    3

    文章

    1283

    瀏覽量

    57199
  • JAVA
    +關(guān)注

    關(guān)注

    19

    文章

    2952

    瀏覽量

    104482
  • 工具包
    +關(guān)注

    關(guān)注

    0

    文章

    45

    瀏覽量

    9518
收藏 人收藏

    評論

    相關(guān)推薦

    Java基礎(chǔ)的 IO

    java ,程序通常會(huì)和其他外部設(shè)備進(jìn)行數(shù)據(jù)交互,比如寫入磁盤,網(wǎng)絡(luò)發(fā)送數(shù)據(jù)等等,今天我們來學(xué)學(xué) java 基礎(chǔ)的 IO
    的頭像 發(fā)表于 10-10 16:16 ?1742次閱讀
    <b class='flag-5'>Java</b><b class='flag-5'>中</b>基礎(chǔ)的 <b class='flag-5'>IO</b> <b class='flag-5'>流</b>

    Java的輸入輸出盤點(diǎn)

    Java分為兩種,一種是字節(jié)流,另一種是字符,分別由四個(gè)抽象類來表示(每種包括輸入和輸出兩種所以一共四個(gè)):InputStream
    發(fā)表于 07-11 07:56

    Java NIO編程理論基礎(chǔ)之Java IO及l(fā)inux網(wǎng)絡(luò)IO模型發(fā)展

    Java NIO編程理論基礎(chǔ)篇——Java IO的發(fā)展以及l(fā)inux網(wǎng)絡(luò)IO模型
    發(fā)表于 07-18 12:40

    淺析javaIO模型

    java IO初識與Linux網(wǎng)絡(luò)IO模型簡介
    發(fā)表于 08-05 06:28

    Java 那些最常用的工具類庫

    緩存通常用redis的hash,如下:# 設(shè)置用戶信息hset student name testhset student age 10這種場景下map和bean的互相轉(zhuǎn)換的工具類就特別
    發(fā)表于 06-15 17:18

    javaIO和單片機(jī)的IO口整體對比

    作為從本科學(xué)單片機(jī)出身筆者,對IO口獨(dú)有情鐘,這里對javaIO和單片機(jī)的IO口整體對比一
    發(fā)表于 01-18 08:28

    java與文件實(shí)驗(yàn)

    實(shí)驗(yàn)10 與文件一、實(shí)驗(yàn)?zāi)康?1. 理解數(shù)據(jù)的概念2. 理解Java的層次結(jié)構(gòu)3. 理解文件的概念二、實(shí)驗(yàn)要求 1. 掌握字節(jié)流
    發(fā)表于 09-23 19:04 ?1898次閱讀

    javaio分析

    一、的概念 (stream)的概念源于UNIX管道(pipe)的概念。在UNIX,管道是一條不間斷的字節(jié)流,用來實(shí)現(xiàn)程序或進(jìn)程間的通信,或讀寫外圍設(shè)備、外部文件等。 一個(gè)
    發(fā)表于 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>分析

    關(guān)于javaio知識總結(jié)詳解

    一、Java io的開始:文件 1. 我們主要講的是,的本質(zhì)也是對文件的處理,我們循序漸進(jìn)一步一步從文件將到流去。 2. java 處理
    發(fā)表于 09-28 13:20 ?0次下載

    理解Java字符與字節(jié)流的區(qū)別

    JDK稱為Java開發(fā)包或Java開發(fā)工具,是一個(gè)編寫Java的Applet小程序和應(yīng)用程序的程序開發(fā)環(huán)境。JDK是整個(gè)Java的核心,包括
    發(fā)表于 12-04 10:39 ?1103次閱讀
    理解<b class='flag-5'>Java</b><b class='flag-5'>中</b>字符<b class='flag-5'>流</b>與字節(jié)流的區(qū)別

    基礎(chǔ):Java IO學(xué)習(xí)總結(jié)

    IO的分類 根據(jù)處理數(shù)據(jù)類型的不同分為:字符和字節(jié)流 根據(jù)數(shù)據(jù)流向不同分為:輸入流和輸出
    發(fā)表于 03-08 14:38 ?2061次閱讀

    java數(shù)組的三種定義方式_java數(shù)組的定義及使用方法(推薦)

    java,數(shù)組是一種很常用的工具,本文將介紹來java數(shù)組的三種定義方式以及java
    發(fā)表于 01-29 09:53 ?3.2w次閱讀

    Guava Collect常見的集合類

    Guava工具的一個(gè)子模塊,主要對jdk的集合操作添加了一些簡易的API,同時(shí)也是對Collections工具類的擴(kuò)展。當(dāng)然
    的頭像 發(fā)表于 10-08 11:35 ?432次閱讀

    java的字符分析

    上次聊到了 java 的 字符 Reader ,今天來看看它的好朋友 Writer 字符。 Writer java
    的頭像 發(fā)表于 10-10 15:38 ?529次閱讀

    Guava這些Map的操作,讓我的代碼量減少了50%

    Guava是google公司開發(fā)的一款Java類庫擴(kuò)展工具包,內(nèi)含了豐富的API,涵蓋了集合、緩存、并發(fā)、I/O等多個(gè)方面。
    的頭像 發(fā)表于 10-20 11:30 ?349次閱讀
    <b class='flag-5'>Guava</b><b class='flag-5'>中</b>這些Map的操作,讓我的代碼量減少了50%