日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > java >内容正文

java

Java基础——Java IO详解

發(fā)布時(shí)間:2023/12/13 java 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java基础——Java IO详解 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一、概述


1、Java IO

? ? ? ?Java IO即Java 輸入輸出系統(tǒng)。不管我們編寫何種應(yīng)用,都難免和各種輸入輸出相關(guān)的媒介打交道,其實(shí)和媒介進(jìn)行IO的過(guò)程是十分復(fù)雜的,這要考慮的因素特別多,比如我們要考慮和哪種媒介進(jìn)行IO(文件、控制臺(tái)、網(wǎng)絡(luò)),我們還要考慮具體和它們的通信方式(順序、隨機(jī)、二進(jìn)制、按字符、按字、按行等等)。Java類庫(kù)的設(shè)計(jì)者通過(guò)設(shè)計(jì)大量的類來(lái)攻克這些難題,這些類就位于java.io包中。

? ? ? ?在JDK1.4之后,為了提高Java IO的效率,Java又提供了一套新的IO,Java New IO簡(jiǎn)稱Java NIO。它在標(biāo)準(zhǔn)java代碼中提供了高速的面向塊的IO操作。本篇文章重點(diǎn)介紹Java IO,關(guān)于Java NIO請(qǐng)參考我的另兩篇文章:

Java NIO詳解(一)?
Java NIO詳解(二)


2、流

? ? ? ?在Java IO中,流是一個(gè)核心的概念。流從概念上來(lái)說(shuō)是一個(gè)連續(xù)的數(shù)據(jù)流。你既可以從流中讀取數(shù)據(jù),也可以往流中寫數(shù)據(jù)。流與數(shù)據(jù)源或者數(shù)據(jù)流向的媒介相關(guān)聯(lián)。在Java IO中流既可以是字節(jié)流(以字節(jié)為單位進(jìn)行讀寫),也可以是字符流(以字符為單位進(jìn)行讀寫)。


3、IO相關(guān)的媒介

Java的IO包主要關(guān)注的是從原始數(shù)據(jù)源的讀取以及輸出原始數(shù)據(jù)到目標(biāo)媒介。以下是最典型的數(shù)據(jù)源和目標(biāo)媒介:

  • 文件
  • 管道
  • 網(wǎng)絡(luò)連接
  • 內(nèi)存緩存
  • System.in, System.out, System.error(注:Java標(biāo)準(zhǔn)輸入、輸出、錯(cuò)誤輸出)


二、Java IO類庫(kù)的框架


1、Java IO的類型

雖然java IO類庫(kù)龐大,但總體來(lái)說(shuō)其框架還是很清楚的。從是讀媒介還是寫媒介的維度看,Java IO可以分為:

? ? ? ?1)輸入流:InputStream和Reader

? ? ? ?2)輸出流:OutputStream和Writer


而從其處理流的類型的維度上看,Java IO又可以分為:

? ? ? ?1)字節(jié)流:InputStream和OutputStream

? ? ? ?2)字符流:Reader和Writer


下面這幅圖就清晰的描述了JavaIO的分類:

? 字節(jié)流 字符流
輸入流 InputStream Reader
輸出流 OutputStream Writer


? ? ? ?我們的程序需要通過(guò)InputStream或Reader從數(shù)據(jù)源讀取數(shù)據(jù),然后用OutputStream或者Writer將數(shù)據(jù)寫入到目標(biāo)媒介中。其中,InputStream和Reader與數(shù)據(jù)源相關(guān)聯(lián),OutputStream和writer與目標(biāo)媒介相關(guān)聯(lián)。 以下的圖說(shuō)明了這一點(diǎn):



2、IO類庫(kù)
? ? ? ?上面我們介紹了Java IO中的四各類:InputStream、OutputStream、Reader、Writer,其實(shí)在我們的實(shí)際應(yīng)用中,我們用到的一般是它們的子類,之所以設(shè)計(jì)這么多子類,目的就是讓每一個(gè)類都負(fù)責(zé)不同的功能,以方便我們開(kāi)發(fā)各種應(yīng)用。各類用途匯總?cè)缦?#xff1a;

  • 文件訪問(wèn)
  • 網(wǎng)絡(luò)訪問(wèn)
  • 內(nèi)存緩存訪問(wèn)
  • 線程內(nèi)部通信(管道)
  • 緩沖
  • 過(guò)濾
  • 解析
  • 讀寫文本 (Readers / Writers)
  • 讀寫基本類型數(shù)據(jù) (long, int etc.)
  • 讀寫對(duì)象

下面我們就通過(guò)兩張圖來(lái)大體了解一下這些類的繼承關(guān)系及其作用

圖1:java io 類的集成關(guān)系



圖2:java io中各個(gè)類所負(fù)責(zé)的媒介



三、Java IO的基本用法


1、Java IO:字節(jié)流

? ? ? ?通過(guò)上面的介紹我們已經(jīng)知道,字節(jié)流對(duì)應(yīng)的類應(yīng)該是InputStreamOutputStream,而在我們實(shí)際開(kāi)發(fā)中,我們應(yīng)該根據(jù)不同的媒介類型選用相應(yīng)的子類來(lái)處理。下面我們就用字節(jié)流來(lái)操作文件媒介:

例1,用字節(jié)流寫文件

public static void writeByteToFile() throws IOException{String hello= new String( "hello word!");byte[] byteArray= hello.getBytes();File file= new File( "d:/test.txt");//因?yàn)槭怯米止?jié)流來(lái)寫媒介,所以對(duì)應(yīng)的是OutputStream //又因?yàn)槊浇閷?duì)象是文件,所以用到子類是FileOutputStreamOutputStream os= new FileOutputStream( file);os.write( byteArray);os.close();} 例2,用字節(jié)流讀文件

public static void readByteFromFile() throws IOException{File file= new File( "d:/test.txt");byte[] byteArray= new byte[( int) file.length()];//因?yàn)槭怯米止?jié)流來(lái)讀媒介,所以對(duì)應(yīng)的是InputStream//又因?yàn)槊浇閷?duì)象是文件,所以用到子類是FileInputStreamInputStream is= new FileInputStream( file);int size= is.read( byteArray);System. out.println( "大小:"+size +";內(nèi)容:" +new String(byteArray));is.close();}

2、Java IO:字符流

? ? ? ?同樣,字符流對(duì)應(yīng)的類應(yīng)該是ReaderWriter。下面我們就用字符流來(lái)操作文件媒介:

例3,用字符流讀文件

public static void writeCharToFile() throws IOException{String hello= new String( "hello word!");File file= new File( "d:/test.txt");//因?yàn)槭怯米址鱽?lái)讀媒介,所以對(duì)應(yīng)的是Writer,又因?yàn)槊浇閷?duì)象是文件,所以用到子類是FileWriterWriter os= new FileWriter( file);os.write( hello);os.close();}
例4,用字符流寫文件

public static void readCharFromFile() throws IOException{File file= new File( "d:/test.txt");//因?yàn)槭怯米址鱽?lái)讀媒介,所以對(duì)應(yīng)的是Reader//又因?yàn)槊浇閷?duì)象是文件,所以用到子類是FileReaderReader reader= new FileReader( file);char [] byteArray= new char[( int) file.length()];int size= reader.read( byteArray);System. out.println( "大小:"+size +";內(nèi)容:" +new String(byteArray));reader.close();}

3、Java IO :字節(jié)流轉(zhuǎn)換為字符流
? ? ? ?字節(jié)流可以轉(zhuǎn)換成字符流,java.io包中提供的 InputStreamReader類就可以實(shí)現(xiàn),當(dāng)然從其命名上就可以看出它的作用。其實(shí)這涉及到另一個(gè)概念,IO流的 組合,后面我們?cè)敿?xì)介紹。下面看一個(gè)簡(jiǎn)單的例子:

例5 ,字節(jié)流轉(zhuǎn)換為字符流

public static void convertByteToChar() throws IOException{File file= new File( "d:/test.txt");//獲得一個(gè)字節(jié)流InputStream is= new FileInputStream( file);//把字節(jié)流轉(zhuǎn)換為字符流,其實(shí)就是把字符流和字節(jié)流組合的結(jié)果。Reader reader= new InputStreamReader( is);char [] byteArray= new char[( int) file.length()];int size= reader.read( byteArray);System. out.println( "大小:"+size +";內(nèi)容:" +new String(byteArray));is.close();reader.close();}

4、Java IO :IO類的組合

? ? ? ?從上面字節(jié)流轉(zhuǎn)換成字符流的例子中我們知道了IO流之間可以組合(或稱嵌套),其實(shí)組合的目的很簡(jiǎn)單,就是把多種類的特性融合在一起以實(shí)現(xiàn)更多的功能。組合使用的方式很簡(jiǎn)單,通過(guò)把一個(gè)流放入另一個(gè)流的構(gòu)造器中即可實(shí)現(xiàn),兩個(gè)流之間可以組合,三個(gè)或者更多流之間也可組合到一起。當(dāng)然,并不是任意流之間都可以組合。關(guān)于組合就不過(guò)多介紹了,后面的例子中有很多都用到了組合,大家好好體會(huì)即可。


5、Java IO:文件媒介操作

? ? ? ?File是Java IO中最常用的讀寫媒介,那么我們?cè)谶@里就對(duì)文件再做進(jìn)一步介紹。


1)File媒介

例6 ,File操作

public class FileDemo {public static void main(String[] args) {//檢查文件是否存在File file = new File( "d:/test.txt");boolean fileExists = file.exists();System. out.println( fileExists);//創(chuàng)建文件目錄,若父目錄不存在則返回falseFile file2 = new File( "d:/fatherDir/subDir");boolean dirCreated = file2.mkdir();System. out.println( dirCreated);//創(chuàng)建文件目錄,若父目錄不存則連同父目錄一起創(chuàng)建File file3 = new File( "d:/fatherDir/subDir2");boolean dirCreated2 = file3.mkdirs();System. out.println( dirCreated2);File file4= new File( "d:/test.txt");//判斷長(zhǎng)度long length = file4.length();//重命名文件boolean isRenamed = file4.renameTo( new File("d:/test2.txt"));//刪除文件boolean isDeleted = file4.delete();File file5= new File( "d:/fatherDir/subDir");//是否是目錄boolean isDirectory = file5.isDirectory();//列出文件名String[] fileNames = file5.list();//列出目錄File[] files = file4.listFiles();} }


2)隨機(jī)讀取File文件
? ? ? ?通過(guò)上面的例子我們已經(jīng)知道,我們可以用FileInputStream(文件字符流)或FileReader(文件字節(jié)流)來(lái)讀文件,這兩個(gè)類可以讓我們分別以字符和字節(jié)的方式來(lái)讀取文件內(nèi)容,但是它們都有一個(gè)不足之處,就是只能從文件頭開(kāi)始讀,然后讀到文件結(jié)束。

? ? ? ?但是有時(shí)候我們只希望讀取文件的一部分,或者是說(shuō)隨機(jī)的讀取文件,那么我們就可以利用RandomAccessFile。RandomAccessFile提供了seek()方法,用來(lái)定位將要讀寫文件的指針位置,我們也可以通過(guò)調(diào)用getFilePointer()方法來(lái)獲取當(dāng)前指針的位置,具體看下面的例子:

例7,隨機(jī)讀取文件

public static void randomAccessFileRead() throws IOException {// 創(chuàng)建一個(gè)RandomAccessFile對(duì)象RandomAccessFile file = new RandomAccessFile( "d:/test.txt", "rw");// 通過(guò)seek方法來(lái)移動(dòng)讀寫位置的指針file.seek(10);// 獲取當(dāng)前指針long pointerBegin = file.getFilePointer();// 從當(dāng)前指針開(kāi)始讀byte[] contents = new byte[1024];file.read( contents);long pointerEnd = file.getFilePointer();System. out.println( "pointerBegin:" + pointerBegin + "\n" + "pointerEnd:" + pointerEnd + "\n" + new String(contents));file.close();}


例8,隨機(jī)寫入文件

public static void randomAccessFileWrite() throws IOException {// 創(chuàng)建一個(gè)RandomAccessFile對(duì)象RandomAccessFile file = new RandomAccessFile( "d:/test.txt", "rw");// 通過(guò)seek方法來(lái)移動(dòng)讀寫位置的指針file.seek(10);// 獲取當(dāng)前指針long pointerBegin = file.getFilePointer();// 從當(dāng)前指針位置開(kāi)始寫file.write( "HELLO WORD".getBytes());long pointerEnd = file.getFilePointer();System. out.println( "pointerBegin:" + pointerBegin + "\n" + "pointerEnd:" + pointerEnd + "\n" );file.close();}


6、Java IO:管道媒介

? ? ? ?管道主要用來(lái)實(shí)現(xiàn)同一個(gè)虛擬機(jī)中的兩個(gè)線程進(jìn)行交流。因此,一個(gè)管道既可以作為數(shù)據(jù)源媒介也可作為目標(biāo)媒介。
? ? ? ?需要注意的是java中的管道和Unix/Linux中的管道含義并不一樣,在Unix/Linux中管道可以作為兩個(gè)位于不同空間進(jìn)程通信的媒介,而在java中,管道只能為同一個(gè)JVM進(jìn)程中的不同線程進(jìn)行通信。和管道相關(guān)的IO類為: PipedInputStreamPipedOutputStream,下面我們來(lái)看一個(gè)例子:

例9,讀寫管道

public class PipeExample {public static void main(String[] args) throws IOException {final PipedOutputStream output = new PipedOutputStream();final PipedInputStream input = new PipedInputStream(output);Thread thread1 = new Thread( new Runnable() {@Overridepublic void run() {try {output.write( "Hello world, pipe!".getBytes());} catch (IOException e) {}}});Thread thread2 = new Thread( new Runnable() {@Overridepublic void run() {try {int data = input.read();while( data != -1){System. out.print(( char) data);data = input.read();}} catch (IOException e) {} finally{try {input.close();} catch (IOException e) {e.printStackTrace();}}}});thread1.start();thread2.start();} }


7、Java IO:網(wǎng)絡(luò)媒介

? ? ? ?關(guān)于Java IO面向網(wǎng)絡(luò)媒介的操作即Java 網(wǎng)絡(luò)編程,其核心是Socket,同磁盤操作一樣,java網(wǎng)絡(luò)編程對(duì)應(yīng)著兩套API,即Java IO和Java NIO,關(guān)于這部分我會(huì)準(zhǔn)備專門的文章進(jìn)行介紹。


8、Java IO:BufferedInputStream和BufferedOutputStream

? ? ? ?BufferedInputStream顧名思義,就是在對(duì)流進(jìn)行寫入時(shí)提供一個(gè)buffer來(lái)提高IO效率。在進(jìn)行磁盤或網(wǎng)絡(luò)IO時(shí),原始的InputStream對(duì)數(shù)據(jù)讀取的過(guò)程都是一個(gè)字節(jié)一個(gè)字節(jié)操作的,而B(niǎo)ufferedInputStream在其內(nèi)部提供了一個(gè)buffer,在讀數(shù)據(jù)時(shí),會(huì)一次讀取一大塊數(shù)據(jù)到buffer中,這樣比單字節(jié)的操作效率要高的多,特別是進(jìn)程磁盤IO和對(duì)大量數(shù)據(jù)進(jìn)行讀寫的時(shí)候。

? ? ? ?使用BufferedInputStream十分簡(jiǎn)單,只要把普通的輸入流和BufferedInputStream組合到一起即可。我們把上面的例2改造成用BufferedInputStream進(jìn)行讀文件,請(qǐng)看下面例子:

例10 ,用緩沖流讀文件

public static void readByBufferedInputStream() throws IOException {File file = new File( "d:/test.txt");byte[] byteArray = new byte[( int) file.length()];//可以在構(gòu)造參數(shù)中傳入buffer大小InputStream is = new BufferedInputStream( new FileInputStream(file),2*1024);int size = is.read( byteArray);System. out.println( "大小:" + size + ";內(nèi)容:" + new String(byteArray));is.close(); }
? ? ? ?關(guān)于如何設(shè)置buffer的大小,我們應(yīng)根據(jù)我們的硬件狀況來(lái)確定。對(duì)于磁盤IO來(lái)說(shuō),如果硬盤每次讀取4KB大小的文件塊,那么我們最好設(shè)置成這個(gè)大小的整數(shù)倍。因?yàn)榇疟P對(duì)于順序讀的效率是特別高的,所以如果buffer再設(shè)置的大寫可能會(huì)帶來(lái)更好的效率,比如設(shè)置成4*4KB或8*4KB。
? ? ? ?還需要注意一點(diǎn)的就是磁盤本身就會(huì)有緩存,在這種情況下,BufferedInputStream會(huì)一次讀取磁盤緩存大小的數(shù)據(jù),而不是分多次的去讀。所以要想得到一個(gè)最優(yōu)的buffer值,我們必須得知道磁盤每次讀的塊大小和其緩存大小,然后根據(jù)多次試驗(yàn)的結(jié)果來(lái)得到最佳的buffer大小。

? ? ? ?BufferedOutputStream的情況和BufferedInputStream一致,在這里就不多做描述了。


9、Java IO:BufferedReader和BufferedWriter

? ? ? ?BufferedReader、BufferedWriter?的作用基本和BufferedInputStream、BufferedOutputStream一致,具體用法和原理都差不多 ,只不過(guò)一個(gè)是面向字符流一個(gè)是面向字節(jié)流。同樣,我們將改造字符流中的例4,給其加上buffer功能,看例子:

public static void readByBufferedReader() throws IOException {File file = new File( "d:/test.txt");// 在字符流基礎(chǔ)上用buffer流包裝,也可以指定buffer的大小Reader reader = new BufferedReader( new FileReader(file),2*1024);char[] byteArray = new char[( int) file.length()];int size = reader.read( byteArray);System. out.println( "大小:" + size + ";內(nèi)容:" + new String(byteArray));reader.close(); }

總結(jié)

以上是生活随笔為你收集整理的Java基础——Java IO详解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。