小师妹学JavaIO之:文件写入那些事
文章目錄
- 簡(jiǎn)介
- 字符輸出和字節(jié)輸出
- 格式化輸出
- 輸出其他對(duì)象
- 在特定的位置寫入
- 給文件加鎖
- 總結(jié)
簡(jiǎn)介
小師妹又對(duì)F師兄提了一大堆奇奇怪怪的需求,要格式化輸出,要特定的編碼輸出,要自己定位輸出,什么?還要閱后即焚?大家看F師兄怎么一一接招吧。
字符輸出和字節(jié)輸出
小師妹:F師兄,上次你的IO講到了一半,文件讀取是基本上講完了,但是文件的寫入還沒有講,什么時(shí)候給小師妹我再科普科普?
小師妹:F師兄,你知道我這個(gè)人一直以來都是勤奮好學(xué)的典范,是老師們眼中的好學(xué)生,同學(xué)們心中的好榜樣,父母身邊乖巧的好孩子。在我永攀科學(xué)高峰的時(shí)候,居然發(fā)現(xiàn)還有一半的知識(shí)沒有獲取,真是讓我扼腕嘆息,F師兄,快快把知識(shí)傳給我吧。
小師妹你的請(qǐng)求,師兄我自當(dāng)盡力辦到,但是我怎么記得上次講IO文件讀取已經(jīng)過了好幾天了,怎么今天你才來找我。
小師妹紅著臉:F師兄,這不是使用的時(shí)候遇到了點(diǎn)問題,才想找你把知識(shí)再?gòu)?fù)習(xí)一遍。
更多精彩內(nèi)容且看:
- 區(qū)塊鏈從入門到放棄系列教程-涵蓋密碼學(xué),超級(jí)賬本,以太坊,Libra,比特幣等持續(xù)更新
- Spring Boot 2.X系列教程:七天從無到有掌握Spring Boot-持續(xù)更新
- Spring 5.X系列教程:滿足你對(duì)Spring5的一切想象-持續(xù)更新
- java程序員從小工到專家成神之路(2020版)-持續(xù)更新中,附詳細(xì)文章教程
那先把輸出類的結(jié)構(gòu)再過一遍:
上面就是輸出的兩大系統(tǒng)了:Writer和OutputStream。
Writer主要針對(duì)于字符,而Stream主要針對(duì)Bytes。
Writer中最最常用的就是FileWriter和BufferedWriter,我們看下一個(gè)最基本寫入的例子:
public void useBufferedWriter() throws IOException {String content = "www.flydean.com";File file = new File("src/main/resources/www.flydean.com");FileWriter fw = new FileWriter(file);try(BufferedWriter bw = new BufferedWriter(fw)){bw.write(content);}}BufferedWriter是對(duì)FileWriter的封裝,它提供了一定的buffer機(jī)制,可以提高寫入的效率。
其實(shí)BufferedWriter提供了三種寫入的方式:
public void write(int c) public void write(char cbuf[], int off, int len) public void write(String s, int off, int len)第一個(gè)方法傳入一個(gè)int,第二個(gè)方法傳入字符數(shù)組和開始讀取的位置和長(zhǎng)度,第三個(gè)方法傳入字符串和開始讀取的位置和長(zhǎng)度。是不是很簡(jiǎn)單,完全可以理解?
小師妹:不對(duì)呀,F師兄,后面兩個(gè)方法的參數(shù),不管是char和String都是字符我可以理解,第一個(gè)方法傳入int是什么鬼?
小師妹,之前跟你講的道理是不是都忘記的差不多了,int的底層存儲(chǔ)是bytes,char和String的底層存儲(chǔ)也是bytes,我們把int和char做個(gè)強(qiáng)制轉(zhuǎn)換就行了。我們看下是怎么轉(zhuǎn)換的:
public void write(int c) throws IOException {synchronized (lock) {ensureOpen();if (nextChar >= nChars)flushBuffer();cb[nextChar++] = (char) c;}}還記得int需要占用多少個(gè)字節(jié)嗎?4個(gè),char需要占用2個(gè)字節(jié)。這樣強(qiáng)制從int轉(zhuǎn)換到char會(huì)有精度丟失的問題,只會(huì)保留低位的2個(gè)字節(jié)的數(shù)據(jù),高位的兩個(gè)字節(jié)的數(shù)據(jù)會(huì)被丟棄,這個(gè)需要在使用中注意。
看完Writer,我們?cè)賮砜纯碨tream:
public void useFileOutputStream() throws IOException {String str = "www.flydean.com";try(FileOutputStream outputStream = new FileOutputStream("src/main/resources/www.flydean.com");BufferedOutputStream bufferedOutputStream= new BufferedOutputStream(outputStream)){byte[] strToBytes = str.getBytes();bufferedOutputStream.write(strToBytes);}}跟Writer一樣,BufferedOutputStream也是對(duì)FileOutputStream的封裝,我們看下BufferedOutputStream中提供的write方法:
public synchronized void write(int b) public synchronized void write(byte b[], int off, int len)比較一下和Writer的區(qū)別,BufferedOutputStream的方法是synchronized的,并且BufferedOutputStream是直接對(duì)byte進(jìn)行操作的。
第一個(gè)write方法傳入int參數(shù)也是需要進(jìn)行截取的,不過這次是從int轉(zhuǎn)換成byte。
格式化輸出
小師妹:F師兄,我們經(jīng)常用的System.out.println可以直接向標(biāo)準(zhǔn)輸出中輸出格式化過后的字符串,文件的寫入是不是也有類似的功能呢?
肯定有,PrintWriter就是做格式化輸出用的:
public void usePrintWriter() throws IOException {FileWriter fileWriter = new FileWriter("src/main/resources/www.flydean.com");try(PrintWriter printWriter = new PrintWriter(fileWriter)){printWriter.print("www.flydean.com");printWriter.printf("程序那些事 %s ", "非常棒");}}輸出其他對(duì)象
小師妹:F師兄,我們看到可以輸出String,char還有Byte,那可不可以輸出Integer,Long等基礎(chǔ)類型呢?
可以的,使用DataOutputStream就可以做到:
public void useDataOutPutStream()throws IOException {String value = "www.flydean.com";try(FileOutputStream fos = new FileOutputStream("src/main/resources/www.flydean.com")){DataOutputStream outStream = new DataOutputStream(new BufferedOutputStream(fos));outStream.writeUTF(value);}}DataOutputStream提供了writeLong,writeDouble,writeFloat等等方法,還可以writeUTF!
在特定的位置寫入
小師妹:F師兄,有時(shí)候我們不需要每次都從頭開始寫入到文件,能不能自定義在什么位置寫入呢?
使用RandomAccessFile就可以了:
public void useRandomAccess() throws IOException {try(RandomAccessFile writer = new RandomAccessFile("src/main/resources/www.flydean.com", "rw")){writer.seek(100);writer.writeInt(50);}}RandomAccessFile可以通過seek來定位,然后通過write方法從指定的位置寫入。
給文件加鎖
小師妹:F師兄,最后還有一個(gè)問題,怎么保證我在進(jìn)行文件寫的時(shí)候別人不會(huì)覆蓋我寫的內(nèi)容,不會(huì)產(chǎn)生沖突呢?
FileChannel可以調(diào)用tryLock方法來獲得一個(gè)FileLock鎖,通過這個(gè)鎖,我們可以控制文件的訪問。
public void useFileLock()throws IOException {try(RandomAccessFile stream = new RandomAccessFile("src/main/resources/www.flydean.com", "rw");FileChannel channel = stream.getChannel()){FileLock lock = null;try {lock = channel.tryLock();} catch (final OverlappingFileLockException e) {stream.close();channel.close();}stream.writeChars("www.flydean.com");lock.release();}}總結(jié)
今天給小師妹講了好多種文件的寫的方法,夠她學(xué)習(xí)一陣子了。
本文的例子https://github.com/ddean2009/learn-java-io-nio
本文作者:flydean程序那些事
本文鏈接:http://www.flydean.com/io-file-writer/
本文來源:flydean的博客
歡迎關(guān)注我的公眾號(hào):程序那些事,更多精彩等著您!
總結(jié)
以上是生活随笔為你收集整理的小师妹学JavaIO之:文件写入那些事的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Lambda表达式和闭包Closure
- 下一篇: Java中的类型推断和lambda表达式