java io

設計模式

裝飾者模式、適配器模式java

類別

同步阻塞IO(BIO)

BIO是一個鏈接一個線程。面試

傳統的同步阻塞模型開發中,ServerSocket負責綁定IP地址,啓動監聽端口;Socket負責發起鏈接操做。鏈接成功後,雙方經過輸入和輸出流進行同步阻塞式通訊。編程

該模型最大的問題就是缺少彈性伸縮能力,當客戶端併發訪問量增長後,服務端的線程個數和客戶端併發訪問數呈1:1的正比關係,Java中的線程也是比較寶貴的系統資源,線程數量快速膨脹後,系統的性能將急劇降低,隨着訪問量的繼續增大,系統最終就死-掉-了設計模式

同步非阻塞IO(NIO)

NIO提供了與傳統BIO模型中的Socket和ServerSocket相對應的SocketChannel和ServerSocketChannel兩種不一樣的套接字通道實現。兩種通道都支持阻塞和非阻塞兩種模式。數組

對於低負載、低併發的應用程序,可使用同步阻塞I/O來提高開發速率和更好的維護性;對於高負載、高併發的(網絡)應用,應使用NIO的非阻塞模式來開發。安全

  • 緩衝區服務器

    java.nio.Buffer是一個抽象類。網絡

    在NIO庫中,全部數據都是用緩衝區處理的,緩衝區包含一些要寫入或者讀出的數據。數據結構

    緩衝區其實是一個數組,並提供了對數據結構化訪問以及維護讀寫位置等信息。如:ByteBuffer、CharBuffer、 ShortBuffer、IntBuffer、LongBuffer、FloatBuffer、DoubleBuffer。併發

  • 通道

    咱們對數據的讀取和寫入要經過Channel,它就像水管同樣,是一個通道。通道不一樣於流的地方就是通道是雙向的,能夠用於讀、寫和同時讀寫操做。

    底層的操做系統的通道通常都是全雙工的,因此全雙工的Channel比流能更好的映射底層操做系統的API。

    • ​ SelectableChannel:用戶網絡讀寫
    • ​ FileChannel:用於文件操做
  • 多路複用器

    Selector提供選擇已經就緒的任務的能力:Selector會不斷輪詢註冊在其上的Channel,若是某個Channel上面發生讀或者寫事件,這個Channel就處於就緒狀態,會被Selector輪詢出來,而後經過SelectionKey能夠獲取就緒Channel的集合,進行後續的I/O操做。

    一個Selector能夠同時輪詢多個Channel,由於JDK使用了epoll()代替傳統的select實現,因此沒有最大鏈接句柄1024/2048的限制。因此,只須要一個線程負責Selector的輪詢,就能夠接入成千上萬的客戶端。

    • select和poll具備O(n)的無差異輪詢複雜度
    • epoll事件複雜度爲O(1),基於時間驅動的

NIO是一個請求一個線程,即客戶端發送的鏈接請求都會註冊到多路複用器上,多路複用器輪詢到鏈接有I/O請求時才啓動一個線程進行處理。

適用場景:聊天服務器

異步非阻塞IO(AIO)

NIO 2.0引入了新的異步通道的概念,並提供了異步文件通道和異步套接字通道的實現。

異步的套接字通道是真正的異步非阻塞I/O,對應於UNIX網絡編程中的事件驅動I/O(AIO)。他不須要過多的Selector對註冊的通道進行輪詢便可實現異步讀寫,從而簡化了NIO的編程模型。

  • AsynchronousSocketChannel
  • AsynchronousServerSocketChannel
  • AsynchronousFileChannel
  • AsynchronousDatagramChannel

AIO是一個有效請求一個線程,客戶端的I/O請求都是由OS先完成了再通知服務器應用去啓動線程進行處理。

適用場景:相冊服務器

根據處理數據類型分類

流式

主體部分

字節流

按字節讀,可用於文件、圖片、視頻、音頻

OutputStream、InputStream

字符流

按字符讀,通常用於文件

Writer、Reader

Java中字符是採用Unicode標準,一個字符是16位,即一個字符使用兩個字節來表示。爲此,JAVA中引入了處理字符的流。由於數據編碼的不一樣,而有了對字符進行高效操做的流對象。本質其實就是基於字節流讀取時,去查了指定的碼錶。

字節流沒有緩衝區,是直接輸出的,而字符流是輸出到緩衝區的。所以在輸出時,字節流不調用close()方法時,信息已經輸出了,而字符流只有在調用close()方法關閉緩衝區時,信息才輸出。要想字符流在未關閉時輸出信息,則須要手動調用flush()方法。

非流式

輔助流式部分的類,如:File、RandomAccessFile、FileDescriptor

其餘類

文件讀取部分的與安全相關的類,如:SerializablePermission;

與本地操做系統相關的文件系統的類,如:FileSystem、Win32FileSystem、WinNTFileSystem。

根據數據來源/操做對象分類

  • 一、文件(file):FileInputStream、FileOutputStream、FileReader、FileWriter
  • 二、數組([]):
    • 2.一、字節數組(byte[]):ByteArrayInputStream、ByteArrayOutputStream
    • 2.二、字符數組(char[]):CharArrayReader、CharArrayWriter
  • 三、管道操做:PipedInputStream、PipedOutputStream、PipedReader、PipedWriter
  • 四、基本數據類型:DataInputStream、DataOutputStream
  • 五、緩衝操做:BufferedInputStream、BufferedOutputStream、BufferedReader、BufferedWriter
  • 六、打印:PrintStream、PrintWriter
  • 七、對象序列化反序列化:ObjectInputStream、ObjectOutputStream
  • 八、轉換:InputStreamReader、OutputStreWriter
  • 九、字符串(String)Java8中已廢棄StringBufferInputStream、StringBufferOutputStream、StringReader、StringWriter

面試題

  1. 什麼是IO流?
    它是一種數據的流從源頭流到目的地。好比文件拷貝,輸入流和輸出流都包括了。輸入流從文件中讀取數據存儲到進程(process)中,輸出流從進程中讀取數據而後寫入到目標文件。

  2. 字節流和字符流的區別。
    字節流在JDK1.0中就被引進了,用於操做包含ASCII字符的文件。JAVA也支持其餘的字符如Unicode,爲了讀取包含Unicode字符的文件,JAVA語言設計者在JDK1.1中引入了字符流。ASCII做爲Unicode的子集,對於英語字符的文件,能夠可使用字節流也可使用字符流。

  3. Java中流類的超類主要由那些?

    • java.io.InputStream
    • java.io.OutputStream
    • java.io.Reader
    • java.io.Writer
  4. FileInputStream和FileOutputStream是什麼?
    這是在拷貝文件操做的時候,常常用到的兩個類。在處理小文件的時候,它們性能表現還不錯,在大文件的時候,最好使用BufferedInputStream (或 BufferedReader) 和 BufferedOutputStream (或 BufferedWriter)

    public class InputAndOutputBuffering {
        public static void main(String args[]) throws IOException {
            FileInputStream fistream = new FileInputStream("pqr.txt");
            BufferedInputStream bistream = new BufferedInputStream(fistream);
    
            FileOutputStream fostream = new FileOutputStream("xyz.txt");
            BufferedOutputStream bostream = new BufferedOutputStream(fostream);
    
            int temp;
            while( ( temp = bistream.read() ) != -1 ) {
                bostream.write(temp);
                System.out.print((char) temp);
            }
            bostream.close();
            fostream.close();
            bistream.close();
            fistream.close();
        }
    }
  5. 字節流和字符流,你更喜歡使用拿一個?
    我的來講,更喜歡使用字符流,由於他們更新一些。許多在字符流中存在的特性,字節流中不存在。好比使用BufferedReader而不是BufferedInputStreams或DataInputStream,使用newLine()方法來讀取下一行,可是在字節流中咱們須要作額外的操做。

  6. System.out.println()是什麼?
    println是PrintStream的一個方法。out是一個靜態PrintStream類型的成員變量,System是一個java.lang包中的類,用於和底層的操做系統進行交互。

  7. 什麼是Filter流?
    Filter Stream是一種IO流主要做用是用來對存在的流增長一些額外的功能,像給目標文件增長源文件中不存在的行數,或者增長拷貝的性能。

  8. 有哪些可用的Filter流?
    在java.io包中主要由4個可用的filter Stream。兩個字節filter stream,兩個字符filter stream,分別是FilterInputStream, FilterOutputStream, FilterReader and FilterWriter。這些類是抽象類,不能被實例化的。

  9. SequenceInputStream的做用?
    在拷貝多個文件到一個目標文件的時候是很是有用的。可用使用不多的代碼實現

    public class TwoFiles {
        public static void main(String args[]) throws IOException {
            FileInputStream fistream1 = new FileInputStream("A.txt");  // first source file
            FileInputStream fistream2 = new FileInputStream("B.txt");  //second source file
    
            SequenceInputStream sistream = new SequenceInputStream(fistream1, fistream2);
            FileOutputStream fostream = new FileOutputStream("C.txt");// destination file
    
            int temp;
            while( ( temp = sistream.read() ) != -1) {
                System.out.print( (char) temp ); // to print at DOS prompt
                fostream.write(temp);   // to write to file
            }
            fostream.close();
            sistream.close();
            fistream1.close();
            fistream2.close();
        }
    }
  10. 說說PrintStream和PrintWriter
    他們兩個的功能相同,可是屬於不一樣的分類。字節流和字符流。他們都有println()方法。

  11. 在文件拷貝的時候,那一種流可用提高更多的性能?
    在字節流的時候,使用BufferedInputStream和BufferedOutputStream。
    在字符流的時候,使用BufferedReader 和 BufferedWriter

  12. 說說管道流(Piped Stream)
    有四種管道流, PipedInputStream, PipedOutputStream, PipedReader 和 PipedWriter.在多個線程或進程中傳遞數據的時候管道流很是有用。

  13. 說說File類
    它不屬於 IO流,也不是用於文件操做的,它主要用於知道一個文件的屬性,讀寫權限,大小等信息。

  14. 說說RandomAccessFile?
    它在java.io包中是一個特殊的類,既不是輸入流也不是輸出流,它二者均可以作到。他是Object的直接子類。一般來講,一個流只有一個功能,要麼讀,要麼寫。可是RandomAccessFile既能夠讀文件,也能夠寫文件。 DataInputStream 和 DataOutStream有的方法,在RandomAccessFile中都存在。

做者:艾賀521 連接:https://www.imooc.com/article/24305

相關文章
相關標籤/搜索