一文帶你搞懂Java中的數(shù)據(jù)流處理
數(shù)據(jù)流轉
在前端的javascrit中,我們幾乎是沒有能力對計算機上的某個文件進行讀寫操作的,畢竟js只是一個網(wǎng)頁腳本。但是,nodejs是可以實現(xiàn)文件讀寫操作的。
在java中,對數(shù)據(jù)進行讀寫操作非常容易!下圖展示了Java中數(shù)據(jù)流轉的大致過程:
數(shù)據(jù)從數(shù)據(jù)源通過管道(stream)流轉之數(shù)據(jù)目的地,管道的入口我們稱之為input,出口稱之為out,因此,數(shù)據(jù)流轉操作也稱之為IO操作。java中就封裝了IO類幫助我們操作文件。
文件流操作
要操作一個文件,我們必須先創(chuàng)建文件對象,使用文件路徑關聯(lián)系統(tǒng)文件。
如圖,我們Data文件夾有一個名 為testData的txt文件
想要獲得文件路徑,我們可以按照下圖的操作方式獲取
關聯(lián)好文件路徑,我們就可以對文件進行一些操作了:
文件基礎操作
import java.io.File; public class Data_IO { public static void main(String[] args) { // 文件流操作 基于 java.io // 使用文件路徑關聯(lián)系統(tǒng)文件 String filePath = "D:\Code\JAVA\collection\src\Data\testData.txt"; // 創(chuàng)建文件對象 File file = new File(filePath); // 文件對象的操作 // 判斷當前文件對象是否文件(File對象也可能是文件夾) System.out.println(file.isFile()); // true // 判斷文件對象是否為文件夾 System.out.println(file.isDirectory()); // false // 判斷文件是否關聯(lián)成功 System.out.println(file.exists()); // true // 獲取文件名稱 System.out.println(file.getName()); // testData.txt // 獲取文件長度 System.out.println(file.lastModified()); // 1698977593862 // 獲取文件的絕對路徑 System.out.println(file.getAbsolutePath()); // D:\Code\JAVA\collection\src\Data\testData.txt } }
文件夾基礎操作
文件夾的一些基礎方法和文件是一致的。但有幾個方法是文件夾操作獨有的,如
獲取文件夾內(nèi)的數(shù)據(jù)列表
獲取文件夾中的文件對象
File[] files = file.listFiles(); for (File file1 : files) { System.out.println(file1 ); // testData.txt }
文件復制
在java中,實現(xiàn)文件復制是一個稍微復雜的過程?,F(xiàn)在,我們通過一個示例來演示下代碼。我們需要在Data文件夾下創(chuàng)建一個testData的副本文件testData_copy.txt
java中,對象復制的流程大致如下模型
首先,我們需要數(shù)據(jù)源對象和數(shù)據(jù)目的對象:
import java.io.*; public class IO_Copy { public static void main(String[] args) { // 數(shù)據(jù)源對象 File srcFile = new File("D:\Code\JAVA\collection\src\Data\testData.txt"); // 數(shù)據(jù)目的地對象 File destFile = new File("D:\Code\JAVA\collection\src\Data\testData_copy.txt"); } }
數(shù)據(jù)目的對象的路徑并不存在,是我們自己定義的要生成的文件路徑。
然后,我們要創(chuàng)建文件輸入管道1和文件輸出管道2:
import java.io.*; public class IO_Copy { public static void main(String[] args) { // 數(shù)據(jù)源對象 File srcFile = new File("D:\Code\JAVA\collection\src\Data\testData.txt"); // 數(shù)據(jù)目的地對象 File destFile = new File("D:\Code\JAVA\collection\src\Data\testData_copy.txt"); // 文件輸入流(管道對象) FileInputStream in = null; // 文件輸出流(管道對象) FileOutputStream out = null; } }
接下來,我們就要打開閥門1和閥門2進行數(shù)據(jù)流轉了
in = new FileInputStream(srcFile); out = new FileOutputStream(destFile); // 打開閥門,流轉數(shù)據(jù)(輸入端) int data = in.read(); // 打開閥門,流轉數(shù)據(jù)(輸出端) out.write(data);
數(shù)據(jù)流轉完畢,我們需要關閉管道
in.close(); out.close();
當然,數(shù)據(jù)操作過程中,存在很多異常情況,比如找不到數(shù)據(jù)源文件等等,所以實際代碼中,我們需要進行異常處理。比較完成的代碼如下:
import java.io.*; public class IO_Copy { public static void main(String[] args) { // 數(shù)據(jù)源對象 File srcFile = new File("D:\Code\JAVA\collection\src\Data\testData.txt"); // 數(shù)據(jù)目的地對象 File destFile = new File("D:\Code\JAVA\collection\src\Data\testData_copy.txt"); // 文件輸入流(管道對象) FileInputStream in = null; // 文件輸出流(管道對象) FileOutputStream out = null; try { in = new FileInputStream(srcFile); out = new FileOutputStream(destFile); // 打開閥門1,流轉數(shù)據(jù)(輸入端) int data = in.read(); // 打開閥門2,流轉數(shù)據(jù)(輸出端) out.write(data); } catch (IOException e) { throw new RuntimeException(e); } finally { if(in != null){ try { in.close(); } catch (IOException e) { throw new RuntimeException(e); } } if(out != null){ try { out.close(); } catch (IOException e) { throw new RuntimeException(e); } } } } }
我們來運行看看
可以看到,文件復制的確完成了,但是為什么復制出來的文件只有一個H字符???
這其實和java的文件復制原理有關,文件流復制時,是這個過程:
復制時,閥門1打開,H字符進入管道1:
當H字符進入管道2時,閥門1關閉,閥門2打開
當H字符進入數(shù)據(jù)目的地后,閥門2也隨之關閉,復制完成
在上述代碼中,我們的閥門1和閥門2只開啟過一次,自然只能復制一個H字符
in = new FileInputStream(srcFile); out = new FileOutputStream(destFile); // 打開閥門1,流轉數(shù)據(jù)(輸入端) int data = in.read(); // 打開閥門2,流轉數(shù)據(jù)(輸出端) out.write(data);
所以很簡單,我們只需要循環(huán)執(zhí)行上述代碼即可!那該執(zhí)行幾次呢?我們看下面代碼:
我們將閥門多開啟了一次,導致副本文件多了一個亂碼字符,通過打印結果可見,當data值為-1前,終止這個循環(huán)即可!改寫代碼:
import java.io.*; public class IO_Copy { public static void main(String[] args) { // 數(shù)據(jù)源對象 File srcFile = new File("D:\Code\JAVA\collection\src\Data\testData.txt"); // 數(shù)據(jù)目的地對象 File destFile = new File("D:\Code\JAVA\collection\src\Data\testData_copy.txt"); // 文件輸入流(管道對象) FileInputStream in = null; // 文件輸出流(管道對象) FileOutputStream out = null; try { in = new FileInputStream(srcFile); out = new FileOutputStream(destFile); // 打開閥門,流轉數(shù)據(jù)(輸入端) int data = in.read(); out.write(data); // 打開閥門,流轉數(shù)據(jù)(輸出端) while ((data = in.read()) != -1){ out.write(data); } } catch (IOException e) { throw new RuntimeException(e); } finally { if(in != null){ try { in.close(); } catch (IOException e) { throw new RuntimeException(e); } } if(out != null){ try { out.close(); } catch (IOException e) { throw new RuntimeException(e); } } } } }
緩沖流
上述的文件復制效率很低,每復制一個字符,都要開啟關閉閥門一次,因此,java也提供了緩沖區(qū)的優(yōu)化方式。
它的概念非常容易,就是在文件傳輸?shù)墓艿乐?,增加了一個緩沖管道
其復制流程大致如下:
閥門1打開,所有內(nèi)容進入管道1
閥門1關閉,所有內(nèi)容進入緩沖區(qū)
緩沖區(qū)內(nèi)容進入管道2,閥門2打開
管道2內(nèi)容進入數(shù)據(jù)目的地,復制完成,閥門2關閉。
完整代碼如下:
import java.io.*; public class IO_Copy { public static void main(String[] args) { // 數(shù)據(jù)源對象 File srcFile = new File("D:\Code\JAVA\collection\src\Data\testData.txt"); // 數(shù)據(jù)目的地對象 File destFile = new File("D:\Code\JAVA\collection\src\Data\testData_copy.txt"); // 文件輸入流(管道對象) FileInputStream in = null; // 文件輸出流(管道對象) FileOutputStream out = null; // 緩沖輸入流 BufferedInputStream bufferIn = null; BufferedOutputStream bufferOut = null; // 創(chuàng)建一個大小為1024字節(jié)的緩存區(qū)cache。這將用于存儲從源文件讀取的數(shù)據(jù),然后再寫入目標文件。 byte[] cache = new byte[1024]; try { in = new FileInputStream(srcFile); out = new FileOutputStream(destFile); // 緩沖輸入流 bufferIn = new BufferedInputStream(in); // 緩沖輸出流 bufferOut = new BufferedOutputStream(out); // 數(shù)據(jù)流轉 int data; // 當讀取到文件末尾(即data為-1)時,循環(huán)結束。 while ((data = bufferIn.read(cache)) != -1){ bufferOut.write(cache,0,data); } } catch (IOException e) { throw new RuntimeException(e); } finally { if(bufferIn != null){ try { bufferIn.close(); } catch (IOException e) { throw new RuntimeException(e); } } if(bufferOut != null){ try { bufferOut.close(); } catch (IOException e) { throw new RuntimeException(e); } } } } }
字符流操作
文件流的操作是基于文件的字節(jié)實現(xiàn)的。字符流的操作提供了另一種通過一行字符的形式操作數(shù)據(jù)。
再文件復制時,它會將一整行的字符一次性復制過去。
它的語法流程如下
首先,定義兩個File對象,srcFile和destFile。這兩個對象分別代表了源文件(我們要從中讀取數(shù)據(jù)的文件)和目標文件(我們要寫入數(shù)據(jù)的文件)。
// 數(shù)據(jù)源對象 File srcFile = new File("D:\Code\JAVA\collection\src\Data\testData.txt"); // 數(shù)據(jù)目的地對象 File destFile = new File("D:\Code\JAVA\collection\src\Data\testData_copy.txt");
然后,創(chuàng)建了兩個流對象,reader和writer。這兩個對象分別用于從源文件讀取數(shù)據(jù)和向目標文件寫入數(shù)據(jù)。
BufferedReader reader = null; PrintWriter writer = null;
接著,使用reader讀取源文件的內(nèi)容,而writer會向目標文件寫入內(nèi)容。
try { reader = new BufferedReader(new FileReader(srcFile)); writer = new PrintWriter(destFile); ... } catch (IOException e) { throw new RuntimeException(e); }
在try塊中,讀取源文件的內(nèi)容。每次讀取一行,直到文件結束(也就是沒有更多的行可以讀?。C孔x取一行,我們都會打印這一行(在控制臺輸出),并且寫入到目標文件。
while ((line = reader.readLine()) != null){ System.out.println(line); // 打印到控制臺 writer.println(line); // 寫入到目標文件 }
在讀取和寫入操作結束后,我們調用writer.flush()方法,確保所有待寫入的數(shù)據(jù)都被立即寫入到目標文件。
writer.flush();
完整代碼如下:
import java.io.*; public class IO_Copy { public static void main(String[] args) { // 數(shù)據(jù)源對象 File srcFile = new File("D:\Code\JAVA\collection\src\Data\testData.txt"); // 數(shù)據(jù)目的地對象 File destFile = new File("D:\Code\JAVA\collection\src\Data\testData_copy.txt"); // 字符輸入流(管道對象) BufferedReader reader = null; // 字符輸出流(管道對象) PrintWriter writer = null; try { reader = new BufferedReader(new FileReader(srcFile)); writer = new PrintWriter(destFile); // 讀取文件的一行數(shù)據(jù)(字符串) String line = null; while ((line = reader.readLine()) != null){ System.out.println(line); // Hello writer.println(line); } // 刷寫數(shù)據(jù) writer.flush(); } catch (IOException e) { throw new RuntimeException(e); } finally { if(reader != null){ try { reader.close(); } catch (IOException e) { throw new RuntimeException(e); } } } } }
以上就是一文帶你搞懂Java中的數(shù)據(jù)流處理的詳細內(nèi)容,更多關于Java數(shù)據(jù)流處理的資料請關注腳本之家其它相關文章!
相關文章
Hibernate validator使用以及自定義校驗器注解
這篇文章主要介紹了Hibernate validator使用以及自定義校驗器注解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-01-01SpringBoot中實現(xiàn)訂單30分鐘自動取消的三種方案分享
在電商和其他涉及到在線支付的應用中,通常需要實現(xiàn)一個功能:如果用戶在生成訂單后的一定時間內(nèi)未完成支付,系統(tǒng)將自動取消該訂單,本文將詳細介紹基于Spring Boot框架實現(xiàn)訂單30分鐘內(nèi)未支付自動取消的幾種方案,并提供實例代碼,需要的朋友可以參考下2023-10-10Springboot項目基于Devtools實現(xiàn)熱部署步驟詳解
這篇文章主要介紹了Springboot項目基于Devtools實現(xiàn)熱部署,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-06-06