1. 程式人生 > 其它 >Java 基礎(IO流原理及流的分類)

Java 基礎(IO流原理及流的分類)

Java IO 原理

  1. I/O是Input/Output的縮寫,I/O技術是非常實用的技術,用於如讀/寫檔案,網路通訊等。 處理裝置之間的資料傳輸。
  2. Java程式中,對於資料的輸入/輸出操作以“流(stream)”的方式進行。
  3. java.io包下提供了各種“流”類和介面,用以獲取不同種類的資料,並通過標準的方法輸入或輸出資料。

● 輸入input:讀取外部資料(磁碟、光碟等儲存裝置的資料)到程式(記憶體)中。

● 輸出output:將程式(記憶體)資料輸出到磁碟、光碟等儲存裝置中。

流的分類

  1. 按操作資料單位不同分為:位元組流(8 bit),字元流(16 bit)
  2. 按資料流的流向不同分為:輸入流,輸出流
  3. 按流的角色的不同分為:節點流,處理流

字元流例子

FileReaderWriterTest.java

package com.klvchen.java;

/*

# 流的體系結構
抽象基類                  節點流(或檔案流)        緩衝流(處理流的一種)
InputStream             FileiInputstream      BufferedInputStream
Outputstream            FiLeoutputstream      BufferedoutputStream
Reader                  FileReader            Bufferedreader
writer                  Filewriter            Bufferedwriter

 */

import org.junit.Test;

import java.io.*;

public class FileReaderWriterTest {

    public static void main(String[] args) {
        File file = new File("hello.txt"); //相較於當前工程
        System.out.println(file.getAbsolutePath());

        File file1 = new File("day09\\hello.txt"); //相較於當前工程
        System.out.println(file1.getAbsolutePath());


    }

    /*
    將day09下的hello.txt檔案內容讀入程式中,並輸出到控制檯
    說明點:
    1. read()的理解:返回讀入的一個字元。如果達到檔案末尾,返回-1
    2.異常的處理:為了保證流資源一定可以執行關閉操作。需要使用try-catch-finally處理
    3.讀入的檔案一定要存在,否則就會報FiLeNotFoundException。|

     */
    @Test
    public void testFileReader() {
        FileReader fr = null;
        try {
            //1. 例項化 File 類的物件,指明要操作的檔案
            File file = new File("hello.txt"); //相較於當前 Module
            //2. 提供具體的流
            fr = new FileReader(file);

            //3.資料的讀入
            //read():返回讀入的一個字元。如果達到檔案末尾,返回-1
            //方式一:
            //int data = fr.read();
            //while (data != -1) {
            //    System.out.println((char) data);
            //    data = fr.read();
            //}

            //方式二:
            int data;
            while ((data = fr.read()) != -1) {
                System.out.println((char) data);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            //4.流的關閉
            //try {
            //    if ( fr != null)
            //        fr.close();
            //} catch (IOException e) {
            //    e.printStackTrace();
            //}
            //或
            if (fr != null) {
                try {
                    fr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    //對read()操作升級:使用read的過載方法
    @Test
    public void testFileReader1(){
        FileReader fr = null;
        try {
            //1.File類的例項化
            File file = new File("hello.txt");

            //2.FileReader流的例項化
            fr = new FileReader(file);

            //3.讀入的操作
            //read(char[] cbuf):返回每次讀入cbuf陣列中的字元的個數。
            char[] cbuf = new char[5];
            int len;
            while ((len = fr.read(cbuf)) != -1) {
                //方式一:
                //錯誤的寫法
                //for (int i = 0; i < cbuf.length; i++) {
                //    System.out.print(cbuf[i]);
                //}
                //正確的寫法
                //for (int i = 0; i < len; i++) {
                //    System.out.print(cbuf[i]);
                //}

                //方式二:
                //錯誤的寫法,對應著方式一的錯誤的寫法
                //String str = new String(cbuf);
                //System.out.print(str);
                //正確的寫法
                String str = new String(cbuf, 0, len);
                System.out.print(str);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4.資源的關閉
            if (fr != null) {
                try {
                    fr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /*
    從記憶體中寫出資料到硬碟的檔案裡。
    說明:
    1.輸出操作,對應的 File可以不存在的。並不會報異常
    2.
       File對應的硬碟中的檔案如果不存在,在輸出的過程中,會自動建立此檔案。
       File對應的硬碟中的檔案如果存在:
            如果流使用的構造器是: FileWriter(file,false)/FileWriter(file):對原有檔案的覆蓋
            如果流使用的構造器是: FileWriter(file,true):不會對原有檔案覆蓋,而是在原有檔案基礎上追加內容。

     */

    @Test
    public void testFileWrite() {
        FileWriter fw = null;
        try {
            //1.提供File類的物件,指明寫出到的檔案
            File file = new File("hello1.txt");

            //2.提供FileWriter的物件,用於資料的寫出
            fw = new FileWriter(file);

            //3.寫出操作
            fw.write("I have a dream!\n");
            fw.write("you need to have a dream!");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4.流資源的關閉
            try {
                if (fw != null)
                    fw.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @Test
    public void testFileReaderFileWrite() {
        FileWriter fw = null;
        FileReader fr = null;
        try {
            //1.建立File類的物件,指明讀入和寫出的檔案
            File srcFile = new File("hello.txt");
            File destFile = new File("hello2.txt");

            //不能使用字元流來處理圖片等位元組資料
            //File srcFile = new File("1.png");
            //File destFile = new File("2.png");

            //2.建立輸入和輸出的對像
            fr = new FileReader(srcFile);
            fw = new FileWriter(destFile);

            //3.資料的讀入和寫入操作
            char[] cbuf = new char[5];
            int len; //記錄每次讀入到 cbuf 陣列中的字元的個數
            while ((len = fr.read(cbuf)) != -1) {
                //每次寫出len個字元
                fw.write(cbuf, 0 , len);
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4.關閉流資源
            try {
                if (fw != null)
                    fw.close();

            } catch (IOException e) {
                e.printStackTrace();
            }

            try {
                if (fr != null)
                    fr.close();

            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


}

位元組流例子

FileInputOutputStreamTest.java

package com.klvchen.java;

import org.junit.Test;

import java.io.*;

/*
對於文字檔案(.txt, .java, .c, .cpp),使用字元流處理
對於非文字檔案(.jpg, .mp3 , .mp4, .avi, .doc, .ppt,...),使用位元組流處理

 */
public class FileInputOutputStreamTest {
    //使用位元組流 FileInputStream 處理文字檔案,可能出現亂碼。
    @Test
    public void testFileInputStream() {
        FileInputStream fis = null;
        try {
            //1.造檔案
            File file = new File("hello.txt");

            //2.造流
            fis = new FileInputStream(file);

            //3.讀資料
            byte[] buffer = new byte[5];
            int len; //記錄每次讀取的位元組的個數
            while ((len = fis.read(buffer)) != -1) {
                String str = new String(buffer, 0, len);
                System.out.print(str);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4.關閉流
            try {
                if (fis != null)
                    fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }

    /*
    實現對圖片的複製操作
     */
    @Test
    public void testFileInputOutputStream()  {
        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
            //
            File srcFile = new File("1.png");
            File destFile = new File("3.png");

            //
            fis = new FileInputStream(srcFile);
            fos = new FileOutputStream(destFile);


            //
            byte[] buffer = new byte[5];
            int len;
            while ((len = fis.read(buffer)) != -1) {
                fos.write(buffer, 0 ,len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (fos != null)
                    fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (fis != null)
                    fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    //指定路徑下檔案的複製
    public void copyFile(String srcPath, String destPath) {
        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
            //
            File srcFile = new File(srcPath);
            File destFile = new File(destPath);

            //
            fis = new FileInputStream(srcFile);
            fos = new FileOutputStream(destFile);


            //
            byte[] buffer = new byte[1024];
            int len;
            while ((len = fis.read(buffer)) != -1) {
                fos.write(buffer, 0 ,len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (fos != null)
                    fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (fis != null)
                    fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @Test
    public void testCopyFile() {
        long start = System.currentTimeMillis();

        //String srcPath = "H:\\download\\1.mp4";
        //String destPaht = "H:\\download\\2.mp4";

        String srcPath = "hello.txt";
        String destPaht = "hello3.txt";

        copyFile(srcPath, destPaht);

        long end = System.currentTimeMillis();

        System.out.println("複製操作花費的時間為: " + (end - start)); //7006
    }


}