【轉載】J2SE知識點歸納筆記(七)---Java IO Part 1:File類與RandomAccessFile類

注:本文出自coder-pig

原文鏈接:http://blog.csdn.net/coder_pig/article/details/45248445





很快要到I/O流了,都是重要的內容,而且內容很多有難度的哦,如果是小花自己寫不知能否堅持下去,感謝小豬的這些文章,他可是花了很多心思,整個人都老了一大截可憐,希望大家能好好看看,不枉他老人家一片苦心。。。偷笑






本節引言:


兜兜轉轉,又回來寫Java了,上一篇J2SE知識點歸納筆記(六)---Java常用類是上2014.4.14寫的,時隔一年

又來重拾之前還沒寫完的系列了,前些天羣裏一個妹子反映她Java基礎薄弱,然後抱怨在csdn上找不到J2SE的

系列教程,J2SE簡單嘛,個個都懶得寫...真的簡單麼?或許吧...今天剛寫完論文初稿,也算稍微輕鬆了那麼一點,

白天上班,晚上趕論文,痛苦的一個星期也算到頭了...趁着臨近週末,小豬也來動下筆墨吧,(*^__^*) 嘻嘻……

哪怕有一個讀者,小豬也會堅持寫下去的。好了,嘮叨的廢話就說到這。本節要學習的東西:

Java IO,一說到IO,估計大家第一時間想起的就是:流,輸入輸出流,字符流,字節流等等,是吧,但是本節先不講

流,先來點開胃菜,介紹兩個文件IO的類: File(文件類)與RandomAccessFile(隨機訪問文件類),開始本節內容~


ps:另外說下Java IO相關的類和接口都放在java.io包下,大家要養成查API的習慣哦~







本節正文:


1.File(文件類):

1)File類的定義:

描述文件的相關特性,比如:是否可讀,可寫,文件大小等特性的一個類


2)創建File類對象時要注意的地方:

答:首先我們要區分兩個名詞:"絕對路徑"和"相對路徑"

絕對路徑——即完整的路徑,比如:D:\MyCode\Java\FileDemo

相對路徑——會在代碼所在的地方生成,比如:res/jay.txt  就會在你代碼的目錄下成jay.txt文件

另外,還有注意一點,文件的路徑與Windows下不同,"\"要寫成'/'或者"\\"不然會報錯的喔~


如果,你想保險點,讓程序跨平臺的話,比如在linux下就和Windows不一樣的,Linux下是"/"

解決方法就是使用File給我們提供的兩個常量,他們分別是:

File.separator: "\"            File.pathSeparator:";"


如果我們是直接自己拼的話,在window下,在D盤下我們要創建一個Jay.txt文件要這樣寫:

File f=new File("D:\\Jay.txt");    如果在Linux下呢?要寫成 //

如果我們用使用上面的兩個常量的話,我們無需理在什麼系統下,直接:

String fileName="D:"+File.separator+"Jay.txt";

File f=new File(fileName);

打印下fileName:  




好了,記得把這兩個變量Mark下來哦~



3)File的常見方法:

1)判斷文件或者目錄是否存在:  exists()

2)判斷是否爲目錄:   isDirectory()

3)判斷是否爲文件:    isFile()

4)判斷文件是否可讀:    canRead()

5)判斷文件是否可寫:    canWrite()

6)判斷文件是否隱藏:    isHidden()

7)判斷文件路徑是否爲絕對路徑:  isAbsolute()

8)判斷文件路徑是否相同:  equals():返回true,false        

                                        compareTo():是否相等,相等返回0,小於返回負數,大於返回正數

9)獲取文件的絕對路徑:   getAbsolutePath()

10)獲取文件名稱:  getName()

11)獲取文件大小:  length()

12)獲取文件最後被修改的時間 :  lastModified()

13)獲取文件的路徑:   getPath()

14)獲取文件的上層文件的目錄:   getParent()

15)創建一個新文件:    createNewFile()

16)創建一個新目錄:    mkdir()

17)刪除文件或目錄:  delete()

18)修改文件的名稱:   renameTo(str)

19)修改文件爲只讀:  setReadOnly() 

20)修改最後的修改時間:   setLastModified(long time) 



4)File的使用示例:

①創建一個文件:

  1. public void newFile(String fileName)throws Exception  
  2. {  
  3.     File f=new File(fileName);  
  4.     f.createNewFile();  
  5. }  

②刪除一個文件:

  1. public void deleteFile(String fileName)  
  2. {  
  3.     File f=new File(fileName);  
  4.     if(f.exists())f.delete();  
  5.     else System.out.println("文件不存在");  
  6. }  

③創建一個文件夾:

  1. public void newDir(String fileName)  
  2. {  
  3.     //fileName寫文件夾名哦,比如:D:\Test  
  4.     File f=new File(fileName);  
  5.     f.mkdir();  
  6. }  

④刪除文件夾

刪除文件夾的方法和刪除文件是一樣的,都是調用delete( )方法,空文件夾可以直接刪除,

但是有一點要注意的是,非空文件夾是不能直接刪除的哦!!!我們需要先把裏面的文件都

刪除了,才能刪除文件夾哦,那麼現在我們要做的是,就是刪除文件夾裏的文件咯,如果

有幾層怎麼破?我們需要考慮這個問題,這裏的話,如果我們使用遞歸的話,就很容易解決

這個問題了,代碼如下:

  1. import java.io.File;  
  2.   
  3. public class RemoveDir {  
  4.     public static void main(String[] args) {  
  5.         File file = new File("D:\\Test");  
  6.         removeDir(file);  
  7.     }  
  8.   
  9.     public static void removeDir(File file) {  
  10.         File[] files = file.listFiles();  
  11.         for (File f : files) {  
  12.             if (f.isDirectory())// 遞歸調用  
  13.             {  
  14.                 removeDir(f);  
  15.             } else {  
  16.                 f.delete();  
  17.             }  
  18.         }   
  19.         // 一層目錄下的內容都刪除以後,刪除掉這個文件夾  
  20.         file.delete();  
  21.     }  
  22. }  

好吧,遞歸就是這麼奇妙~


⑤判斷路徑是否爲文件夾(目錄):

  1. public boolean isDir(String fileName)  
  2. {  
  3.     File f=new File(fileName);  
  4.     if(f.isDirectory()){  
  5.            <span style="white-space:pre">     </span>return true;  
  6.        <span style="white-space:pre"> </span>}  
  7.     return false;  
  8. }  


⑥遍歷某文件夾下所有文件(文件名,包含隱藏文件):

  1. public void getAllFile1(String fileName) {  
  2.     File f = new File(fileName);  
  3.     String[] str = f.list();  
  4.     for (int i = 0; i < str.length; i++) {  
  5.         System.out.println(str[i]);  
  6.     }  
  7. }  


⑦遍歷某文件夾下所有文件(包括完整路徑,包含隱藏文件)

  1. public void getAllFile2(String fileName) {  
  2.     File f = new File(fileName);  
  3.     File[] str = f.listFiles();  
  4.     for (int i = 0; i < str.length; i++) {  
  5.         System.out.println(str[i]);  
  6.     }  
  7. }  


⑧遍歷某目錄下的全部文件(包含子目錄,完整路徑,隱藏文件)

還是用到我們的遞歸:

  1.     /* 
  2.      * 獲取某目錄下的全部文件(包含子目錄,完整路徑,隱藏文件) 
  3.      * */  
  4.     public void getAllFile3(File file) {  
  5.         if(file != null){  
  6.             if(file.isDirectory()){  
  7.                 File[] fileArray=file.listFiles();  
  8.                 if(fileArray!=null){  
  9.                     for (int i = 0; i < fileArray.length; i++) {  
  10.                         //遞歸調用  
  11.                         getAllFile3(fileArray[i]);  
  12.                     }  
  13.                 }  
  14.             }  
  15.             else{  
  16.                 System.out.println(file);  
  17.             }  
  18.         }  
  19. }  


5)學以致用的兩個小例子:

①遍歷某個文件夾下特定的文件

比如某個目錄下的所有.zip文件,筆者的電腦下載了很多編程視頻,

我們想遍歷查看所有.zip的文件的名稱:


核心是:判斷是否爲目錄,文件名的篩選

好吧,下面我們就來實現吧:


  1. /* 
  2.  * 遍歷某目錄下特定文件的文件名與路徑 
  3.  */  
  4. public static void getSpecificFile(File file, String suffix) {  
  5.     if (file != null) {  
  6.         if (file.isDirectory()) {  
  7.             File[] fileArray = file.listFiles();  
  8.             String name1 = file.getName();  
  9.             System.out.println("——————" + name1);  
  10.             if (fileArray != null) {  
  11.                 for (int i = 0; i < fileArray.length; i++) {  
  12.                     // 遞歸調用  
  13.                     getSpecificFile(fileArray[i], suffix);  
  14.                 }  
  15.             }  
  16.         } else {  
  17.             if (file.getName().toString().endsWith(suffix)) {  
  18.                 System.out.print("               ");  
  19.                 System.out.println(file  
  20.                         .getName()  
  21.                         .toString()  
  22.                         .substring(  
  23.                                 0,  
  24.                                 file.getName().toString().length()  
  25.                                         - suffix.length()));  
  26.             }  
  27.         }  
  28.     }  
  29. }  


調用方法處代碼:



部分運行截圖:





②批量文件命名:

比如我們寫App的時候,下載了一大堆了素材圖片:



而下載的時候:他們的文件名是這樣的:


我們是想把他們作爲頭像的,我們想把他們改成head1.png,head2.png...這種文件名格式的,

難道我們一個個手動的去改麼=-=,如果這些圖標有上百個,改到什麼時候呢?

學以致用,這裏我們就來實現簡單的批量文件名修改:

比如我們這裏需要批量修改下述的圖標:



代碼實現:

  1. /** 
  2.  * 批量修改文件名: 
  3.  * @param filename 要是目錄哦! 
  4.  */  
  5. public static boolean changeFileNames(String fileName,String suffix)  
  6. {  
  7.     File f = new File(fileName);  
  8.     if(!f.isDirectory())  
  9.     {  
  10.         return false;  
  11.     }  
  12.     int j = 0;  
  13.     File[] fs = f.listFiles();  
  14.     for(int i = 0;i < fs.length;i++)  
  15.     {  
  16.         String str = fs[i].getName();  
  17.         if(str.endsWith(suffix))  
  18.         {  
  19.             fs[i].renameTo(new File(fileName + File.separator +"head" + j +suffix));  
  20. /               System.out.println(fileName + File.separator +"head" + j +suffix);  
  21.             j++;  
  22.         }  
  23.     }  
  24.     return true;  
  25. }  


運行後:



好了,就是那麼簡單,是不是又有趣呢?這裏並沒有都是一些簡單的東西,筆者可以根據自己的需要,

進行拓展,比如遍歷文件後,生成另外的txt文件而不是直接打印到屏幕上等....




2.RandomAccessFile類

1)這個類是幹嘛的?

隨機訪問文件類,其實和File的功能類似,都是用於操作文件,但是RandomAccessFile類

seek( )方法來訪問文件,可以從文件的任意位置讀寫文件,這個seek可以看做文件指針吧,

而這個類,我們用的最多的無疑是:Java多線程文件下載~

ps:其實這個小豬已經在Android入門之路的day 8寫過了,這裏就再貼一遍哈,別怪小豬偷懶哈偷笑,

另外這個多線程下載的話,文件小的話效果不大哦~比如下個1,2mb的東西....另外示例給的是

Tomact搭建的web空項目,要下載的東西丟到Webroot目錄下即可,另外你可以可以直接改成

網上的一個下載鏈接~



我們都知道使用多線程下載文件可以更快地完成文件的下載,但是爲什麼呢?

答:因爲搶佔的服務器資源多,假設服務器最多服務100個用戶,服務器中的一個線程對應一個用戶

100條線程在計算機中併發執行,由CPU劃分時間片輪流執行,加入a有99條線程下載文件,那麼

相當於佔用了99個用戶資源,自然就有用較快的下載速度

ps:當然不是線程越多就越好,開啓過多線程的話,app需要維護和同步每條線程的開銷,這些開銷

反而會導致下載速度的降低,另外還和你的網速有關!


多線程下載的流程

獲取網絡連接——本地磁盤創建相同大小的空文件——計算每條線程需從文件哪個部分開始下載,結束

——依次創建,啓動多條線程來下載網絡資源的指定部分



ps:這裏直接用J2SE來完成多線程操作,直接建立一個工程,使用Junit運行指定方法即可

如果再Android下用單元測試有點麻煩,照顧一部分朋友,你直接new一個Java Project即可!


代碼如下:

DownLoader.java

  1. package com.jay.test;  
  2.   
  3. import java.io.InputStream;  
  4. import java.io.RandomAccessFile;  
  5. import java.net.HttpURLConnection;  
  6. import java.net.URL;  
  7. import org.junit.Test;  
  8.   
  9.   
  10. public class Downloader {  
  11.     //添加@Test標記是表示該方法是Junit測試的方法,就可以直接運行該方法了  
  12.         @Test  
  13.         public void download() throws Exception  
  14.         {  
  15.             //設置URL的地址和下載後的文件名  
  16.             String filename = "meitu.exe";  
  17.             String path = "http://10.13.20.32:8080/Test/XiuXiu_Green.exe";  
  18.               
  19.             URL url = new URL(path);  
  20.             HttpURLConnection conn = (HttpURLConnection) url.openConnection();  
  21.             conn.setConnectTimeout(5000);  
  22.             conn.setRequestMethod("GET");  
  23.               
  24.             //獲得需要下載的文件的長度(大小)  
  25.             int filelength = conn.getContentLength();  
  26.             System.out.println("要下載的文件長度"+filelength);  
  27.             //生成一個大小相同的本地文件  
  28.             RandomAccessFile file = new RandomAccessFile(filename, "rwd");  
  29.             file.setLength(filelength);  
  30.             file.close();  
  31.             conn.disconnect();  
  32.             //設置有多少條線程下載  
  33.             int threadsize = 3;  
  34.             //計算每個線程下載的量  
  35.             int threadlength = filelength % 3 == 0 ? filelength/3:filelength+1;  
  36.             for(int i = 0;i < threadsize;i++)  
  37.             {  
  38.                 //設置每條線程從哪個位置開始下載  
  39.                 int startposition = i * threadlength;  
  40.                 //從文件的什麼位置開始寫入數據  
  41.                 RandomAccessFile threadfile = new RandomAccessFile(filename, "rwd");  
  42.                 threadfile.seek(startposition);  
  43.                 //啓動三條線程分別從startposition位置開始下載文件  
  44.                 new DownLoadThread(i,startposition,threadfile,threadlength,path).start();  
  45.             }  
  46.             int quit = System.in.read();  
  47.             while('q' != quit)  
  48.             {  
  49.                 Thread.sleep(2000);  
  50.             }  
  51.         }  
  52.       
  53.       
  54.     private class DownLoadThread extends Thread {  
  55.           
  56.           
  57.         private int threadid;  
  58.         private int startposition;  
  59.         private RandomAccessFile threadfile;  
  60.         private int threadlength;  
  61.         private String path;  
  62.         public DownLoadThread(int threadid, int startposition,  
  63.                 RandomAccessFile threadfile, int threadlength, String path) {  
  64.             this.threadid = threadid;  
  65.             this.startposition = startposition;  
  66.             this.threadfile = threadfile;  
  67.             this.threadlength = threadlength;  
  68.             this.path = path;  
  69.         }  
  70.           
  71.         public DownLoadThread() {}  
  72.           
  73.         @Override  
  74.         public void run() {  
  75.             try  
  76.             {  
  77.                 URL url = new URL(path);  
  78.                 HttpURLConnection conn = (HttpURLConnection) url.openConnection();  
  79.                 conn.setConnectTimeout(5000);  
  80.                 conn.setRequestMethod("GET");  
  81.                 //指定從什麼位置開始下載  
  82.                 conn.setRequestProperty("Range""bytes="+startposition+"-");  
  83.                 //System.out.println(conn.getResponseCode());  
  84.                 if(conn.getResponseCode() == 206)  
  85.                 {  
  86.                     InputStream is = conn.getInputStream();  
  87.                     byte[] buffer = new byte[1024];  
  88.                     int len = -1;  
  89.                     int length = 0;  
  90.                     while(length < threadlength && (len = is.read(buffer)) != -1)  
  91.                     {  
  92.                         threadfile.write(buffer,0,len);  
  93.                         //計算累計下載的長度  
  94.                         length += len;  
  95.                     }  
  96.                     threadfile.close();  
  97.                     is.close();  
  98.                     System.out.println("線程"+(threadid+1) + "已下載完成");  
  99.                 }  
  100.                   
  101.                   
  102.             }catch(Exception ex){System.out.println("線程"+(threadid+1) + "下載出錯"+ ex);}  
  103.         }  
  104.           
  105.     }  
  106. }  


運行截圖:



如圖,使用多線程完成了對文件的下載!雙擊exe文件可運行,說明文件並沒有損壞!


注意事項:

int filelength = conn.getContentLength();   //獲得下載文件的長度(大小)

RandomAccessFile file = new RandomAccessFile(filename, "rwd");  

//該類運行對文件進行讀寫,是多線程下載的核心

int threadlength = filelength % 3 == 0 ? filelength/3:filelength+1;

//計算每個線程要下載的量

conn.setRequestProperty("Range", "bytes="+startposition+"-");

//指定從哪個位置開始讀寫,這個是URLConnection提供的方法

//System.out.println(conn.getResponseCode());

//這個註釋了的代碼是用來查看conn的返回碼的,我們前面用的都是200,

而針對多線程的話,通常是206,必要時我們可以通過調用該方法查看返回碼!

int quit = System.in.read();

while('q' != quit){Thread.sleep(2000);}

//這段代碼是做延時操作的,因爲我們用的是本地下載,可能該方法運行完了,而我們的

線程還沒有開啓,這樣會引發異常,這裏的話,讓用戶輸入一個字符,如果是'q'的話就退出


代碼下載:J2SEMulDownLoader.zip





最後說兩句:

關於JavaIO中的File和RandowAccessFile就介紹這裏了,得意

大家可以發揮自己的創造力,使用這兩個類,實現自己想要的功能~


最後把File的東東都貼到一個工具類中,有需要的可以複製粘貼:

  1. import java.io.File;  
  2.   
  3.   
  4. public class FileUtil {  
  5.     /* 
  6.      * 創建一個新文件 
  7.      * */  
  8.     public static void newFile(String fileName) throws Exception {  
  9.         File f = new File(fileName);  
  10.         f.createNewFile();  
  11.     }  
  12.   
  13.       
  14.     /* 
  15.      * 刪除文件 
  16.      * */  
  17.     public static void deleteFile(String fileName) {  
  18.         File f = new File(fileName);  
  19.         if (f.exists())  
  20.             f.delete();  
  21.         else  
  22.             System.out.println("文件不存在");  
  23.     }  
  24.   
  25.     /* 
  26.      * 創建一個文件夾(目錄) 
  27.      * */  
  28.     public static void newDir(String fileName) {  
  29.         // fileName寫文件夾名哦,比如:D:\Test  
  30.         File f = new File(fileName);  
  31.         f.mkdir();  
  32.     }  
  33.   
  34.     /* 
  35.      * 刪除一個文件夾(目錄) 
  36.      * */  
  37.     public static void deleteDir(File file) {  
  38.         File[] files = file.listFiles();  
  39.         for (File f : files) {  
  40.             if (f.isDirectory())// 遞歸調用  
  41.             {  
  42.                 deleteDir(f);  
  43.             } else {  
  44.                 f.delete();  
  45.             }  
  46.         }  
  47.         // 一層目錄下的內容都刪除以後,刪除掉這個文件夾  
  48.         file.delete();  
  49.     }  
  50.   
  51.     /* 
  52.      * 判斷是否爲一個文件夾(目錄) 
  53.      * */  
  54.     public static boolean isDir(String fileName) {  
  55.         File f = new File(fileName);  
  56.         if (f.isDirectory()) {  
  57.             return true;  
  58.         }  
  59.         return false;  
  60.     }  
  61.   
  62.     /* 
  63.      * 獲取目錄下的全部文件名,包含隱藏文件 
  64.      */  
  65.     public static void getAllFile1(String fileName) {  
  66.         File f = new File(fileName);  
  67.         String[] str = f.list();  
  68.         for (int i = 0; i < str.length; i++) {  
  69.             System.out.println(str[i]);  
  70.         }  
  71.     }  
  72.   
  73.     /* 
  74.      * 獲取目錄下的全部文件名包含完整路徑,包含隱藏文件 
  75.      */  
  76.     public static void getAllFile2(String fileName) {  
  77.         File f = new File(fileName);  
  78.         File[] str = f.listFiles();  
  79.         for (int i = 0; i < str.length; i++) {  
  80.             System.out.println(str[i]);  
  81.         }  
  82.     }  
  83.   
  84.     /* 
  85.      * 獲取某目錄下的全部文件(包含子目錄,完整路徑,隱藏文件) 
  86.      */  
  87.     public static void getAllFile3(File file) {  
  88.         if (file != null) {  
  89.             if (file.isDirectory()) {  
  90.                 File[] fileArray = file.listFiles();  
  91.                 if (fileArray != null) {  
  92.                     for (int i = 0; i < fileArray.length; i++) {  
  93.                         // 遞歸調用  
  94.                         getAllFile3(fileArray[i]);  
  95.                     }  
  96.                 }  
  97.             } else {  
  98.                 System.out.println(file);  
  99.             }  
  100.         }  
  101.     }  
  102.   
  103.     /* 
  104.      * 遍歷某目錄下特定文件的文件名與路徑 
  105.      */  
  106.     public static void getSpecificFile(File file, String suffix) {  
  107.         if (file != null) {  
  108.             if (file.isDirectory()) {  
  109.                 File[] fileArray = file.listFiles();  
  110.                 String name1 = file.getName();  
  111.                 System.out.println("——————" + name1);  
  112.                 if (fileArray != null) {  
  113.                     for (int i = 0; i < fileArray.length; i++) {  
  114.                         // 遞歸調用  
  115.                         getSpecificFile(fileArray[i], suffix);  
  116.                     }  
  117.                 }  
  118.             } else {  
  119.                 if (file.getName().toString().endsWith(suffix)) {  
  120.                     System.out.print("               ");  
  121.                     System.out.println(file  
  122.                             .getName()  
  123.                             .toString()  
  124.                             .substring(  
  125.                                     0,  
  126.                                     file.getName().toString().length()  
  127.                                             - suffix.length()));  
  128.                 }  
  129.             }  
  130.         }  
  131.     }  
  132.   
  133.     /** 
  134.      * 批量修改文件名: 
  135.      * @param filename 要是目錄哦! 
  136.      */  
  137.     public static boolean changeFileNames(String fileName,String suffix)  
  138.     {  
  139.         File f = new File(fileName);  
  140.         if(!f.isDirectory())  
  141.         {  
  142.             return false;  
  143.         }  
  144.         int j = 0;  
  145.         File[] fs = f.listFiles();  
  146.         for(int i = 0;i < fs.length;i++)  
  147.         {  
  148.             String str = fs[i].getName();  
  149.             if(str.endsWith(suffix))  
  150.             {  
  151.                 fs[i].renameTo(new File(fileName + File.separator +"head" + j +suffix));  
  152. //              System.out.println(fileName + File.separator +"head" + j +suffix);  
  153.                 j++;  
  154.             }  
  155.         }  
  156.         return true;  
  157.     }  
  158. }  



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章