JAVA-----IO篇(概念介紹以及FileIputStream)一

JAVA-----IO篇

io主要是對內存以及硬盤之間的輸入、輸出操作進行定義。

i:即使input。o:即使output。
輸入(input)、輸入流(inputStream)、讀(read):都是將硬盤中的信息傳遞到內存中。硬盤—>內存。
輸出(output)、輸出流(outputStream)、寫(Write):則是內存---->硬盤。其實可以看做對象序列化的過程(不知道這樣說是否確切)。
這兩個順序容易搞混,需要明確記憶。【主角是內存】,所謂輸入、輸出都是對於內存而言。
對io流進行分類便於理解和記憶

io流的分類:

  1. 按照流的方向進行分類:
    以內存爲參照物
    數據往內存中去,即爲:輸入、輸入流、讀。
    數據從內存中出,即爲:輸出、輸出流、寫。
  2. 按照讀取數據方式進行分類:
    有的流按照字節的方式進行讀取,一次讀取一個字節byte,等同於一次讀取8個二進制位。
    這種流是萬能的,字節流。 什麼類型的文件都能夠讀取,包括但不限於文本、圖片、聲音文件、視頻文件。
    另外一種即按照字符的方式進行讀取,一次讀取一個字符,這種流爲了方便讀取普通文本文件。稱爲字符流,只能讀取純文本文件,視頻、聲音都不能被讀取,甚至word文件也不能被讀取。普通文本文件是指以txt作爲後綴名的文件。
    比如文件file.txt中,內容爲:a你好世界aaaa
    1. 以字符流的形式讀取該文件,第一次讀取:'a’字符(在windows系統中,a字符佔用一個字節)
      第二次讀取:‘中’字符(在windows中,中字符佔用2個字節)。
    2. 如果以字節流的形式進行讀取,則第一次讀a,第二次讀’中’字符的一半,第三次就讀’中’的另外一半。
      綜上所述:流的分類:輸出流、輸出流。 字符流、字節流。

Java中char類型佔用兩個字節,windows中是一個字節。

Java中提供了哪些流?相關的方法?每個流的特點是什麼?

java中所有的流都是在java.io包下
java.io下有四大家族。分別是;java.io.inputStream(字節輸入流),java.io.outputStream(字節輸出流)、java.io.Reader(字符輸入流)、java.io.Writer(字符輸出流)。這四個都是抽象類。具體實現是根據其子類。 所有的流都實現了java.io.closeable接口,都是可關閉的,都有close方法,在對流的操作完畢後,一定要關閉流,流的使用會使用大量的資源。

注意:java中只要類名“以Stream結尾的都是字節流,以Reader/Writer結尾的都是字符流,着重對Stream進行理解學習”

輸出流:outputStream以及Writer還擁有一個共同特性,繼承了flushable接口,所有的輸出流,都是可刷新的,都具有flush()方法,在用完輸出流時,一定要進行刷新,表示將流管道中剩餘未輸出的數據強行輸出完,刷新的所用就是清空管道。
注意:如果沒有flush()可能會造成數據丟失。

java.io包下需要掌握的16個流(其實有很多,這16個常用)。分別是

文件專屬流(4個):
java.io.FileInputStream
java.io.FileOutputStream
java.io.FileReader
java.io.File.Writer
華麗分割線---------------------------------------------------------------------
轉換流(將字節流轉換爲字符流)(2個):
java.io.InputStreamReader
java.io.OutputStreamWriter
華麗分割線---------------------------------------------------------------------
緩衝流專屬(4個):
java.io.BufferedReader
java.io…BufferedWriter
java.io…BufferedInputStream
java.io…BufferedOutputStream
華麗分割線---------------------------------------------------------------------
數據流專屬(2個):
java.io.DataInputStream
java.io.DataOutputStream
華麗分割線---------------------------------------------------------------------
標準輸出流(2個):
java.io.PrintWriter
java.io.PrintStream
華麗分割線---------------------------------------------------------------------
對象專屬流(2個):
java.io.ObjectInputStream
java.io.ObjectOutputStream
華麗分割線---------------------------------------------------------------------

java.io.FileInputStream

FileInputStream是對txt文件的讀取,第一次讀取第一個字符,在讀取時會讀取第二個字符,在實際應用則不會一下一下讀取,一般是使用循環讀取。對於讀到的字符返回ASCI值,如果讀完了,再次讀就會返回-1,而對於文件中的空格【 】,會返回32,空格也是一個字符。

import java.io.FileInputStream;
import java.io.IOException;

/**
 * @author cz
 * @date 2020/6/11/011
 * 文件字節輸入流,完成的,任何類型文件都能夠採用這種方式
 * 從硬盤到內存的輸入方式
 **/
public class FileInputStreamTest01 {
    public static void main(String[] args) {
        //創建文件輸入流對象,以下采用絕對路徑的方式,相對路徑也可以
    //    文件路徑F:\a.txt,(IDEA中能夠自動將\變爲\\),因爲在java中\表示轉義字符fileInputStream = new FileInputStream("F:\\a.txt");
    //    FileInputStream fileInputStream = new FileInputStream("F:\\a.txt");   文件內容asdasdasd
    //    此時存在編譯時異常,需要程序員進行手動處理,這裏進行try..catch
    //    不寫\\而是改爲\,也是可以的
        FileInputStream fileInputStream=null;
        try {
            fileInputStream = new FileInputStream("F:\\a.txt");
//            開始讀
            int read = fileInputStream.read();  //返回值是讀取到的字節本身
            System.out.println(read);  // a返回97,讀第一次時指向第一個字符,再次調用read方法,就會指向第二個字符,當什麼都沒有時返回-1.

            read = fileInputStream.read();  //s返回115
            System.out.println(read); //s返回115
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
//            在finlly中確保流一定要進行關閉,前提是該流不能爲空
            if (fileInputStream!=null){  // 當流是空時沒必要關閉,避免空指針異常
                try {
                    fileInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

}

使用FileInputStream循環讀取txt文件。此時文件內容爲 a sdasdasd。在while循環(),括號中的條件必須爲true或者爲false。

import java.io.FileInputStream;
import java.io.IOException;

/**
 * @author cz
 * @date 2020/6/11/011
 * 文件字節輸入流,完成的,任何類型文件都能夠採用這種方式
 * 從硬盤到內存的輸入方式
 **/
public class FileInputStramTest01 {
    public static void main(String[] args) {
        //創建文件輸入流
    //    文件路徑F:\a.txt,(IDEA中能夠自動將\變爲\\),因爲在java中\表示轉義字符fileInputStream = new FileInputStream("F:\\a.txt");
    //    FileInputStream fileInputStream = new FileInputStream("F:\\a.txt"); 
    //    此時存在編譯時異常,需要程序員進行手動處理,這裏進行try..catch
    //    不寫\\而是改爲\,也是可以的
        FileInputStream fileInputStream=null;
        try {
            fileInputStream = new FileInputStream("F:\\a.txt");
//            開始讀
            while (true){
                int read = fileInputStream.read();  //返回值是讀取到的字節本身
                if (read==-1){
                    break;
                }
                System.out.println(read);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
//            在finlly中確保流一定要進行關閉,前提是該流不能爲空
            if (fileInputStream!=null){  // 避免空指針異常
                try {
                    fileInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

}

在這裏插入圖片描述
可以對while循環進行改造。

 int readData = 0;
            while ((readData = fileInputStream.read())!=-1){
                System.out.println(readData);
            }

這樣代碼看起來會簡潔一些。
但是這種讀取方式效率太低,一次只讀取一個字節,內存與硬盤之間的IO會佔用極大地系統資源,在具體應用中會採取更加高效的方法。
在FileInputStream中同樣提供了另一種方法,能夠一次讀取多個字節, int read(byte[] b),一次讀取b.length個字節,往byte數組當中讀取。能夠減少內存和硬盤之間的交互次數,提高程序的執行效率。這個方法的返回值是讀到的數組長度,當沒有讀取到內容時也是返回-1。而每一次讀取,實際上是將讀取到的內容存入byte數組,那麼第二次讀取到的的內容就會覆蓋第一次內容,如果第二次只讀取1個字節,那麼只有第一個字節會被覆蓋,數組後續的字節依然不會被改變

import java.io.FileInputStream;
import java.io.IOException;

/**
 * @author cz
 * @date 2020/6/11/011
 * 文件字節輸入流,完成的,任何類型文件都能夠採用這種方式
 * 從硬盤到內存的輸入方式
 **/
public class FileInputStramTest01 {
    public static void main(String[] args) {
        FileInputStream fileInputStream=null;
        try {
            fileInputStream = new FileInputStream("F:\\a.txt");
//            開始讀
           byte[] b = new byte[4];
            int read = fileInputStream.read(b);
            System.out.println(read);  //4
            System.out.println(new String(b));
            read = fileInputStream.read(b);
            System.out.println(read); // 4
            System.out.println(new String(b));   //dasd
            read = fileInputStream.read(b);
            System.out.println(read);  // 3
            System.out.println(new String(b));   //asdd  只讀取到3個數,覆蓋前3個
            read = fileInputStream.read(b);
            System.out.println(read);  // -1
            System.out.println(new String(b));   //asdd  沒有讀取到數字,不覆蓋
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
//            在finlly中確保流一定要進行關閉,前提是該流不能爲空
            if (fileInputStream!=null){  // 避免空指針異常
                try {
                    fileInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

這種輸出方法會將數組的全部內容輸出,於預期不符,應該是讀取到什麼,就輸出什麼。
System.out.println(new String(b,0,read)); 應該這樣,從數組0,開始輸出,長度爲讀取的長度,注意當內容結束時,再次讀取read返回值就是-1,此時0,-1就會出現數組越界。進行循環輸出和之前相同。

byte[] b = new byte[4];
           int readC = 0;
           while ((readC = fileInputStream.read(b))!=-1){
               System.out.print(new String(b,0,readC));
           }

fileInputStream的其他常用方法: int avaliable():返回流當中剩餘的字節數量,length skip(long n):跳過幾個字節數不讀。

使用avaliable()方法,能夠知道該文件的(剩餘)字節長度,可以創建出該長度的byte數組,直接一次讀出,但是不適合大文件,因爲byte數組不能太大。

import java.io.FileInputStream;
import java.io.IOException;

/**
 * @author cz
 * @date 2020/6/11/011
 * 文件字節輸入流,完成的,任何類型文件都能夠採用這種方式
 * 從硬盤到內存的輸入方式
 **/
public class FileInputStramTest01 {
    public static void main(String[] args) {
        FileInputStream fileInputStream=null;
        try {
            fileInputStream = new FileInputStream("F:\\a.txt");
//            開始讀
            System.out.println("總字節數"+fileInputStream.available());  // 11
//            int read = fileInputStream.read();
//            System.out.println("剩餘字節數"+fileInputStream.available());  //10
            byte[] b  = new byte[fileInputStream.available()];
            int readCount = fileInputStream.read(b);
            System.out.println(new String(b,0,readCount));  //a  sdasdasd
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
//            在finlly中確保流一定要進行關閉,前提是該流不能爲空
            if (fileInputStream!=null){  // 避免空指針異常
                try {
                    fileInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

skip跳過方法。

import java.io.FileInputStream;
import java.io.IOException;

/**
 * @author cz
 * @date 2020/6/11/011
 * 文件字節輸入流,完成的,任何類型文件都能夠採用這種方式
 * 從硬盤到內存的輸入方式
 **/
public class FileInputStramTest01 {
    public static void main(String[] args) {
        FileInputStream fileInputStream=null;
        try {
            fileInputStream = new FileInputStream("F:\\a.txt");
//            開始讀
            System.out.println("總字節數"+fileInputStream.available());  // 11
            fileInputStream.skip(3);
            byte[] b  = new byte[fileInputStream.available()];
            int readCount = fileInputStream.read(b);
            System.out.println(new String(b,0,readCount));  //sdasdasd
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
//            在finlly中確保流一定要進行關閉,前提是該流不能爲空
            if (fileInputStream!=null){  // 避免空指針異常
                try {
                    fileInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

以上就是關於FileIputStream的常用方法,和基本使用方式。
歡迎點贊評論,提出問題意見

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章