首頁  >  文章  >  类库下载  >  Java檔案I/O的三種方法

Java檔案I/O的三種方法

高洛峰
高洛峰原創
2016-10-12 17:53:311930瀏覽

之前在面試中被問到過兩次Java中文件讀入輸出怎麼寫,當時只記得一個大概,沒有辦法很清晰的說出一個條理,今天特地看出總結了一下這方面的內容,想要寫出來給大家分享。

首先檔案讀入輸出流常用有三種:FileInputStream/FileOutputStream,FileReader/FileWriter,RandomAccessFile。以下具體列出一些簡單的例子參考:

基礎篇:

1.

FileRead fr = new FileReader(filename);  
String s;  
while( (s=fr.readLine())!=null){  
...  
}  
fr.close();  
//FileWriter同理,输出时可用write()函数  
//Java I/O中所有的Reader、Writer都是面向字符流的输出输出

2.

FileInputStream fi =new FileInputStream(filename);  
int in;  
while( (in=fi.read())!=-1){  
...  
}  
fi.close();  
//FileOutputStream同理  
//Java I/O中所有的Reader、Writer都是面向字节流的输出输出

3.

RandomAccessFile ra =new RandomAccessFile(filename,"rw");//后面的参数指定的是  
打开文件流的方式,“rw”是指读写,“r”是只读,Java不提供只写  
ra.seek(number);//将文件指针移动到number处,这里文件指针可以理解为文件开始读的位置  
ra.skipByte(number);//跳过number个字节  
ra.read();  
ra.close();  
//RandomAccessFile既可以读也可以写,而且可以利用seek()函数指定位置

下面是百度百科全書的一些介紹:

RandStreampippippppp生活裡是不屬於人類的一些介紹:

RandStream系的。實際上,除了實作DataInput和DataOutput介面之外(DataInputStream和DataOutputStream也實作了這兩個介面),它和這兩個類別系毫不相干,甚至沒有用InputStream和OutputStream已經準備好的功能;它是一個完全獨立的類,所有方法(絕大多數都只屬於它自己)都是從零開始寫的。這可能是因為RandomAccessFile能在文件裡面前後移動,所以它的行為與其它的I/O類別有些根本性的不同。總而言之,它是一個直接繼承Object的,獨立的類別。

進階篇:

在nio中,Java重新實現了I/O流,並且引入了一些新的方法來提高速度。我主要介紹通道、記憶體映射檔

1.通道:

通道和緩衝器是一個成對的概念,Thinking in Java中的一個例子特別好理解:我們把想要讀入的文件看作一個煤礦,數據就是我們想要的煤炭。通道好比是傳送煤礦的傳送帶,我們沒有辦法直接從傳送帶上拿走煤炭,只好利用卡車來裝載這些煤炭,卡車就是緩衝器,它主要負責從通道中取出數據,傳給我們寫的程序。唯一能與通道互動的緩衝器是ByteBuffer。可以看出和通道支援的解析流的方式是位元組流。所以它配套使用的是FileInputStream/FileOutputStream,RandomAccessFile

例子:

a.

FileChannel fc =new FileOutputStream(filename).getChannel();  
fc.write(ByteBuffer.wrap("something test".getBytes() ));//这里使用ByteBuffer比较简单,其实ByteBuffer可以利用个put()函数写入byte数组  
fc.close();

b.

fc= new FileOutputStream(filename).getChannel();  
ByteBuffer buff = ByteBuffer.allocate(size);//没错,ByteBuffer是不提供显示构造函数的,想要新建一个对象必须利用allocate()函数来分配空间。  
fc.read(buff);  
fc.close();

為什麼想到要用通道來做I/O?主要考慮的是性能問題,通道加緩衝器能夠讓程式一些讀寫一定量的字符,而只使用InputStream/OutputStream,Reader/Writer只能一次讀寫一個位元組/字符。而程式在進行I/O時要交給作業系統去解決這部分功能(呼叫系統呼叫),減少交給作業系統的次數可以有效的消減I/O花費的時間

2.記憶體映射檔:

記憶體映射檔案主要的意思其實假定將檔案都放入記憶體中,把它當作非常大的數組來訪問,效率特別好。為什麼比較好呢?這要從Java虛擬機和作業系統開始說起le(其實我也不太懂,剛才看了一篇文章講的比較清晰,連結是http://www.360doc.com/content ...)這篇文章主要介紹了Java I/O的原理以及記憶體映射檔案的原理。我嘗試概括一下:Java I/O主要的實作手段肯定是利用系統調用,而係統調用先將想要使用的檔案從硬碟調入到核心的I/O緩衝區中,這次會導入比Java程序想要的檔案更多的內容(拷入更多的內容是因為程式的局部性原理,能夠得到更好的效率),然後再從核心的I/O緩衝區導入到Java進程自己的私有記憶體空間中。而記憶體映射檔案放棄了兩次拷貝的方法,直接將Java進程的虛擬空間與檔案物件構成一個映射,當私有記憶體空間找不打想要的內容時發生缺頁異常,然後利用更底層的系統呼叫解決這個問題(其實在I/O的系統呼叫中也涉及到了缺頁異常處理),好處就是減少了一次從內核I/O緩衝區到進程私有地址的開銷。

例子:

FileChannel fc = new RandomAccessFile(filename,"rw").getChannel();  
MappedByteBuffer mb = fc.map(FileChannel.MapMode.READ_WRITE,start,length);  
mb.put((byte)'x');  
mb.get();  
fc.close();
🎜寫到這裡突然想到在《孔乙己》中「 Hayes」的4中寫法,現在Java開啟檔案也有了至少五種方法了,每一種都一各有利弊。以後也可以穿著長袍問別人你知道Java讀寫文件的5種方法麼🎜
陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn