apache FileUtils 和 IOUtils 工具類 改寫普通文件讀寫方式 提高效率

不重複開發的輪子,既然人家已經寫好了通用成熟的工具,與其自己吭哧吭哧寫通用類,還不如拿來用即可。但是用歸用,不瞭解還是不行滴,咻咻,

apache下 開源了許多實用的工具類,一般都是在commons包下。

開源的在線文檔:http://commons.apache.org/

commons.jar 包下載 :http://commons.apache.org/io/download_io.cgi

這裏講到了:  IOUtils 和 FileUtils 。 中文文檔奇缺,有知道的童鞋可以吱一聲。

1.IOUtils 簡要說明

該類爲input/output操作提供了通用靜態方法。

包括功能:

•closeQuietly——這些關閉一個流的方法將忽略nulls和例外的情況。

•toXxx /read-這些方法從一個流讀取數據。

• write這些方法將數據寫到一個流裏。

copy——這些方法用於從一個流的所有的數據複製到另一個流。

•contentEquals——這些方法用於比較兩個流的內容。

 

byte-to-char方法集和char-to-byte方法集都包括一個轉換步驟。給出的兩種方法集合在每種情況下,一種是使用平臺默認的編碼方式,另一個允許你指定一個編碼。

鼓勵你總是指定一個編碼因爲依靠平臺違約會帶來意想不到的結果,例如從開發階段移動到產品部署。

 

這個類裏面所有的方法在讀一個流的時候內部是被緩衝的。這意味着我們外部使用的時候就不需要BufferedInputStream或BufferedReader。在測試中默認緩存4 K已被證明是有效。

無論在何處,在這個類裏的方法在這堂課裏不要衝洗或關閉流。這是爲了避免犯不可移植的假設那小溪的來源和進一步使用。因此調用者還需要負責使用後手動關閉流。

 

-------------------------------------------------------------------------------------------------------------------------------------------------------------

 使用IOUtils來重寫原來的讀取寫入流的操作,代碼簡潔,沒了煩人的try  以前連基本的操作都要在兩個流之間倒來倒去 還要考慮怎麼轉換,現在一切都是浮雲了。

--------------------------------------------------------------------------------------------------------------------------------------------------------------

這邊是API的簡單介紹:

1.closeQuietly 包括對各種類型輸入輸出流的關閉。 無條件的關閉流。

  1. byte[] data = "Hello, World".getBytes();   
  2.   
  3. OutputStream out = null;  
  4.   
  5.  try {   
  6.   
  7.     out = new FileOutputStream("foo.txt");   
  8.   
  9.     out.write(data);   
  10.   
  11.     //out.close();//close errors are handled  我們通常的用法,是不太好的。  
  12.   
  13.     }   
  14.   
  15. catch (IOException e) {   
  16.   
  17. // error handling   
  18.   
  19. finally  
  20.   
  21.  {  
  22.   
  23.   IOUtils.closeQuietly(out); 以後就直接在finally裏關閉流。也不需要判斷條件。  
  24.   
  25.  }  


2. toByteArray 從各類輸入流中讀取數據並轉換爲字節數組。

toByteArray(參數) 裏的參數包括:Reader,InputStream,String,這裏String 已經過時,等同於String.getBytes();

toByteArray

public static byte[] toByteArray(InputStream input,
                                 long size)
                          throws IOException

以字節數組的形式來獲取inputStream流裏的內容,如果在流的大小已知的情況下,可以用此方法來代替默認的toByteArray(InputStream input)方法。

注:該方法會檢查size是否可以安全地轉換爲int,在其正式讀到字節數組前。

 

①讀操作

IOUtils類提供的讀操作方法有兩大類:第一類是readLines方法。第二類是toXxx方法。

 ※ readLines方法

List readLines(InputStream input)
List readLines(InputStream input, String encoding)
readLines(Reader input)


我們知道在字節流中是沒有“行”的概念的,但是爲什麼這裏的readLines方法可以接收InputStream呢?看看源代碼就知道了

public static List readLines(InputStream input, String encoding) throws IOException {
        
if (encoding == null{
            
return readLines(input);
        }
 else {
            InputStreamReader reader = new InputStreamReader(input, encoding);

            
return readLines(reader);
        }

    }


public static List readLines(Reader input) throws IOException {
        BufferedReader reader 
= new BufferedReader(input);
        List list 
= new ArrayList();
        String line 
= reader.readLine();
        
while (line != null{
            list.add(line);
            line 
= reader.readLine();
        }

        
return list;
    }


原來在底層,IOUtils使用了InputStreamReader對input stream進行了包裝,到了readLines(Reader)方法內,又再加了一個緩衝。如果我們是直接調用readLines(Reader)方法,爲了確保編碼正確,需要手工創建一個InputStreamReader並指明encoding,否則將採用默認的encoding。

 ※ toXxx方法

IOUtils支持把inputStream中的數據轉換成byte[],char[],String對象。而且input stream可以是字節流,字符流。同時可以指定encoding。這些方法實質上是“輸出”的過程:即從輸入流中讀入數據,然後轉換爲byte[],char[],String,輸出到內存中。看看下面的一個源代碼:

    public static char[] toCharArray(InputStream is, String encoding)
            
throws IOException {
        CharArrayWriter output 
= new CharArrayWriter();
        copy(is, output, encoding);
        
return output.toCharArray();
    }


    
public static void copy(InputStream input, Writer output, String encoding)
            
throws IOException {
        
if (encoding == null{
            copy(input, output);
        }
 else {
          InputStreamReader in = new InputStreamReader(input, encoding);

            copy(in, output);
        }

    }


    
public static int copy(Reader input, Writer output) throws IOException {
        
long count = copyLarge(input, output);
        
if (count > Integer.MAX_VALUE) {
            
return -1;
        }

        
return (int) count;
    }


    
public static long copyLarge(Reader input, Writer output) throws IOException {
        
char[] buffer = new char[DEFAULT_BUFFER_SIZE];
        
long count = 0;
        
int n = 0;
        
while (-1 != (n = input.read(buffer))) {
            output.write(buffer, 0, n);

            count 
+= n;
        }

        
return count;
    }



我們可以看到這個過程是沒有進行flush的操作的,也就是說使用者必須負責在調用結束後進行緩存清空和輸入、輸入流關閉。對於input stream是文件的情況,在FileUtils的文件讀方法的最後都會調用IOUtils.closeQuietly(in);方法來確保輸入流正確關閉。

②寫操作

和讀操作一樣,IOUtils一樣提供了大量的寫方法,這些方法可以將byte[],char[],StringBuffer,String,Collection中的數據以字節流,字符流的形式寫入到目的源。

 ※ writeLines方法

public static void writeLines(Collection lines, String lineEnding,
            OutputStream output, String encoding) 
throws IOException {
        
if (encoding == null{
            writeLines(lines, lineEnding, output);
        }
 else {
            
if (lines == null{
                
return;
            }

            
if (lineEnding == null{
                lineEnding 
= LINE_SEPARATOR;
            }

            
for (Iterator it = lines.iterator(); it.hasNext(); ) {
                Object line 
= it.next();
                
if (line != null{
                    output.write(line.toString().getBytes(encoding));
                }

                output.write(lineEnding.getBytes(encoding));
            }

        }

    }


public static void writeLines(Collection lines, String lineEnding,
            Writer writer) 
throws IOException {
        
if (lines == null{
            
return;
        }

        
if (lineEnding == null{
            lineEnding 
= LINE_SEPARATOR;
        }

        
for (Iterator it = lines.iterator(); it.hasNext(); ) {
            Object line 
= it.next();
            
if (line != null{
                writer.write(line.toString());
            }

            writer.write(lineEnding);
        }

    }


如果我們查看FileUtils,會發現它對所有的文件讀寫(包括writeLines,writeStringToFile),都是調用字節流+encoding的方式來進行的。因爲所有基於字符流的方式最終都需要轉換爲基於字節流的方式。

③流拷貝

我們在從文件等數據源讀入數據時,習慣性地以字節讀入,到了內存又轉換成String對象,最後修改性地以字符寫回文件。IOUtils提供了一系列方便的方法來進行這中間的轉換。

copy(InputStream input, Writer output, String encoding),這個方法使用指定的encoding,從字節流中讀入字節,然後按照encoding解碼,通過字符流寫回目的源。

copy(Reader input, OutputStream output, String encoding),這個方法從字符流中讀取字符,使用指定的encoding編碼,通過字節流寫回目的源,然後立即清空緩衝。

上面這兩個方法底層都調用了一個名爲copyLarge的方法,他們分別在通過一個byte[]或者char[]數組對要寫回的內容進行緩衝。一次性地從源端讀入4K數據然後通過輸出流寫回。

    public static long copyLarge(InputStream input, OutputStream output)
            
throws IOException {
        
byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
        
long count = 0;
        
int n = 0;
        
while (-1 != (n = input.read(buffer))) {
            output.write(buffer, 
0, n);
            count 
+= n;
        }

        
return count;
    }


    
public static long copyLarge(Reader input, Writer output) throws IOException {
        
char[] buffer = new char[DEFAULT_BUFFER_SIZE];
        
long count = 0;
        
int n = 0;
        
while (-1 != (n = input.read(buffer))) {
            output.write(buffer, 
0, n);
            count 
+= n;
        }

        
return count;
    }

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