posts - 262,  comments - 221,  trackbacks - 0
          【一】Apache commons IO包之IOUtils

          前面我們已經(jīng)學(xué)習(xí)了FileUtils,知道了Apache commons IO包提供了很多實(shí)用的工具來對文件進(jìn)行操作。但是它們的底層到底是怎么實(shí)現(xiàn)的呢?如果現(xiàn)在我們要操作的不是文件,而是網(wǎng)絡(luò)資源呢?

          其實(shí)FileUtils的基石就是IOUtils,它內(nèi)置了大量的簡化方法來簡化IO讀寫操作和提供默認(rèn)的緩沖支持。看看官網(wǎng)的說法:



          【二】IOUtils的常用API及解析

          ①讀操作

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

           ※ readLines方法

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


          我們知道在字節(jié)流中是沒有“行”的概念的,但是為什么這里的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進(jìn)行了包裝,到了readLines(Reader)方法內(nèi),又再加了一個緩沖。如果我們是直接調(diào)用readLines(Reader)方法,為了確保編碼正確,需要手工創(chuàng)建一個InputStreamReader并指明encoding,否則將采用默認(rèn)的encoding。

           ※ toXxx方法

          IOUtils支持把input stream中的數(shù)據(jù)轉(zhuǎn)換成byte[],char[],String對象。而且input stream可以是字節(jié)流,字符流。同時可以指定encoding。這些方法實(shí)質(zhì)上是“輸出”的過程:即從輸入流中讀入數(shù)據(jù),然后轉(zhuǎn)換為byte[],char[],String,輸出到內(nèi)存中。看看下面的一個源代碼:

              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;
              }



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

          ②寫操作

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

           ※ 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,會發(fā)現(xiàn)它對所有的文件讀寫(包括writeLines,writeStringToFile),都是調(diào)用字節(jié)流+encoding的方式來進(jìn)行的。因?yàn)樗谢谧址鞯姆绞阶罱K都需要轉(zhuǎn)換為基于字節(jié)流的方式。

          ③流拷貝

          我們在從文件等數(shù)據(jù)源讀入數(shù)據(jù)時,習(xí)慣性地以字節(jié)讀入,到了內(nèi)存又轉(zhuǎn)換成String對象,最后修改性地以字符寫回文件。IOUtils提供了一系列方便的方法來進(jìn)行這中間的轉(zhuǎn)換。

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

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

          上面這兩個方法底層都調(diào)用了一個名為copyLarge的方法,他們分別在通過一個byte[]或者char[]數(shù)組對要寫回的內(nèi)容進(jìn)行緩沖。一次性地從源端讀入4K數(shù)據(jù)然后通過輸出流寫回。

              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;
              }

          ④內(nèi)容比較

          這一點(diǎn)在前面FileUtils.contentEquals(File, File)方法中已經(jīng)有提及,請參考上一篇文章


          -------------------------------------------------------------
          生活就像打牌,不是要抓一手好牌,而是要盡力打好一手爛牌。
          posted on 2010-03-08 21:24 Paul Lin 閱讀(2396) 評論(0)  編輯  收藏 所屬分類: J2SE
          <2010年3月>
          28123456
          78910111213
          14151617181920
          21222324252627
          28293031123
          45678910

          常用鏈接

          留言簿(21)

          隨筆分類

          隨筆檔案

          BlogJava熱點(diǎn)博客

          好友博客

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 渝中区| 湟源县| 祁阳县| 德令哈市| 禄丰县| 五常市| 宾阳县| 普洱| 吉林省| 铜陵市| 吉首市| 大姚县| 灵台县| 江川县| 万盛区| 罗山县| 桂东县| 瑞安市| 红桥区| 小金县| 上饶市| 东乡族自治县| 定陶县| 应用必备| 蒲江县| 沁源县| 湖北省| 兴义市| 穆棱市| 富顺县| 收藏| 舞阳县| 元谋县| 娱乐| 安义县| 中山市| 正安县| 资源县| 马山县| 萍乡市| 东港市|