鏈流
在使用流時,它們通常被鏈接在一起。
讓我們看看使用鏈接流的優(yōu)點是什么:
- 一個流實例利用另一個流實例。
- 這將創(chuàng)建更高級別的功能。我們可以有一個流訪問數(shù)據,然后有另一個流獲取數(shù)據的結果并處理更復雜的功能。
- 這簡化了可重用性,因為您可以以允許每個流執(zhí)行特定工作的方式來組織流。這樣,他們不需要知道彼此的內部運作方式。
我們使用構造函數(shù)執(zhí)行鏈接。我們構造該流的更高級別的實例,然后傳遞一個較低級別的流的實例。InputStreamReader 類是鏈式流的一個很好的例子。此類通過在上提供讀者行為來利用鏈接 InputStream。它將二進制響應轉換為字符行為。
讓我們看看它是如何工作的。
void doChain(InputStream in) throws IOException{
int length;
char[] buffer = new char[128];
try(InputStreamReader rdr = new InputStreamReader(in)) {
while((length = rdr.read(buffer)) >= 0) {
//do something
}
}
}我們不需要關心其 InputStream 工作原理。它是由文件支持還是由網絡支持都沒有關系。我們唯一知道的是它將給我們二進制數(shù)據,我們將其傳遞給我們InputStreamReader 并將其轉換為二進制數(shù)據并可以將其作為字符數(shù)據使用。
注意,我們try-with-resources 也在這里使用。如果我們關閉InputStreamReader,它InputStream 也會自動關閉。您應該知道這是一個非常強大的概念。
文件和緩沖流
我們經常使用流來訪問文件。
java.io包中有幾個要使用的類,例如:
- FileReader
- FileWriter
- FileInputStream
- FileOutputStream
真正的事實是這些文件流現(xiàn)在已被棄用。盡管如此,它們仍被廣泛用于代碼中,因此值得一提。
緩沖流
引入了緩沖流來替換java.io包中的 FileStream 類。這些新的Streams放在java.nio包下。這是必要的,因為直接文件訪問可能效率低下,并且緩沖的流可以通過以下方式顯著提高效率:
- 緩沖內存中的內容
- 大批量執(zhí)行讀/寫
- 減少底層流交互
緩沖可用于所有四種流類型:
- BufferReader
- BufferWriter
- BufferedInputStream
- BufferedOutputStream
使用它們非常簡單。
try(BufferedReader br = new BufferedReader(new FileReader("file.txt"))){
int value;
while((value = br.read()) >= 0) {
char charValue = (char)value;
//do something
}
}使用 BufferedStreams 好處:
- 它為各種平臺(如Windows或Unix)處理換行符
- 為當前平臺使用正確的值
- 這個BufferedWriter有一種方法:newLine() .它將創(chuàng)建一個具有適當字符的新行。
- 這個BufferedReader有一種基于行的讀取方法:readLine().
讓我們看看它們是如何工作的。
BufferedWriter:
void writeData(String[] data) throws IOException {
try(BufferedWriter bw = new BufferedWriter(new FileWriter("file.txt"))){
int value;
for(String str : data) {
bw.write(str);
bw.newLine();
}
}BufferedReader:
void readData(String[] data) throws IOException {
try(BufferedReader br = new BufferedReader(new FileReader("file.txt"))){
String inValue;
while((inValue = br.readLine()) != null) {
System.out.println(inValue);
}
}上面的代碼將逐行寫出文件的內容。
使用java.nio.file包訪問文件
在Java 8中,不贊成使用java.io.FileXXX流。 有一個用于處理文件流的新程序包,稱為java.nio.file程序包。
與java.io相比,該軟件包有幾個好處:
- 更好的異常報告
- 更大的可擴展性,它們在處理大文件時效果更好
- 更多文件系統(tǒng)功能支持
- 簡化常見任務
Path和Paths類型
Path:
- 用于查找文件系統(tǒng)項
- 它可以是文件或目錄
Paths:
- 用于通過靜態(tài)Path工廠方法獲取Path對象
- 它將基于字符串的分層路徑或URI轉換為Path。
示例:Path p = Paths.get(“\\documents\\foo.txt”)
文件類型
- 與文件交互的靜態(tài)方法
- 創(chuàng)建,復制,刪除等…
- 打開文件流
1、newBufferedReader
2、newBufferedWriter
3、newInputStream
4、newOutputStream - 讀取/寫入文件內容
1、readAllLines
2、write?Reading Lines With BufferedReader
void readData(String[] data) throws IOException {
try(BufferedReader br = Files.newBufferedReader(Paths.get("data.txt")){
String inValue;
while((inValue = br.readLine()) != null) {
System.out.println(inValue);
}
}
}Read All lines
void readAllLines(String[] data) throws IOException {
List<String> lines = Files.readAllLines(Paths.get("data.txt"));
for(String line:lines) {
System.out.println();
}
}文件系統(tǒng)
當我們使用Java程序中的文件時,這些文件包含在文件系統(tǒng)中。最常見的是,我們使用計算機的默認文件系統(tǒng)。
Java還支持專用文件系統(tǒng),例如Zip文件系統(tǒng)。
路徑實例綁定到文件系統(tǒng),Path 該類僅適用于默認實例。因此,我們需要另一個解決方案。幸運的是,在Java.nio包中,我們有機會對這一問題進行了處理。
文件系統(tǒng)類型
FileSystem
- 代表一個單獨的文件系統(tǒng)
- Path 實例工廠
FileSystems
- 用于FileSystem 通過靜態(tài)FileSystem 工廠方法獲取 對象
- 打開或創(chuàng)建文件系統(tǒng) newFileSystem
訪問文件系統(tǒng)
URI標識的文件系統(tǒng)
- URI的細節(jié)在文件系統(tǒng)之間差異很大
- zip文件系統(tǒng)使用“ jar:file ”方案jar:文件:/documents/data.zip
文件系統(tǒng)支持自定義屬性
- 每種文件系統(tǒng)類型不同
- 示例:字符串編碼,如果不存在則是否創(chuàng)建
創(chuàng)建一個Zip文件系統(tǒng)
public static void main(String[] args) throws FileNotFoundException, IOException {
try (FileSystem zipFileSystem = openZip(Paths.get("data.zip"))){ //pass the Path where we would like to create our FileSystem
}catch (Exception e) {
System.out.println(e.getClass().getSimpleName() + " - " + e.getLocalizedMessage());;
}
}
private static FileSystem openZip(Path path) throws URISyntaxException, IOException {
Map<String, String> properties = new HashMap<>();
properties.put("create", "true"); //set the property to allow creating
URI zipUri = new URI("jar:file", path.toUri().getPath(), null); //make a new URI from the path
FileSystem zipFileSystem = FileSystems.newFileSystem(zipUri, properties); //create the filesystem
return zipFileSystem;
}在上面的代碼之后,您應該在目錄中看到data.zip文件。

將文件復制到Zip文件系統(tǒng)
讓我們通過文件復制操作來擴展上述示例。
在此示例中,我在項目庫中創(chuàng)建了一個名為file.txt的文件。我們會將這個文件復制到我們的data.zip文件系統(tǒng)中。

try (FileSystem zipFileSystem = openZip(Paths.get("data.zip"))){
copyFileToZip(zipFileSystem); //Here we call the file copy
}catch (Exception e) {
System.out.println(e.getClass().getSimpleName() + " - " + e.getLocalizedMessage());;
}
}
private static FileSystem openZip(Path path) throws URISyntaxException, IOException {
Map<String, String> properties = new HashMap<>();
properties.put("create", "true");
URI zipUri = new URI("jar:file", path.toUri().getPath(), null);
FileSystem zipFileSystem = FileSystems.newFileSystem(zipUri, properties);
return zipFileSystem;
}
static void copyFileToZip(FileSystem zipFileSystem) throws IOException{
Path sourceFile = FileSystems.getDefault().getPath("file.txt"); //Read the file to copy
Path destFile = zipFileSystem.getPath("/fileCopied.txt"); //get the path of the new file
Files.copy(sourceFile, destFile);//Copy the file to our zip FileSystem
}運行代碼后,您應該在zip文件中看到fileCopied.txt。它的上下文應該與我們的file.txt中的相同。

概括
在本文中,研究了Java 8中的流。演示了流鏈接是如何工作的,以及如何通過新的java.nio包處理文件。還談到了為什么應該使用更多最新的緩沖版本的文件流。