Guava IO
日常系統交互中,文件的上傳下載都是常見的,一般我們會通過jdk提供的IO操作庫幫助我們實現。IO指的是數據相對當前操作程序的入與出,將數據通過 輸出流從程序輸出,或者通過輸入流將數據(從文件、網絡、數據等)寫入到程序,這里的IO指的是基于流作為載體進行數據傳輸。如果把數據比作合理的水,河就是IO流,也是數據的載體。
Java為我們提供了非常多的操作IO的接口與類,幫助開發者實現不同源間的數據傳輸,比如硬盤文件、網絡傳輸、應用調用間的數據交互與傳遞。今天我們來簡單了解下Java中的流 以及在Guava工具包中,針對IO操作做了什么樣的封裝與設計。
分類
在java.io包中有非常多的IO相關接口,我們可以根據流的輸出類型、處理對象以及功能將其分為以下幾種類型:
- 按數據流向
- 輸入流 (java.io.InputStream)
用于實現將數據讀入到程序 - 輸出流 (java.io.OutputStream)
用于實現將數據從程序寫出
- 輸入流 (java.io.InputStream)
- 按操作單位
區分:
字節流一般以Stream結尾 字符流一般以Reader或Writer結尾
- 按操作方式
- 讀 (java.io.Reader)
主要針對字符流的讀取操作 - 寫 (java.io.Writer)
主要針對字符流的寫出操作
- 讀 (java.io.Reader)
- 按功能
- 緩存流
按字節進行數據讀寫時,通過緩沖批量寫入來提高傳輸效率 - 轉換流
實現輸入/出與讀/寫方式間的轉換
- 緩存流
常用的流
- 操作文件的
java.io.FileinputStream/FileOutputStream java.io.FileReader/FileWriter - 通用的字節流
java.io.InputStreamReader/outputStreamWriter - 緩沖流
java.io.BufferedReader/BufferedWriter java.io.BufferedInputStream/BufferedOutputStream - 數據流
java.io.DataInpoutStream/DataOutputStream - 功能型的
java.io.PrintWriter/PrintStream - 對象序列化相關的
java.io.ObjectInputStream/ObjectOutputStream
可見,提供的IO對象基本都是成對出現的,用以完成數據的輸入輸出,實現程序與外部載體間的數據交換
示例
下面我們通過一些常用示例來看看IO的使用的場景與使用方法:
- 文件復制
- 文件的合并
- 讀取文件內容為字符串
- 字節數組轉換成流
- 對象序列化與反序列化
- 流的轉換
- ......
- 文件復制
@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:_projectssuclsblogmy_studyguavaguava-iosrctestjavacomsuclsblogguavaiocategoryFileTests.java");
File file2 = new File("E:_projectssuclsblogmy_studyguavaguava-iosrctestjavacomsuclsblogguavaiocategoryStreamTests.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; // 真實讀取到的字節數
while ( (read = sequenceInputStream.read(buff)) !=-1){
fos.write(buff, 0, read);
}
fos.close();
}
- 讀取文件內容為字符串
@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 ); // 文件內容
}
- 字節數組轉換成流
@Test
public void bytesToStream(){
byte [] data = new byte[1024]; // 來源于其他數據源
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 );
}
- 流的轉換 將字節流轉換成字符流來操作,同樣以文件復制為例
@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
}
關于流的操作非常多,像包括網絡通信中、音視頻文件處理、流合并等等
Guava中的IO
關于IO的內容并不復雜,上面的那些例子在很多工具庫中基本都會提供對應的API方便開發者調用,今天主要看下Guava IO模塊針對流的操作提供了什么樣的 封裝
Files
提供對文件快捷讀寫方法 其中主要提供了ByteSource、ByteSink、CharSource、CharSink 4個類,分別對應按字節的讀寫與按字符的讀寫,
/**
* 文件復制
*/
@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();
}
/**
* 讀文件為字節數組
* @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 );
// 字節寫入文件,實現復制
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");
// 作為字節讀
Files.asByteSource(dest);
// 作為字節寫
Files.asByteSink(dest);
// 作為字符讀
Files.asCharSource(dest, Charset.defaultCharset());
// 作為字符寫
Files.asCharSink(dest, Charset.defaultCharset());
}
其他
管道流
PipedOutputStream PipedInputStream 實現多線程間的數據通信;類似生產消費者模式
@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();
}
結束語
在任何編程語言中,數據的IO都是比較常見并相當重要的。Guava作為工具型類庫,主要是幫助開發者封裝常用、重復的操作,開放出簡介的API,不僅能讓讓代碼更加整潔, 同時對開發出穩健程序也是比不可少的。
-
IO
+關注
關注
0文章
473瀏覽量
39654 -
數據傳輸
+關注
關注
9文章
1974瀏覽量
65028 -
硬盤
+關注
關注
3文章
1328瀏覽量
57684 -
JAVA
+關注
關注
19文章
2980瀏覽量
105673 -
工具包
+關注
關注
0文章
47瀏覽量
9599
發布評論請先 登錄
相關推薦
Java中的輸入輸出流盤點
Java 那些最常用的工具類庫
java流與文件實驗
java中的io流分析

關于java中的io流知識總結詳解
理解Java中字符流與字節流的區別

評論