一文帶你了解Java中IO流與Guava的使用
Guava IO
日常系統(tǒng)交互中,文件的上傳下載都是常見的,一般我們會通過jdk提供的IO操作庫幫助我們實現(xiàn)。IO指的是數(shù)據(jù)相對當(dāng)前操作程序的入與出,將數(shù)據(jù)通過 輸出流從程序輸出,或者通過輸入流將數(shù)據(jù)(從文件、網(wǎng)絡(luò)、數(shù)據(jù)等)寫入到程序,這里的IO指的是基于流作為載體進(jìn)行數(shù)據(jù)傳輸。如果把數(shù)據(jù)比作合理的水,河就是IO流,也是數(shù)據(jù)的載體。
Java為我們提供了非常多的操作IO的接口與類,幫助開發(fā)者實現(xiàn)不同源間的數(shù)據(jù)傳輸,比如硬盤文件、網(wǎng)絡(luò)傳輸、應(yīng)用調(diào)用間的數(shù)據(jù)交互與傳遞。今天我們來簡單了解下Java中的流 以及在Guava工具包中,針對IO操作做了什么樣的封裝與設(shè)計。
分類
在java.io包中有非常多的IO相關(guān)接口,我們可以根據(jù)流的輸出類型、處理對象以及功能將其分為以下幾種類型:
按數(shù)據(jù)流向
- 輸入流 (java.io.InputStream) 用于實現(xiàn)將數(shù)據(jù)讀入到程序
- 輸出流 (java.io.OutputStream) 用于實現(xiàn)將數(shù)據(jù)從程序?qū)懗?/li>
按操作單位
- 字節(jié)流:以字節(jié)(byte)為單位進(jìn)行數(shù)據(jù)的讀、寫 (其中針對文件也提供了按基礎(chǔ)數(shù)據(jù)類型的讀與寫DataInpoutStream,也就是按照J(rèn)ava基礎(chǔ)類型所占字節(jié)數(shù)來進(jìn)行定量字節(jié)讀取并合并)
- 字符流:以字符(char)為單位進(jìn)行數(shù)據(jù)的讀、寫,此時需要注意字符編碼
區(qū)分:
字節(jié)流一般以Stream結(jié)尾 字符流一般以Reader或Writer結(jié)尾
按操作方式
- 讀 (java.io.Reader):主要針對字符流的讀取操作
- 寫 (java.io.Writer):主要針對字符流的寫出操作
按功能
- 緩存流:按字節(jié)進(jìn)行數(shù)據(jù)讀寫時,通過緩沖批量寫入來提高傳輸效率
- 轉(zhuǎn)換流:實現(xiàn)輸入/出與讀/寫方式間的轉(zhuǎn)換
常用的流
操作文件的
java.io.FileinputStream/FileOutputStream java.io.FileReader/FileWriter
通用的字節(jié)流
java.io.InputStreamReader/outputStreamWriter
緩沖流
java.io.BufferedReader/BufferedWriter java.io.BufferedInputStream/BufferedOutputStream
數(shù)據(jù)流
java.io.DataInpoutStream/DataOutputStream
功能型的
java.io.PrintWriter/PrintStream
對象序列化相關(guān)的
java.io.ObjectInputStream/ObjectOutputStream
可見,提供的IO對象基本都是成對出現(xiàn)的,用以完成數(shù)據(jù)的輸入輸出,實現(xiàn)程序與外部載體間的數(shù)據(jù)交換
示例
下面我們通過一些常用示例來看看IO的使用的場景與使用方法:
- 文件復(fù)制
- 文件的合并
- 讀取文件內(nèi)容為字符串
- 字節(jié)數(shù)組轉(zhuǎn)換成流
- 對象序列化與反序列化
- 流的轉(zhuǎn)換
- ......
文件復(fù)制
????@Test ????public?void?copyByBytes()?throws?IOException?{ ????????String?root?=?FileTests.class.getResource("/").getPath(); ????????FileInputStream?fis?=?new?FileInputStream(new?File(root,"/start.bat")); ????????FileOutputStream?fos?=?new?FileOutputStream(root+"/out2.bat"); ????????byte[]?buff?=?new?byte[100]; ????????int?b; ????????while?(?(b?=?fis.read(buff))!=-1?){ ????????????fos.write(buff,?0,?b); ????????} ????????//?close ????}
文件合并
@Test ????public?void?mergeFiles()?throws?IOException?{ ????????File?file1?=?new?File("E:\\_projects\\sucls\\blog\\my_study\\guava\\guava-io\\src\\test\\java\\com\\sucls\\blog\\guava\\io\\category\\FileTests.java"); ????????File?file2?=?new?File("E:\\_projects\\sucls\\blog\\my_study\\guava\\guava-io\\src\\test\\java\\com\\sucls\\blog\\guava\\io\\category\\StreamTests.java"); ????????Enumeration<InputStream>?ins?=?Collections.enumeration(Arrays.asList( ????????????????new?FileInputStream(file1), ????????????????new?FileInputStream(file2) ????????)); ????????SequenceInputStream?sequenceInputStream?=?new?SequenceInputStream(ins); ????????FileOutputStream?fos?=?new?FileOutputStream(root+"/out4"); ????????byte[]?buff?=?new?byte[100]; ????????int?read;?//?真實讀取到的字節(jié)數(shù) ????????while?(?(read?=?sequenceInputStream.read(buff))?!=-1){ ????????????fos.write(buff,?0,?read); ????????} ????????fos.close(); ????}
讀取文件內(nèi)容為字符串
????@Test ????public?void?readStringFromFile()?throws?IOException?{ ????????FileReader?fileReader?=?new?FileReader(new?File(this.getClass().getResource("/").getPath(),"/start.bat")); ????????StringBuilder?stringBuilder?=?new?StringBuilder(); ????????int?i; ????????while?(?(i?=?fileReader.read())!=-1?){ ????????????stringBuilder.append(?(char)i?);?//?按字符讀取 ????????} ????????System.out.println(?stringBuilder?);?//?文件內(nèi)容 ????}
字節(jié)數(shù)組轉(zhuǎn)換成流
????@Test ????public?void?bytesToStream(){ ????????byte?[]?data?=?new?byte[1024];?//?來源于其他數(shù)據(jù)源 ????????ByteArrayInputStream?inputStream?=?new?ByteArrayInputStream(data); ????????ByteArrayOutputStream?outputStream?=?new?ByteArrayOutputStream(); ????????int?v; ????????while?(?(v=inputStream.read())!=-1?){ ????????????outputStream.write(v); ????????} ????????System.out.println(?Arrays.toString(?outputStream.toByteArray()?)); ????}
對象序列化與反序列化
@Test ????public?void?objectToFile()?throws?IOException?{ ????????Person?person?=?new?Person(); ????????person.setName("張三").setAge(25); ????????String?root?=?FileTests.class.getResource("/").getPath(); ????????FileOutputStream?fos?=?new?FileOutputStream(new?File(root,"/person")); ????????ObjectOutputStream?oos?=?new?ObjectOutputStream(fos); ????????oos.writeObject(person); ????} ????@Test ????public?void?fileToObject()?throws?IOException,?ClassNotFoundException?{ ????????String?root?=?FileTests.class.getResource("/").getPath(); ????????FileInputStream?fis?=?new?FileInputStream(new?File(root,"/person")); ????????ObjectInputStream?ois?=?new?ObjectInputStream(fis); ????????Person?person?=?(Person)?ois.readObject(); ????????System.out.println(?person?); ????}
流的轉(zhuǎn)換 將字節(jié)流轉(zhuǎn)換成字符流來操作,同樣以文件復(fù)制為例
????@Test ????public?void?copyByBuffer()?throws?IOException?{ ????????String?root?=?FileTests.class.getResource("/").getPath(); ????????FileInputStream?fis?=?new?FileInputStream(new?File(root,"/start.bat")); ????????InputStreamReader?isr?=?new?InputStreamReader(fis); ????????BufferedReader?br?=?new?BufferedReader(isr); ????????FileOutputStream?fos?=?new?FileOutputStream(root+"/out3.bat"); ????????OutputStreamWriter?osw?=?new?OutputStreamWriter(fos); ????????BufferedWriter?bw?=?new?BufferedWriter(osw); ????????String?line; ????????while?(?(line?=?br.readLine())!=null?){ ????????????bw.append(line); ????????????bw.newLine(); ????????????bw.flush(); ????????} ????????//?close ????}
關(guān)于流的操作非常多,像包括網(wǎng)絡(luò)通信中、音視頻文件處理、流合并等等
Guava中的IO
關(guān)于IO的內(nèi)容并不復(fù)雜,上面的那些例子在很多工具庫中基本都會提供對應(yīng)的API方便開發(fā)者調(diào)用,今天主要看下Guava IO模塊針對流的操作提供了什么樣的 封裝
Files
提供對文件快捷讀寫方法 其中主要提供了ByteSource、ByteSink、CharSource、CharSink 4個類,分別對應(yīng)按字節(jié)的讀寫與按字符的讀寫,
?/** ?????*?文件復(fù)制 ?????*/ ????@Test ????public?void?copy()?throws?IOException?{ ????????File?from?=?new?File(root,"from"); ????????File?to?=?new?File(root,"to"); ????????Files.copy(from,to); ????} ????/** ?????*?文件移動 ?????*/ ????@Test ????public?void?move()?throws?IOException?{ ????????File?from?=?new?File(root,"from"); ????????File?to?=?new?File(root,"to"); ????????Files.move(from,to); ????} ????/** ?????*?按行讀取文件 ?????*?@throws?IOException ?????*/ ????@Test ????public?void?readLines()?throws?IOException?{ ????????File?dest?=?new?File(root,"start.bat"); ????????List<String>?lines?=?Files.readLines(dest,?Charset.defaultCharset()); ????????lines.forEach(System.out::println); ????} ????/** ?????*?寫入文件 ?????*?@throws?IOException ?????*/ ????@Test ????public?void?writeToFile()?throws?IOException?{ ????????File?dest?=?new?File(root,"demo.txt"); ????????Files.write("hello?world!".getBytes(Charset.defaultCharset()),?dest); ????} ????/** ?????*?修改文件更新時間 ?????*?@throws?IOException ?????*/ ????@Test ????public?void?touch()?throws?IOException?{ ????????File?dest?=?new?File(root,"demo.txt"); ????????Files.touch(dest); ????} ????/** ?????*?文件的零拷貝 ?????*?@throws?IOException ?????*/ ????@Test ????public?void?map()?throws?IOException,?URISyntaxException?{ ????????File?from?=?new?File(root,"from"); ????????File?to?=?new?File(root,"to"); ????????Files.touch(to); ???????? ????????MappedByteBuffer?fromBuff?=?Files.map(from,?MapMode.READ_ONLY,?1024); ????????//?=> ????????FileChannel?channel?=?FileChannel.open(Paths.get(to.toURI()),?StandardOpenOption.WRITE); ????????channel.write(fromBuff); ????????channel.close(); ????} ????/** ?????*?讀文件為字節(jié)數(shù)組 ?????*?@throws?IOException ?????*/ ????@Test ????public?void?fileAndBytes()?throws?IOException?{ ????????File?dest?=?new?File(root,"start.bat"); ????????ByteSource?byteSource?=?Files.asByteSource(dest); ????????byte[]?bytes?=?byteSource.read(); ????????System.out.println(?bytes?); ????????//?字節(jié)寫入文件,實現(xiàn)復(fù)制 ????????File?target?=?new?File(root,?"start2.bat"); ????????ByteSink?byteSink?=?Files.asByteSink(target); ????????byteSink.write(bytes); ????} ????@Test ????public?void?wrapper(){ ????????File?dest?=?new?File(root,"start.bat"); ????????//?作為字節(jié)讀 ????????Files.asByteSource(dest); ????????//?作為字節(jié)寫 ????????Files.asByteSink(dest); ????????//?作為字符讀 ????????Files.asCharSource(dest,?Charset.defaultCharset()); ????????//?作為字符寫 ????????Files.asCharSink(dest,?Charset.defaultCharset()); ????}
其他
管道流
PipedOutputStream PipedInputStream 實現(xiàn)多線程間的數(shù)據(jù)通信;類似生產(chǎn)消費者模式
@Test ????public?void?pipe()?throws?IOException?{ ????????PipedOutputStream?pipedOutputStream?=?new?PipedOutputStream(); ????????PipedInputStream?pipedInputStream?=?new?PipedInputStream(); ????????pipedOutputStream.connect(pipedInputStream); ????????new?Thread(()->{ ????????????while?(true){ ????????????????String?date?=?new?Date().toString(); ????????????????try?{ ????????????????????pipedOutputStream.write(?date.getBytes(StandardCharsets.UTF_8)?); ????????????????????pipedOutputStream.flush(); ????????????????????TimeUnit.SECONDS.sleep(2); ????????????????}?catch?(IOException?e)?{ ????????????????????throw?new?RuntimeException(e); ????????????????}?catch?(InterruptedException?e)?{ ????????????????????throw?new?RuntimeException(e); ????????????????} ????????????} ????????}).start(); ???????? ????????new?Thread(()->{ ????????????while?(true){ ????????????????byte?[]?buff?=?new?byte[1024]; ????????????????try?{ ????????????????????int?read?=?pipedInputStream.read(buff); ????????????????????TimeUnit.SECONDS.sleep(4); ????????????????}?catch?(IOException?e)?{ ????????????????????throw?new?RuntimeException(e); ????????????????}?catch?(InterruptedException?e)?{ ????????????????????throw?new?RuntimeException(e); ????????????????} ????????????????System.out.println(?new?String(buff)?); ????????????} ????????}).start(); ????}
結(jié)束語
在任何編程語言中,數(shù)據(jù)的IO都是比較常見并相當(dāng)重要的。Guava作為工具型類庫,主要是幫助開發(fā)者封裝常用、重復(fù)的操作,開放出簡介的API,不僅能讓讓代碼更加整潔, 同時對開發(fā)出穩(wěn)健程序也是比不可少的。
到此這篇關(guān)于一文帶你了解Java中IO流與Guava的使用的文章就介紹到這了,更多相關(guān)Java IO流 Guava內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Mybatis的SqlRunner執(zhí)行流程實現(xiàn)
MyBatis提供了一個用于操作數(shù)據(jù)庫的SqlRunner工具類,對JDBC做了很好的封裝,本文主要介紹了Mybatis的SqlRunner執(zhí)行流程實現(xiàn),具有一定的參考價值,感興趣的可以了解一下2023-10-10劍指Offer之Java算法習(xí)題精講數(shù)組與二叉樹
跟著思路走,之后從簡單題入手,反復(fù)去看,做過之后可能會忘記,之后再做一次,記不住就反復(fù)做,反復(fù)尋求思路和規(guī)律,慢慢積累就會發(fā)現(xiàn)質(zhì)的變化2022-03-03Java實現(xiàn)的不同圖片居中剪裁生成同一尺寸縮略圖功能示例
這篇文章主要介紹了Java實現(xiàn)的不同圖片居中剪裁生成同一尺寸縮略圖功能,涉及java針對圖片的讀取、屬性修改等相關(guān)操作技巧,需要的朋友可以參考下2017-09-09Failed to execute goal org...的解決辦法
這篇文章主要介紹了Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.1的解決辦法的相關(guān)資料,需要的朋友可以參考下2017-06-06