一文帶你了解Java中IO流與Guava的使用
Guava IO
日常系統(tǒng)交互中,文件的上傳下載都是常見的,一般我們會通過jdk提供的IO操作庫幫助我們實(shí)現(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ā)者實(shí)現(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) 用于實(shí)現(xiàn)將數(shù)據(jù)讀入到程序
- 輸出流 (java.io.OutputStream) 用于實(shí)現(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)換流:實(shí)現(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ù)的輸入輸出,實(shí)現(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;?//?真實(shí)讀取到的字節(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é)寫入文件,實(shí)現(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 實(shí)現(xiàn)多線程間的數(shù)據(jù)通信;類似生產(chǎn)消費(fèi)者模式
@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)文章
使用Java生成JWT(JSON Web Token)的方法示例
在現(xiàn)代應(yīng)用程序中,身份驗(yàn)證和授權(quán)是至關(guān)重要的,JWT是一種簡單而強(qiáng)大的身份驗(yàn)證和授權(quán)機(jī)制,可以在Web應(yīng)用程序中安全地傳輸用戶信息,本文主要介紹了使用Java生成JWT的方法示例,感興趣的可以了解一下2024-03-03
詳解Java如何判斷ResultSet結(jié)果集是否為空
ResultSet 表示 select 語句的查詢結(jié)果集。這篇文章主要為大家詳細(xì)介紹了Java如何判斷ResultSet結(jié)果集是否為空,感興趣的可以了解一下2023-02-02
Java源碼解析阻塞隊(duì)列ArrayBlockingQueue介紹
今天小編就為大家分享一篇關(guān)于Java源碼解析阻塞隊(duì)列ArrayBlockingQueue介紹,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2019-01-01
SpringBoot?實(shí)現(xiàn)動態(tài)添加定時任務(wù)功能
這篇文章主要介紹了SpringBoot?動態(tài)添加定時任務(wù),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-02-02
SpringCloud-Hystrix實(shí)現(xiàn)原理總結(jié)
通過hystrix可以解決雪崩效應(yīng)問題,它提供了資源隔離、降級機(jī)制、融斷、緩存等功能。接下來通過本文給大家分享SpringCloud-Hystrix實(shí)現(xiàn)原理,感興趣的朋友一起看看吧2021-05-05

