您好,登錄后才能下訂單哦!
這篇文章主要介紹“Java File類的理解與使用”,在日常操作中,相信很多人在Java File類的理解與使用問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Java File類的理解與使用”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
File類的一個對象,代表一個文件或一個文件目錄(俗稱:文件夾)。
File類聲明在java.io包下:文件和文件路徑的抽象表示形式,與平臺無關。
File類中涉及到關于文件或文件目錄的創建、刪除、重命名、修改時間、文件大小等方法,并未涉及到寫入或讀取文件內容的操作。如果需要讀取或寫入文件內容,必須使用IO流來完成。
想要在Java程序中表示一個真實存在的文件或目錄,那么必須有一個File對象,但是Java程序中的一個File對象,可能沒有一個真實存在的文件或目錄。
后續File類的對象常會作為參數傳遞到流的構造器中,指明讀取或寫入的"終點"。
File(String filePath)
File(String parentPath,String childPath)
File(File parentFile,String childPath)
代碼示例:
@Test public void test1() { //構造器1 File file1 = new File("hello.txt"); File file2 = new File("E:\\workspace_idea\\JavaSenic\\IO\\hello.txt"); System.out.println(file1); System.out.println(file2); //構造器2 File file3 = new File("E:\\workspace_idea\\JavaSenior", "hello.txt"); System.out.println(file3); //構造器3 File file4 = new File(file3, "hi.txt"); System.out.println(file4); }
相對路徑:相較于某個路徑下,指明的路徑。
絕對路徑:包含盤符在內的文件或文件目錄的路徑。
說明:
IDEA中:
如果使用JUnit中的單元測試方法測試,相對路徑即為當前Module下。
如果使用main()測試,相對路徑即為當前的Project下。
Eclipse中:
不管使用單元測試方法還是使用main()測試,相對路徑都是當前的Project下。
windows和DOS系統默認使用“\”來表示
UNIX和URL使用“/”來表示
Java程序支持跨平臺運行,因此路徑分隔符要慎用。
為了解決這個隱患,File類提供了一個常量: public static final String separator。根據操作系統,動態的提供分隔符。
舉例:
//windows和DOS系統 File file1 = new File("E:\\io\\test.txt"); //UNIX和URL File file = new File("E:/io/test.txt"); //java提供的常量 File file = new File("E:"+File.separator+"io"+File.separator+"test.txt");
public String getAbsolutePath():獲取絕對路徑
public String getPath() :獲取路徑
public String getName() :獲取名稱
public String getParent():獲取上層文件目錄路徑。若無,返回null
public long length() :獲取文件長度(即:字節數)。不能獲取目錄的長度。
public long lastModified() :獲取最后一次的修改時間,毫秒值
如下的兩個方法適用于文件目錄:
public String[] list() :獲取指定目錄下的所有文件或者文件目錄的名稱數組
public File[] listFiles() :獲取指定目錄下的所有文件或者文件目錄的File數組
代碼示例:
@Test public void test2(){ File file1 = new File("hello.txt"); File file2 = new File("d:\\io\\hi.txt"); System.out.println(file1.getAbsolutePath()); System.out.println(file1.getPath()); System.out.println(file1.getName()); System.out.println(file1.getParent()); System.out.println(file1.length()); System.out.println(new Date(file1.lastModified())); System.out.println(); System.out.println(file2.getAbsolutePath()); System.out.println(file2.getPath()); System.out.println(file2.getName()); System.out.println(file2.getParent()); System.out.println(file2.length()); System.out.println(file2.lastModified()); } @Test public void test3(){ File file = new File("D:\\workspace_idea1\\JavaSenior"); String[] list = file.list(); for(String s : list){ System.out.println(s); } System.out.println(); File[] files = file.listFiles(); for(File f : files){ System.out.println(f); } }
public boolean renameTo(File dest):把文件重命名為指定的文件路徑
注意:file1.renameTo(file2)為例:要想保證返回true,需要file1在硬盤中是存在的,且file2不能在硬盤中存在。
代碼示例:
@Test public void test4(){ File file1 = new File("hello.txt"); File file2 = new File("D:\\io\\hi.txt"); boolean renameTo = file2.renameTo(file1); System.out.println(renameTo); }
public boolean isDirectory():判斷是否是文件目錄
public boolean isFile() :判斷是否是文件
public boolean exists() :判斷是否存在
public boolean canRead() :判斷是否可讀
public boolean canWrite() :判斷是否可寫
public boolean isHidden() :判斷是否隱藏
代碼示例:
@Test public void test5(){ File file1 = new File("hello.txt"); file1 = new File("hello1.txt"); System.out.println(file1.isDirectory()); System.out.println(file1.isFile()); System.out.println(file1.exists()); System.out.println(file1.canRead()); System.out.println(file1.canWrite()); System.out.println(file1.isHidden()); System.out.println(); File file2 = new File("d:\\io"); file2 = new File("d:\\io1"); System.out.println(file2.isDirectory()); System.out.println(file2.isFile()); System.out.println(file2.exists()); System.out.println(file2.canRead()); System.out.println(file2.canWrite()); System.out.println(file2.isHidden()); }
創建硬盤中對應的文件或文件目錄
public boolean createNewFile() :創建文件。若文件存在,則不創建,返回false
public boolean mkdir() :創建文件目錄。如果此文件目錄存在,就不創建了。如果此文件目錄的上層目錄不存在,也不創建。
public boolean mkdirs() :創建文件目錄。如果此文件目錄存在,就不創建了。如果上層文件目錄不存在,一并創建
代碼示例:
@Test public void test6() throws IOException { File file1 = new File("hi.txt"); if(!file1.exists()){ //文件的創建 file1.createNewFile(); System.out.println("創建成功"); }else{//文件存在 file1.delete(); System.out.println("刪除成功"); } } @Test public void test7(){ //文件目錄的創建 File file1 = new File("d:\\io\\io1\\io3"); boolean mkdir = file1.mkdir(); if(mkdir){ System.out.println("創建成功1"); } File file2 = new File("d:\\io\\io1\\io4"); boolean mkdir1 = file2.mkdirs(); if(mkdir1){ System.out.println("創建成功2"); } //要想刪除成功,io4文件目錄下不能有子目錄或文件 File file3 = new File("D:\\io\\io1\\io4"); file3 = new File("D:\\io\\io1"); System.out.println(file3.delete()); }
刪除磁盤中的文件或文件目錄
public boolean delete():刪除文件或者文件夾
刪除注意事項:Java中的刪除不走回收站。
利用Fie構造器,new一個文件目錄file 1)在其中創建多個文件和目錄 2)編寫方法,實現刪除fle中指定文件的操作
@Test public void test1() throws IOException { File file = new File("E:\\io\\io1\\hello.txt"); //創建一個與file同目錄下的另外一個文件,文件名為:haha.txt File destFile = new File(file.getParent(),"haha.txt"); boolean newFile = destFile.createNewFile(); if(newFile){ System.out.println("創建成功!"); } }
判斷指定目錄下是否有后綴名為jpg的文件,如果有,就輸出該文件名稱
public class FindJPGFileTest { @Test public void test1(){ File srcFile = new File("d:\\code"); String[] fileNames = srcFile.list(); for(String fileName : fileNames){ if(fileName.endsWith(".jpg")){ System.out.println(fileName); } } } @Test public void test2(){ File srcFile = new File("d:\\code"); File[] listFiles = srcFile.listFiles(); for(File file : listFiles){ if(file.getName().endsWith(".jpg")){ System.out.println(file.getAbsolutePath()); } } } /* * File類提供了兩個文件過濾器方法 * public String[] list(FilenameFilter filter) * public File[] listFiles(FileFilter filter) */ @Test public void test3(){ File srcFile = new File("d:\\code"); File[] subFiles = srcFile.listFiles(new FilenameFilter() { @Override public boolean accept(File dir, String name) { return name.endsWith(".jpg"); } }); for(File file : subFiles){ System.out.println(file.getAbsolutePath()); } } }
遍歷指定目錄所有文件名稱,包括子文件目錄中的文件。 拓展1:并計算指定目錄占用空間的大小 拓展2:刪除指定文件目錄及其下的所有文件
public class ListFileTest { public static void main(String[] args) { // 遞歸:文件目錄 /** 打印出指定目錄所有文件名稱,包括子文件目錄中的文件 */ //1.創建目錄對象 File file = new File("E:\\test"); //2.打印子目錄 printSubFile(file); } /** * 遞歸方法遍歷所有目錄下的文件 * * @param dir */ public static void printSubFile(File dir) { //打印子目錄 File[] files = dir.listFiles(); for (File f : files) { if (f.isDirectory()) {//如果為文件目錄,則遞歸調用自身 printSubFile(f); } else { System.out.println(f.getAbsolutePath());//輸出絕對路徑 } } } // 拓展1:求指定目錄所在空間的大小 // 求任意一個目錄的總大小 public long getDirectorySize(File file) { // file是文件,那么直接返回file.length() // file是目錄,把它的下一級的所有大小加起來就是它的總大小 long size = 0; if (file.isFile()) { size += file.length(); } else { File[] allFiles = file.listFiles();// 獲取file的下一級 // 累加all[i]的大小 for (File f : allFiles) { size += getDirectorySize(f);//f的大小 } } return size; } /** * 拓展2:刪除指定的目錄 */ public void deleteDirectory(File file) { // 如果file是文件,直接delete // 如果file是目錄,先把它的下一級干掉,然后刪除自己 if (file.isDirectory()) { File[] allFiles = file.listFiles(); //遞歸調用刪除file下一級 for (File f : allFiles) { deleteDirectory(f); } } else { //刪除文件 file.delete(); } } }
IO是Input/Output的縮寫,I/O技術是非常實用的技術,用于處理設備之間的數據傳輸。如讀/寫文件,網絡通訊等。
Java程序中,對于數據的輸入輸出操作以“流(stream)”的方式進行。
Java.IO包下提供了各種“流”類和接口,用以獲取不同種類的數據,并通過標準的方法輸入或輸出數據。
操作數據單位:字節流、字符流
對于文本文件(.txt,.java,.c,.cpp),使用字符流處理
對于非文本文件(.jpg,.mp3,.mp4,.avi,.doc,.ppt,...),使用字節流處理
數據的流向:輸入流、輸出流
輸入input:讀取外部數據(磁盤、光盤等存儲設備的數據)到程序(內存)中。
輸出output:將程序(內存)數據輸出到磁盤、光盤等存儲設備中。
流的角色:節點流、處理流
節點流:直接從數據源或目的地讀寫數據。
處理流:不直接連接到數據源或目的地,而是“連接”在已存在的流(節點流或處理流)之上,通過對數據的處理為程序提供更為強大的讀寫功能。
圖示:
紅框為抽象基類,藍框為常用IO流
抽象基類 | 節點流(或文件流) | 緩沖流(處理流的一種) |
---|---|---|
InputStream | FileInputStream (read(byte[] buffer)) | BufferedInputStream (read(byte[] buffer)) |
OutputSteam | FileOutputStream (write(byte[] buffer,0,len) | BufferedOutputStream (write(byte[] buffer,0,len) / flush() |
Reader | FileReader (read(char[] cbuf)) | BufferedReader (read(char[] cbuf) / readLine()) |
Writer | FileWriter (write(char[] cbuf,0,len) | BufferedWriter (write(char[] cbuf,0,len) / flush() |
抽象基類 | 字節流 | 字符流 |
---|---|---|
輸入流 | InputSteam | Reader |
輸出流 | OutputSteam | Writer |
說明:Java的lO流共涉及40多個類,實際上非常規則,都是從如下4個抽象基類派生的。
由這四個類派生出來的子類名稱都是以其父類名作為子類名后綴。
3.3.1InputSteam & Reader
InputStream和Reader是所有輸入流的基類。
InputStream(典型實現:FileInputStream)
int read()
int read(byte[] b)
int read(byte[] b,int off,int len)
Reader(典型實現:FileReader)
int read()
int read(char[] c)
int read(char[] c,int off,int len)
程序中打開的文件IO資源不屬于內存里的資源,垃圾回收機制無法回收該資源,所以應該顯式關閉文件IO資源。
FileInputStream從文件系統中的某個文件中獲得輸入字節。FileInputStream用于讀取非文本數據之類的原始字節流。要讀取字符流,需要使用 FileReader。
InputSteam:
int read()
從輸入流中讀取數據的下一個字節。返回0到255范圍內的int字節值。如果因為已經到達流末尾而沒有可用的字節,則返回值-1。
int read(byte[] b)
從此輸入流中將最多b.length個字節的數據讀入一個byte數組中。如果因為已經到達流末尾而沒有可用的字節,則返回值-1.否則以整數形式返回實際讀取的字節數。
int read(byte[] b,int off,int len)
將輸入流中最多len個數據字節讀入byte數組。嘗試讀取len個字節,但讀取的字節也可能小于該值。以整數形式返回實際讀取的字節數。如果因為流位于文件末尾而沒有可用的字節,則返回值-1。
public void close throws IOException
關閉此輸入流并釋放與該流關聯的所有系統資源。
Reader:
int read()
讀取單個字符。作為整數讀取的字符,范圍在0到65535之間(0x00-0xffff)(2個字節的 Unicode碼),如果已到達流的末尾,則返回-1。
int read(char[] cbuf)
將字符讀入數組。如果已到達流的末尾,則返回-1。否則返回本次讀取的字符數。
int read(char[] cbuf,int off,int len)
將字符讀入數組的某一部分。存到數組cbuf中,從off處開始存儲,最多讀len個字符。如果已到達流的末尾,則返回-1。否則返回本次讀取的字符數。
public void close throws IOException
關閉此輸入流并釋放與該流關聯的所有系統資源
3.3.2 OutputSteam & Writer
OutputStream和Writer也非常相似:
void write(int b/int c);
void write(byte[] b/char[] cbuf);
void write(byte[] b/char[] buff,int off,int len);
void flush();
void close();需要先刷新,再關閉此流
因為字符流直接以字符作為操作單位,所以 Writer可以用字符串來替換字符數組,即以 String對象作為參數
void write(String str);
void write(String str,int off,int len);
FileOutputStream從文件系統中的某個文件中獲得輸出字節。FileOutputstream用于寫出非文本數據之類的原始字節流。要寫出字符流,需要使用 FileWriter
OutputStream:
void write(int b)
將指定的字節寫入此輸出流。 write的常規協定是:向輸出流寫入一個字節。要寫入的字節是參數b的八個低位。b的24個高位將被忽略。即寫入0~255范圍的
void write(byte[] b)
將b.length個字節從指定的byte數組寫入此輸出流。write(b)的常規協定是:應該與調用wite(b,0,b.length)的效果完全相同。
void write(byte[] b,int off,int len)
將指定byte數組中從偏移量off開始的len個字節寫入此輸出流。
public void flush()throws IOException
刷新此輸出流并強制寫出所有緩沖的輸出字節,調用此方法指示應將這些字節立即寫入它們預期的目標。
public void close throws IOException
關閉此輸岀流并釋放與該流關聯的所有系統資源。
Writer:
void write(int c)
寫入單個字符。要寫入的字符包含在給定整數值的16個低位中,16高位被忽略。即寫入0到65535之間的 Unicode碼。
void write(char[] cbuf)
寫入字符數組
void write(char[] cbuf,int off,int len)
寫入字符數組的某一部分。從off開始,寫入len個字符
void write(String str)
寫入字符串。
void write(String str,int off,int len)
寫入字符串的某一部分。
void flush()
刷新該流的緩沖,則立即將它們寫入預期目標。
public void close throws IOException
關閉此輸出流并釋放與該流關聯的所有系統資源
① 創建File類的對象,指明讀取的數據的來源。(要求此文件一定要存在)
② 創建相應的輸入流,將File類的對象作為參數,傳入流的構造器中
③ 具體的讀入過程:創建相應的byte[] 或 char[]。
④ 關閉流資源
說明:程序中出現的異常需要使用try-catch-finally處理。
① 創建File類的對象,指明寫出的數據的位置。(不要求此文件一定要存在)
② 創建相應的輸出流,將File類的對象作為參數,傳入流的構造器中
③ 具體的寫出過程:write(char[]/byte[] buffer,0,len)
④ 關閉流資源
說明:程序中出現的異常需要使用try-catch-finally處理。
從文件中讀取到內存(程序)中
步驟:
建立一個流對象,將已存在的一個文件加載進流 FileReader fr = new FileReader(new File("Test. txt"));
創建一個臨時存放數據的數組 char[] ch = new char[1024];
調用流對象的讀取方法將流中的數據讀入到數組中。 fr.read(ch);
關閉資源。 fr.close();
代碼示例:
@Test public void testFileReader1() { FileReader fr = null; try { //1.File類的實例化 File file = new File("hello.txt"); //2.FileReader流的實例化 fr = new FileReader(file); //3.讀入的操作 //read(char[] cbuf):返回每次讀入cbuf數組中的字符的個數。如果達到文件末尾,返回-1 char[] cbuf = new char[5]; int len; while((len = fr.read(cbuf)) != -1){ String str = new String(cbuf,0,len); System.out.print(str); } } catch (IOException e) { e.printStackTrace(); } finally { if(fr != null){ //4.資源的關閉 try { fr.close(); } catch (IOException e) { e.printStackTrace(); } } } }
注意點:
read()的理解:返回讀入的一個字符。如果達到文件末尾,返回-1
異常的處理:為了保證流資源一定可以執行關閉操作。需要使用try-catch-finally處理
讀入的文件一定要存在,否則就會報FileNotFoundException。
從內存(程序)到硬盤文件中
步驟:
創建流對象,建立數據存放文件 File Writer fw = new File Writer(new File("Test.txt"))
調用流對象的寫入方法,將數據寫入流 fw.write("HelloWord")
關閉流資源,并將流中的數據清空到文件中。 fw.close();
代碼示例:
@Test public void testFileWriter() { FileWriter fw = null; try { //1.提供File類的對象,指明寫出到的文件 File file = new File("hello1.txt"); //2.提供FileWriter的對象,用于數據的寫出 fw = new FileWriter(file,false); //3.寫出的操作 fw.write("I have a dream!\n"); fw.write("you need to have a dream!"); } catch (IOException e) { e.printStackTrace(); } finally { //4.流資源的關閉 if(fw != null){ try { fw.close(); } catch (IOException e) { e.printStackTrace(); } } } }
實現文本文件的復制操作
@Test public void testFileReaderFileWriter() { FileReader fr = null; FileWriter fw = null; try { //1.創建File類的對象,指明讀入和寫出的文件 File srcFile = new File("hello.txt"); File destFile = new File("hello2.txt"); //不能使用字符流來處理圖片等字節數據 // File srcFile = new File("test.jpg"); // File destFile = new File("test1.jpg"); //2.創建輸入流和輸出流的對象 fr = new FileReader(srcFile); fw = new FileWriter(destFile); //3.數據的讀入和寫出操作 char[] cbuf = new char[5]; int len;//記錄每次讀入到cbuf數組中的字符的個數 while((len = fr.read(cbuf)) != -1){ //每次寫出len個字符 fw.write(cbuf,0,len); } } catch (IOException e) { e.printStackTrace(); } finally { //4.關閉流資源 try { if(fw != null) fw.close(); } catch (IOException e) { e.printStackTrace(); } try { if(fr != null) fr.close(); } catch (IOException e) { e.printStackTrace(); } } }
文件字節流操作與字符流操作類似,只是實例化對象操作和數據類型不同。
代碼示例:
//使用字節流FileInputStream處理文本文件,可能出現亂碼。 @Test public void testFileInputStream() { FileInputStream fis = null; try { //1. 造文件 File file = new File("hello.txt"); //2.造流 fis = new FileInputStream(file); //3.讀數據 byte[] buffer = new byte[5]; int len;//記錄每次讀取的字節的個數 while((len = fis.read(buffer)) != -1){ String str = new String(buffer,0,len); System.out.print(str); } } catch (IOException e) { e.printStackTrace(); } finally { if(fis != null){ //4.關閉資源 try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } } }
小練習
實現圖片文件復制操作
@Test public void testFileInputOutputStream() { FileInputStream fis = null; FileOutputStream fos = null; try { //1.創建File對象 File srcFile = new File("test.jpg"); File destFile = new File("test2.jpg"); //2.創建操流 fis = new FileInputStream(srcFile); fos = new FileOutputStream(destFile); //3.復制的過程 byte[] buffer = new byte[5]; int len; while((len = fis.read(buffer)) != -1){ fos.write(buffer,0,len); } } catch (IOException e) { e.printStackTrace(); } finally { //4.關閉流 if(fos != null){ // try { fos.close(); } catch (IOException e) { e.printStackTrace(); } } if(fis != null){ try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } } }
定義路徑時,可以用“/”或“\\”。
輸出操作,對應的File可以不存在的。并不會報異常。
File對應的硬盤中的文件如果不存在,在輸出的過程中,會自動創建此文件。
File對應的硬盤中的文件如果存在:
如果流使用的構造器是:FileWriter(file,false) / FileWriter(file):對原有文件的覆蓋。
如果流使用的構造器是:FileWriter(file,true):不會對原有文件覆蓋,而是在原有文件基礎上追加內容。
讀取文件時,必須保證文件存在,否則會報異常。
對于文本文件(.txt,.java,.c,.cpp),使用字符流處理
對于非文本文件(.jpg,.mp3,.mp4,.avi,.doc,.ppt,...),使用字節流處理
BufferedInputStream
BufferedOutputStream
BufferedReader
BufferedWriter
作用:提供流的讀取、寫入的速度
提高讀寫速度的原因:內部提供了一個緩沖區。默認情況下是8kb
處理流與節點流的對比圖示
當讀取數據時,數據按塊讀入緩沖區,其后的讀操作則直接訪問緩沖區。
當使用 BufferedInputStream讀取字節文件時,BufferedInputStream會一次性從文件中讀取8192個(8Kb),存在緩沖區中,直到緩沖區裝滿了,才重新從文件中讀取下一個8192個字節數組。
向流中寫入字節時,不會直接寫到文件,先寫到緩沖區中直到緩沖區寫滿,BufferedOutputStream才會把緩沖區中的數據一次性寫到文件里。使用方法flush()可以強制將緩沖區的內容全部寫入輸出流。
關閉流的順序和打開流的順序相反。只要關閉最外層流即可,關閉最外層流也會相應關閉內層節點流。
flush()方法的使用:手動將buffer中內容寫入文件。
如果是帶緩沖區的流對象的close()方法,不但會關閉流,還會在關閉流之前刷新緩沖區,關閉后不能再寫出。
代碼示例:
@Test public void testBufferedStream(){ BufferedInputStream bis = null; BufferedOutputStream bos = null; try { //1.造文件 File srcFile = new File("test.jpg"); File destFile = new File("test4.jpg"); //2.造流 //2.1造節點流 FileInputStream fis = new FileInputStream(srcFile); FileOutputStream fos = new FileOutputStream(destFile); //2.2造緩沖流,可以合并書寫 bis = new BufferedInputStream(fis); bos = new BufferedOutputStream(fos); //3.文件讀取、寫出操作 byte[] buffer = new byte[1024]; int len; while ((len = bis.read(buffer)) != -1){ bos.write(buffer,0,len); } } catch (IOException e) { e.printStackTrace(); } finally { //4.關閉流 if (bos != null){ try { bos.close(); } catch (IOException e) { e.printStackTrace(); } } if (bis != null){ try { bis.close(); } catch (IOException e) { e.printStackTrace(); } } } }
@Test public void testBufferedReaderBufferedWriter(){ BufferedReader br = null; BufferedWriter bw = null; try { //創建文件和相應的流 br = new BufferedReader(new FileReader(new File("dbcp.txt"))); bw = new BufferedWriter(new FileWriter(new File("dbcp1.txt"))); //讀寫操作 //方式一:使用char[]數組 // char[] cbuf = new char[1024]; // int len; // while((len = br.read(cbuf)) != -1){ // bw.write(cbuf,0,len); // // bw.flush(); // } //方式二:使用String String data; while((data = br.readLine()) != null){ //方法一: // bw.write(data + "\n");//data中不包含換行符 //方法二: bw.write(data);//data中不包含換行符 bw.newLine();//提供換行的操作 } } catch (IOException e) { e.printStackTrace(); } finally { //關閉資源 if(bw != null){ try { bw.close(); } catch (IOException e) { e.printStackTrace(); } } if(br != null){ try { br.close(); } catch (IOException e) { e.printStackTrace(); } } } }
節點流實現復制方法
//指定路徑下文件的復制 public void copyFile(String srcPath,String destPath){ FileInputStream fis = null; FileOutputStream fos = null; try { //1.造文件 File srcFile = new File(srcPath); File destFile = new File(destPath); //2.造流 fis = new FileInputStream(srcFile); fos = new FileOutputStream(destFile); //3.復制的過程 byte[] buffer = new byte[1024]; int len; while((len = fis.read(buffer)) != -1){ fos.write(buffer,0,len); } } catch (IOException e) { e.printStackTrace(); } finally { if(fos != null){ //4.關閉流 try { fos.close(); } catch (IOException e) { e.printStackTrace(); } } if(fis != null){ try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } } }
緩沖流實現復制操作
//實現文件復制的方法 public void copyFileWithBuffered(String srcPath,String destPath){ BufferedInputStream bis = null; BufferedOutputStream bos = null; try { //1.造文件 File srcFile = new File(srcPath); File destFile = new File(destPath); //2.造流 //2.1 造節點流 FileInputStream fis = new FileInputStream((srcFile)); FileOutputStream fos = new FileOutputStream(destFile); //2.2 造緩沖流 bis = new BufferedInputStream(fis); bos = new BufferedOutputStream(fos); //3.復制的細節:讀取、寫入 byte[] buffer = new byte[1024]; int len; while((len = bis.read(buffer)) != -1){ bos.write(buffer,0,len); } } catch (IOException e) { e.printStackTrace(); } finally { //4.資源關閉 //要求:先關閉外層的流,再關閉內層的流 if(bos != null){ try { bos.close(); } catch (IOException e) { e.printStackTrace(); } } if(bis != null){ try { bis.close(); } catch (IOException e) { e.printStackTrace(); } } } }
測試二者速度
@Test public void testCopyFileWithBuffered(){ long start = System.currentTimeMillis(); String srcPath = "C:\\Users\\Administrator\\Desktop\\01-視頻.avi"; String destPath = "C:\\Users\\Administrator\\Desktop\\03-視頻.avi"; copyFileWithBuffered(srcPath,destPath); long end = System.currentTimeMillis(); System.out.println("復制操作花費的時間為:" + (end - start));//618 - 176 }
加密操作
將圖片文件通過字節流讀取到程序中
將圖片的字節流逐一進行^操作
將處理后的圖片字節流輸出
//圖片的加密 @Test public void test1() { FileInputStream fis = null; FileOutputStream fos = null; try { fis = new FileInputStream("test.jpg"); fos = new FileOutputStream("testSecret.jpg"); byte[] buffer = new byte[20]; int len; while ((len = fis.read(buffer)) != -1) { for (int i = 0; i < len; i++) { buffer[i] = (byte) (buffer[i] ^ 5); } fos.write(buffer, 0, len); } } catch (IOException e) { e.printStackTrace(); } finally { if (fos != null) { try { fos.close(); } catch (IOException e) { e.printStackTrace(); } } if (fis != null) { try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } } }
解密操作
將加密后圖片文件通過字節流讀取到程序中
將圖片的字節流逐一進行^操作(原理:A^B^B = A)
將處理后的圖片字節流輸出
//圖片的解密 @Test public void test2() { FileInputStream fis = null; FileOutputStream fos = null; try { fis = new FileInputStream("testSecret.jpg"); fos = new FileOutputStream("test4.jpg"); byte[] buffer = new byte[20]; int len; while ((len = fis.read(buffer)) != -1) { for (int i = 0; i < len; i++) { buffer[i] = (byte) (buffer[i] ^ 5); } fos.write(buffer, 0, len); } } catch (IOException e) { e.printStackTrace(); } finally { if (fos != null) { try { fos.close(); } catch (IOException e) { e.printStackTrace(); } } if (fis != null) { try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } } }
實現思路:
遍歷文本每一個字符
字符出現的次數存在Map中
把map中的數據寫入文件
@Test public void testWordCount() { FileReader fr = null; BufferedWriter bw = null; try { //1.創建Map集合 Map<Character, Integer> map = new HashMap<Character, Integer>(); //2.遍歷每一個字符,每一個字符出現的次數放到map中 fr = new FileReader("dbcp.txt"); int c = 0; while ((c = fr.read()) != -1) { //int 還原 char char ch = (char) c; // 判斷char是否在map中第一次出現 if (map.get(ch) == null) { map.put(ch, 1); } else { map.put(ch, map.get(ch) + 1); } } //3.把map中數據存在文件count.txt //3.1 創建Writer bw = new BufferedWriter(new FileWriter("wordcount.txt")); //3.2 遍歷map,再寫入數據 Set<Map.Entry<Character, Integer>> entrySet = map.entrySet(); for (Map.Entry<Character, Integer> entry : entrySet) { switch (entry.getKey()) { case ' ': bw.write("空格=" + entry.getValue()); break; case '\t'://\t表示tab 鍵字符 bw.write("tab鍵=" + entry.getValue()); break; case '\r':// bw.write("回車=" + entry.getValue()); break; case '\n':// bw.write("換行=" + entry.getValue()); break; default: bw.write(entry.getKey() + "=" + entry.getValue()); break; } bw.newLine(); } } catch (IOException e) { e.printStackTrace(); } finally { //4.關流 if (fr != null) { try { fr.close(); } catch (IOException e) { e.printStackTrace(); } } if (bw != null) { try { bw.close(); } catch (IOException e) { e.printStackTrace(); } } } }
轉換流提供了在字節流和字符流之間的轉換
Java API提供了兩個轉換流:
InputstreamReader:將 Inputstream轉換為Reader
OutputStreamWriter:將 Writer轉換為OutputStream
字節流中的數據都是字符時,轉成字符流操作更高效。
很多時候我們使用轉換流來處理文件亂碼問題。實現編碼和解碼的功能。
InputStreamReader將一個字節的輸入流轉換為字符的輸入流 解碼:字節、字節數組 --->字符數組、字符串
構造器:
public InputStreamReader(InputStream in)
public InputStreamReader(Inputstream in,String charsetName)//可以指定編碼集
OutputStreamWriter將一個字符的輸出流轉換為字節的輸出流 編碼:字符數組、字符串 ---> 字節、字節數組
構造器:
public OutputStreamWriter(OutputStream out)
public OutputStreamWriter(Outputstream out,String charsetName)//可以指定編碼集
圖示:
/** 綜合使用InputStreamReader和OutputStreamWriter */ @Test public void test1() { InputStreamReader isr = null; OutputStreamWriter osw = null; try { //1.造文件、造流 File file1 = new File("dbcp.txt"); File file2 = new File("dbcp_gbk.txt"); FileInputStream fis = new FileInputStream(file1); FileOutputStream fos = new FileOutputStream(file2); isr = new InputStreamReader(fis, "utf-8"); osw = new OutputStreamWriter(fos, "gbk"); //2.讀寫過程 char[] cbuf = new char[20]; int len; while ((len = isr.read(cbuf)) != -1){ osw.write(cbuf,0,len); } } catch (IOException e) { e.printStackTrace(); } finally { //3.關流 if (isr != null){ try { isr.close(); } catch (IOException e) { e.printStackTrace(); } } if (osw != null){ try { osw.close(); } catch (IOException e) { e.printStackTrace(); } } } }
說明:文件編碼的方式(比如:GBK),決定了解析時使用的字符集(也只能是GBK)。
ASCII:美國標準信息交換碼。用一個字節的7位可以表示。
ISO8859-1:拉丁碼表。歐洲碼表用一個字節的8位表示。
GB2312:中國的中文編碼表。最多兩個字節編碼所有字符
GBK:中國的中文編碼表升級,融合了更多的中文文字符號。最多兩個字節編碼
Unicode:國際標準碼,融合了目前人類使用的所字符。為每個字符分配唯一的字符碼。所有的文字都用兩個字節來表示。
UTF-8:變長的編碼方式,可用1-4個字節來表示一個字符。
說明:
面向傳輸的眾多UTF(UCS Transfer Format)標準出現了,顧名思義,UTF-8就是每次8個位傳輸數據,而UTF-16就是每次16個位。這是為傳輸而設計的編碼,并使編碼無國界,這樣就可以顯示全世界上所有文化的字符了。
Unicode只是定義了一個龐大的、全球通用的字符集,并為每個字符規定了唯確定的編號,具體存儲成什么樣的字節流,取決于字符編碼方案。推薦的Unicode編碼是UTF-8和UTF-16。
UTF-8變長編碼表示
編碼:字符串-->字節數組
解碼:字節數組-->字符串
轉換流的編碼應用
可以將字符按指定編碼格式存儲
可以對文本數據按指定編碼格式來解讀
指定編碼表的動作由構造器完成
使用要求:
客戶端/瀏覽器端 <----> 后臺(java,GO,Python,Node.js,php) <----> 數據庫
要求前前后后使用的字符集都要統一:UTF-8.
System.in:標準的輸入流,默認從鍵盤輸入
System.out:標準的輸出流,默認從控制臺輸出
System類的setIn(InputStream is) 方式重新指定輸入的流
System類的setOut(PrintStream ps)方式重新指定輸出的流。
從鍵盤輸入字符串,要求將讀取到的整行字符串轉成大寫輸出。然后繼續進行輸入操作,
直至當輸入“e”或者“exit”時,退出程序。
設計思路
方法一:使用Scanner實現,調用next()返回一個字符串
方法二:使用System.in實現。System.in ---> 轉換流 ---> BufferedReader的readLine()
public static void main(String[] args) { BufferedReader br = null; try { InputStreamReader isr = new InputStreamReader(System.in); br = new BufferedReader(isr); while (true) { System.out.println("請輸入字符串:"); String data = br.readLine(); if ("e".equalsIgnoreCase(data) || "exit".equalsIgnoreCase(data)) { System.out.println("程序結束"); break; } String upperCase = data.toUpperCase(); System.out.println(upperCase); } } catch (IOException e) { e.printStackTrace(); } finally { if (br != null) { try { br.close(); } catch (IOException e) { e.printStackTrace(); } } } }
設計實現Scanner類
public class MyInput { // Read a string from the keyboard public static String readString() { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); // Declare and initialize the string String string = ""; // Get the string from the keyboard try { string = br.readLine(); } catch (IOException ex) { System.out.println(ex); } // Return the string obtained from the keyboard return string; } // Read an int value from the keyboard public static int readInt() { return Integer.parseInt(readString()); } // Read a double value from the keyboard public static double readDouble() { return Double.parseDouble(readString()); } // Read a byte value from the keyboard public static double readByte() { return Byte.parseByte(readString()); } // Read a short value from the keyboard public static double readShort() { return Short.parseShort(readString()); } // Read a long value from the keyboard public static double readLong() { return Long.parseLong(readString()); } // Read a float value from the keyboard public static double readFloat() { return Float.parseFloat(readString()); } }
PrintStream 和 PrintWriter 說明:
提供了一系列重載的print()和println()方法,用于多種數據類型的輸出
System.out返回的是PrintStream的實例
@Test public void test2() { PrintStream ps = null; try { FileOutputStream fos = new FileOutputStream(new File("D:\\IO\\text.txt")); // 創建打印輸出流,設置為自動刷新模式(寫入換行符或字節 '\n' 時都會刷新輸出緩沖區) ps = new PrintStream(fos, true); if (ps != null) {// 把標準輸出流(控制臺輸出)改成文件 System.setOut(ps); } for (int i = 0; i <= 255; i++) { // 輸出ASCII字符 System.out.print((char) i); if (i % 50 == 0) { // 每50個數據一行 System.out.println(); // 換行 } } } catch (FileNotFoundException e) { e.printStackTrace(); } finally { if (ps != null) { ps.close(); } } }
DataInputStream 和 DataOutputStream 作用: 用于讀取或寫出基本數據類型的變量或字符串
示例代碼:
將內存中的字符串、基本數據類型的變量寫出到文件中。
@Test public void test3(){ //1.造對象、造流 DataOutputStream dos = null; try { dos = new DataOutputStream(new FileOutputStream("data.txt")); //數據輸出 dos.writeUTF("Bruce"); dos.flush();//刷新操作,將內存的數據寫入到文件 dos.writeInt(23); dos.flush(); dos.writeBoolean(true); dos.flush(); } catch (IOException e) { e.printStackTrace(); } finally { //3.關閉流 if (dos != null){ try { dos.close(); } catch (IOException e) { e.printStackTrace(); } } } }
將文件中存儲的基本數據類型變量和字符串讀取到內存中,保存在變量中。
/* 注意點:讀取不同類型的數據的順序要與當初寫入文件時,保存的數據的順序一致! */ @Test public void test4(){ DataInputStream dis = null; try { //1.造對象、造流 dis = new DataInputStream(new FileInputStream("data.txt")); //2.從文件讀入數據 String name = dis.readUTF(); int age = dis.readInt(); boolean isMale = dis.readBoolean(); System.out.println("name:"+name); System.out.println("age:"+age); System.out.println("isMale:"+isMale); } catch (IOException e) { e.printStackTrace(); } finally { //3.關閉流 if (dis != null){ try { dis.close(); } catch (IOException e) { e.printStackTrace(); } } } }
ObjectInputStream 和 ObjectOutputStream
ObjectOutputStream:內存中的對象--->存儲中的文件、通過網絡傳輸出去:序列化過程
ObjectInputStream:存儲中的文件、通過網絡接收過來 --->內存中的對象:反序列化過程
對象序列化機制允許把內存中的Java對象轉換成平臺無關的二進制流,從而允許把這種二進制流持久地保存在磁盤上,或通過網絡將這種二進制流傳輸到另一個網絡節點。//當其它程序獲取了這種二進制流,就可以恢復成原來的Java對象。
序列化的好處在于可將任何實現了Serializable接口的對象轉化為字節數據,使其在保存和傳輸時可被還原。
序列化是RMI(Remote Method Invoke-遠程方法調用)過程的參數和返回值都必須實現的機制,RMI是JavaEE的基礎。因此序列化機制是JavaEE平臺的基礎。
如果需要讓某個對象支持序列化機制,則必須讓對象所屬的類及其屬性是可序列化的,為了讓某個類是可序列化的,該類必須實現如下兩個接口之一。否則,會拋出 NotserializableEXception異常
Serializable
Externalizable
凡是實現Serializable接口的類都有一個表示序列化版本標識符的靜態變量:
private static final long serialVersionUID;
serialVersionUID用來表明類的不同版本間的兼容性。簡言之,其目的是以序列化對象進行版本控制,有關各版本反序列化時是否兼容
如果類沒有顯示定義這個靜態常量,它的值是Java運行時環境根據類的內部細節自動生成的。若類的實例變量做了修改,serialVersionUID可能發生變化。故建議顯式聲明。
簡單來說,Java的序列化機制是通過在運行時判斷類的serialversionUID來驗證版本一致性的。在進行反序列化時,JVM會把傳來的字節流中的serialversionUID與本地相應實體類的serialversionUID進行比較,如果相同就認為是一致的,可以進行反序列化,否則就會出現序列化版本不一致的異常。(InvalidCastException)
需要實現接口:Serializable(標識接口)
當前類提供一個全局常量:serialVersionUID(序列版本號)
除了當前Person類需要實現Serializable接口之外,還必須保證其內部所屬性也必須是可序列化的。(默認情況下,基本數據類型可序列化)
補充:ObjectOutputStream和ObjectInputStream不能序列化static和transient修飾的成員變量
序列化:將對象寫入磁盤或進行網絡傳輸
要求被序列化對象必須實現序列化
@Test public void testObjectOutputStream(){ ObjectOutputStream oos = null; try { //1.創建對象,創建流 oos = new ObjectOutputStream(new FileOutputStream("object.dat")); //2.操作流 oos.writeObject(new String("我愛北京天安門")); oos.flush();//刷新操作 oos.writeObject(new Person("王銘",23)); oos.flush(); oos.writeObject(new Person("張學良",23,1001,new Account(5000))); oos.flush(); } catch (IOException e) { e.printStackTrace(); } finally { if(oos != null){ //3.關閉流 try { oos.close(); } catch (IOException e) { e.printStackTrace(); } } } }
反序列化:將磁盤的對象數據源讀出
@Test public void testObjectInputStream(){ ObjectInputStream ois = null; try { ois = new ObjectInputStream(new FileInputStream("object.dat")); Object obj = ois.readObject(); String str = (String) obj; Person p = (Person) ois.readObject(); Person p1 = (Person) ois.readObject(); System.out.println(str); System.out.println(p); System.out.println(p1); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } finally { if(ois != null){ try { ois.close(); } catch (IOException e) { e.printStackTrace(); } } } }
RandomAccessFile的使用
RandomAccessFile直接繼承于java.lang.Object類,實現了DataInput和DataOutput接口
RandomAccessFile既可以作為一個輸入流,又可以作為一個輸出流
RandomAccessFile類支持“隨機訪問”的方式,程序可以直接跳到文件的任意地方來讀、寫文件
支持只訪問文件的部分內容
可以向已存在的文件后追加內容
RandomAccessFile對象包含一個記錄指針,用以標示當前讀寫處的位置
RandomaccessFile類對象可以自由移動記錄指針:
long getFilePointer():獲取文件記錄指針的當前位置
void seek(long pos):將文件記錄指針定位到pos位置
構造器
public RandomAccessFile(File file,String mode)
public RandomAccessFile(String name,String mode)
如果RandomAccessFile作為輸出流時,寫出到的文件如果不存在,則在執行過程中自動創建。
如果寫出到的文件存在,則會對原文件內容進行覆蓋。(默認情況下,從頭覆蓋)
可以通過相關的操作,實現RandomAccessFile“插入”數據的效果。借助seek(int pos)方法
創建RandomAccessFile類實例需要指定一個mode參數,該參數指定RandomAccessFile的訪問模式:
r:以只讀方式打開
rw:打開以便讀取和寫入
rwd:打開以便讀取和寫入;同步文件內容的更新
rws:打開以便讀取和寫入;同步文件內容和元數據的更新
如果模式為只讀r,則不會創建文件,而是會去讀取一個已經存在的文件,讀取的文件不存在則會出現異常。如果模式為rw讀寫,文件不存在則會去創建文件,存在則不會創建。
文件的讀取和寫出操作
@Test public void test1() { RandomAccessFile raf1 = null; RandomAccessFile raf2 = null; try { //1.創建對象,創建流 raf1 = new RandomAccessFile(new File("test.jpg"),"r"); raf2 = new RandomAccessFile(new File("test1.jpg"),"rw"); //2.操作流 byte[] buffer = new byte[1024]; int len; while((len = raf1.read(buffer)) != -1){ raf2.write(buffer,0,len); } } catch (IOException e) { e.printStackTrace(); } finally { //3.關閉流 if(raf1 != null){ try { raf1.close(); } catch (IOException e) { e.printStackTrace(); } } if(raf2 != null){ try { raf2.close(); } catch (IOException e) { e.printStackTrace(); } } } }
使用RandomAccessFile實現數據的插入效果
@Test public void test2(){ RandomAccessFile raf1 = null; try { raf1 = new RandomAccessFile(new File("hello.txt"), "rw"); raf1.seek(3);//將指針調到角標為3的位置 // //方式一 // //保存指針3后面的所有數據到StringBuilder中 // StringBuilder builder = new StringBuilder((int) new File("hello.txt").length()); // byte[] buffer = new byte[20]; // int len; // while ((len = raf1.read(buffer)) != -1){ // builder.append(new String(buffer,0,len)); // } //方式二 ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] buffer = new byte[20]; int len; while ((len = raf1.read(buffer)) != -1){ baos.write(buffer); } //調回指針,寫入“xyz” raf1.seek(3); raf1.write("xyz".getBytes()); //將StringBuilder中的數據寫入到文件中 raf1.write(baos.toString().getBytes()); } catch (IOException e) { e.printStackTrace(); } finally { if (raf1 != null){ try { raf1.close(); } catch (IOException e) { e.printStackTrace(); } } } }
流是用來處理數據的。
處理數據時,一定要先明確數據源,與數據目的地數據源可以是文件,可以是鍵盤數據目的地可以是文件、顯示器或者其他設備
而流只是在幫助數據進行傳輸,并對傳輸的數據進行處理,比如過濾處理、轉換處理等
除去RandomAccessFile類外所有的流都繼承于四個基本數據流抽象類InputSteam、OutputSteam、Reader、Writer
不同的操作流對應的后綴均為四個抽象基類中的某一個
不同處理流的使用方式都是標準操作:
創建文件對象,創建相應的流
處理流數據
關閉流
用try-catch-finally處理異常
Path、Paths、Files的使用,介紹比較簡單,后期會再抽時間詳細寫有關NIO的博客。
Java NIO (New IO,Non-Blocking IO)是從Java 1.4版本開始引入的一套新的IO API,可以替代標準的Java IO AP。
NIO與原來的IO同樣的作用和目的,但是使用的方式完全不同,NIO支持面向緩沖區的(IO是面向流的)、基于通道的IO操作。
NIO將以更加高效的方式進行文件的讀寫操作。
JDK 7.0對NIO進行了極大的擴展,增強了對文件處理和文件系統特性的支持,稱他為 NIO.2。
Java API中提供了兩套NIO,一套是針對標準輸入輸出NIO,另一套就是網絡編程NIO |-----java.nio.channels.Channel |---- FileChannel:處理本地文件 |---- SocketChannel:TCP網絡編程的客戶端的Channel |---- ServerSocketChannel:TCP網絡編程的服務器端的Channel |---- DatagramChannel:UDP網絡編程中發送端和接收端的Channel
早期的Java只提供了一個File類來訪問文件系統,但File類的功能比較有限,所提供的方法性能也不高。而且,大多數方法在出錯時僅返回失敗,并不會提供異常信息。
NIO.2為了彌補這種不足,引入了Path接口,代表一個平臺無關的平臺路徑,描述了目錄結構中文件的位置。Path可以看成是File類的升級版本,實際引用的資源也可以不存在。
Path替換原有的File類。
在以前IO操作都是這樣寫的:
import java.io.File
File file = new File("index.html");
但在Java7中,我們可以這樣寫:
import java.nio.file.Path;
import java.nio.file.Paths;
Path path = Paths.get("index. html");
Paths類提供的靜態get()方法用來獲取Path對象:
static Path get(String first, String….more):用于將多個字符串串連成路徑
static Path get(URI uri):返回指定uri對應的Path路徑
代碼示例
@Test public void test1(){ Path path2 = Paths.get("hello.txt");//new File(String filepath) Path path3 = Paths.get("E:\\", "test\\test1\\haha.txt");//new File(String parent,String filename); Path path4 = Paths.get("E:\\", "test"); System.out.println(path2); System.out.println(path3); System.out.println(path4); }
String toString() : 返回調用 Path 對象的字符串表示形式
boolean startsWith(String path) : 判斷是否以 path 路徑開始
boolean endsWith(String path) : 判斷是否以 path 路徑結束
boolean isAbsolute() : 判斷是否是絕對路徑
Path getParent() :返回Path對象包含整個路徑,不包含 Path 對象指定的文件路徑
Path getRoot() :返回調用 Path 對象的根路徑
Path getFileName() : 返回與調用 Path 對象關聯的文件名
int getNameCount() : 返回Path 根目錄后面元素的數量
Path getName(int idx) : 返回指定索引位置 idx 的路徑名稱
Path toAbsolutePath() : 作為絕對路徑返回調用 Path 對象
Path resolve(Path p) :合并兩個路徑,返回合并后的路徑對應的Path對象
File toFile(): 將Path轉化為File類的對象
代碼示例
@Test public void test2() { Path path2 = Paths.get("d:\\", "nio\\nio1\\nio2\\hello.txt"); Path path3 = Paths.get("hello.txt"); // String toString() : 返回調用 Path 對象的字符串表示形式 System.out.println(path2); // boolean startsWith(String path) : 判斷是否以 path 路徑開始 System.out.println(path2.startsWith("d:\\nio")); // boolean endsWith(String path) : 判斷是否以 path 路徑結束 System.out.println(path2.endsWith("hello.txt")); // boolean isAbsolute() : 判斷是否是絕對路徑 System.out.println(path2.isAbsolute() + "~"); System.out.println(path3.isAbsolute() + "~"); // Path getParent() :返回Path對象包含整個路徑,不包含 Path 對象指定的文件路徑 System.out.println(path2.getParent()); System.out.println(path3.getParent()); // Path getRoot() :返回調用 Path 對象的根路徑 System.out.println(path2.getRoot()); System.out.println(path3.getRoot()); // Path getFileName() : 返回與調用 Path 對象關聯的文件名 System.out.println(path2.getFileName() + "~"); System.out.println(path3.getFileName() + "~"); // int getNameCount() : 返回Path 根目錄后面元素的數量 // Path getName(int idx) : 返回指定索引位置 idx 的路徑名稱 for (int i = 0; i < path2.getNameCount(); i++) { System.out.println(path2.getName(i) + "*****"); } // Path toAbsolutePath() : 作為絕對路徑返回調用 Path 對象 System.out.println(path2.toAbsolutePath()); System.out.println(path3.toAbsolutePath()); // Path resolve(Path p) :合并兩個路徑,返回合并后的路徑對應的Path對象 Path path4 = Paths.get("d:\\", "nio"); Path path5 = Paths.get("nioo\\hi.txt"); path4 = path4.resolve(path5); System.out.println(path4); // File toFile(): 將Path轉化為File類的對象 File file = path2.toFile();//Path--->File的轉換 Path newPath = file.toPath();//File--->Path的轉換 }
java.nio.file.Files用于操作文件或目錄的工具類
Path copy(Path src, Path dest, CopyOption … how) : 文件的復制
要想復制成功,要求path2對應的物理上的文件存在。path2對應的文件沒有要求。
Files.copy(path2, path3, StandardCopyOption.REPLACE_EXISTING);
Path createDirectory(Path path, FileAttribute<?> … attr) : 創建一個目錄
要想執行成功,要求path對應的物理上的文件目錄不存在。一旦存在,拋出異常。
Path createFile(Path path, FileAttribute<?> … arr) : 創建一個文件
要想執行成功,要求path對應的物理上的文件不存在。一旦存在,拋出異常。
void delete(Path path) : 刪除一個文件/目錄,如果不存在,執行報錯
void deleteIfExists(Path path) : Path對應的文件/目錄如果存在,執行刪除.如果不存在,正常執行結束
Path move(Path src, Path dest, CopyOption…how) : 將 src 移動到 dest 位置
要想執行成功,src對應的物理上的文件需要存在,dest對應的文件沒有要求。
long size(Path path) : 返回 path 指定文件的大小
代碼示例
@Test public void test1() throws IOException{ Path path2 = Paths.get("d:\\nio", "hello.txt"); Path path3 = Paths.get("atguigu.txt"); // Path copy(Path src, Path dest, CopyOption … how) : 文件的復制 //要想復制成功,要求path2對應的物理上的文件存在。path2對應的文件沒有要求。 // Files.copy(path2, path3, StandardCopyOption.REPLACE_EXISTING); // Path createDirectory(Path path, FileAttribute<?> … attr) : 創建一個目錄 //要想執行成功,要求path對應的物理上的文件目錄不存在。一旦存在,拋出異常。 Path path4 = Paths.get("d:\\nio\\nio1"); // Files.createDirectory(path4); // Path createFile(Path path, FileAttribute<?> … arr) : 創建一個文件 //要想執行成功,要求path對應的物理上的文件不存在。一旦存在,拋出異常。 Path path5 = Paths.get("d:\\nio\\hi.txt"); // Files.createFile(path5); // void delete(Path path) : 刪除一個文件/目錄,如果不存在,執行報錯 // Files.delete(path5); // void deleteIfExists(Path path) : Path對應的文件/目錄如果存在,執行刪除.如果不存在,正常執行結束 Files.deleteIfExists(path4); // Path move(Path src, Path dest, CopyOption…how) : 將 src 移動到 dest 位置 //要想執行成功,src對應的物理上的文件需要存在,dest對應的文件沒有要求。 // Files.move(path2, path3, StandardCopyOption.ATOMIC_MOVE); // long size(Path path) : 返回 path 指定文件的大小 long size = Files.size(path3); System.out.println(size); }
boolean exists(Path path, LinkOption … opts) : 判斷文件是否存在
boolean isDirectory(Path path, LinkOption … opts) : 判斷是否是目錄
不要求此path對應的物理文件存在。
boolean isRegularFile(Path path, LinkOption … opts) : 判斷是否是文件
boolean isHidden(Path path) : 判斷是否是隱藏文件
要求此path對應的物理上的文件需要存在。才可判斷是否隱藏。否則,拋異常。
boolean isReadable(Path path) : 判斷文件是否可讀
boolean isWritable(Path path) : 判斷文件是否可寫
boolean notExists(Path path, LinkOption … opts) : 判斷文件是否不存在
代碼示例
@Test public void test2() throws IOException{ Path path2 = Paths.get("d:\\nio", "hello.txt"); Path path3 = Paths.get("atguigu.txt"); // boolean exists(Path path, LinkOption … opts) : 判斷文件是否存在 System.out.println(Files.exists(path3, LinkOption.NOFOLLOW_LINKS)); // boolean isDirectory(Path path, LinkOption … opts) : 判斷是否是目錄 //不要求此path對應的物理文件存在。 System.out.println(Files.isDirectory(path2, LinkOption.NOFOLLOW_LINKS)); // boolean isRegularFile(Path path, LinkOption … opts) : 判斷是否是文件 // boolean isHidden(Path path) : 判斷是否是隱藏文件 //要求此path對應的物理上的文件需要存在。才可判斷是否隱藏。否則,拋異常。 // System.out.println(Files.isHidden(path2)); // boolean isReadable(Path path) : 判斷文件是否可讀 System.out.println(Files.isReadable(path2)); // boolean isWritable(Path path) : 判斷文件是否可寫 System.out.println(Files.isWritable(path2)); // boolean notExists(Path path, LinkOption … opts) : 判斷文件是否不存在 System.out.println(Files.notExists(path2, LinkOption.NOFOLLOW_LINKS)); }
補充:
StandardOpenOption.READ:表示對應的Channel是可讀的。
StandardOpenOption.WRITE:表示對應的Channel是可寫的。
StandardOpenOption.CREATE:如果要寫出的文件不存在,則創建。如果存在,忽略
StandardOpenOption.CREATE_NEW:如果要寫出的文件不存在,則創建。如果存在,拋異常
InputStream newInputStream(Path path, OpenOption…how):獲取 InputStream 對象
OutputStream newOutputStream(Path path, OpenOption…how) : 獲取 OutputStream 對象
SeekableByteChannel newByteChannel(Path path, OpenOption…how) : 獲取與指定文件的連接,how 指定打開方式。
DirectoryStream<Path> newDirectoryStream(Path path) : 打開 path 指定的目錄
代碼示例
@Test public void test3() throws IOException{ Path path2 = Paths.get("d:\\nio", "hello.txt"); // InputStream newInputStream(Path path, OpenOption…how):獲取 InputStream 對象 InputStream inputStream = Files.newInputStream(path2, StandardOpenOption.READ); // OutputStream newOutputStream(Path path, OpenOption…how) : 獲取 OutputStream 對象 OutputStream outputStream = Files.newOutputStream(path2, StandardOpenOption.WRITE,StandardOpenOption.CREATE); // SeekableByteChannel newByteChannel(Path path, OpenOption…how) : 獲取與指定文件的連接,how 指定打開方式。 SeekableByteChannel channel = Files.newByteChannel(path2, StandardOpenOption.READ,StandardOpenOption.WRITE,StandardOpenOption.CREATE); // DirectoryStream<Path> newDirectoryStream(Path path) : 打開 path 指定的目錄 Path path3 = Paths.get("e:\\teach"); DirectoryStream<Path> directoryStream = Files.newDirectoryStream(path3); Iterator<Path> iterator = directoryStream.iterator(); while(iterator.hasNext()){ System.out.println(iterator.next()); } }
到此,關于“Java File類的理解與使用”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。