Java IO 流總結篇

1. 寫在前面的話

I/O ,I 是 Input (輸入)的縮寫,O是Output (輸出) 的縮寫,衆所周知,人與人之間想要溝通交流,就須要講彼此都能聽懂的語言,好比你們都統一說英語。css

人類若是想和計算機交流,也須要共同的語言,而計算機只懂二進制0101代碼,然而人類發現很難理解和學懂這門語言,因而乎有了一個「翻譯機「——高級編程語言,好比C#,Java 等,高級編程語言經過一種解釋器的程序能夠將人類容易學習的高級語言代碼解釋翻譯成二進制代碼,因而乎計算機便能聽懂咱們的命令,作咱們想讓它作的事情了。html

一樣,程序和程序之間也有交流方式,那就是I/O.前端

I/O 其實在某種意義上是一個應用程序與文件,網絡鏈接,控制檯 通訊交流的一套API.java

在Java.io包中最重要的就是5個類和一個接口。5個類指的是File、OutputStream、InputStream、Writer、Reader;一個接口指的是Serializable。掌握了這些就掌握了Java I/O的精髓了。ios

正如上面所提到,若是咱們想對文件操做,可使用File相關的類,來進行文件新建,複製,移動,遍歷,刪除等操做。c++

若是想對文件的內容進行操做,咱們則能夠考慮兩種方式,一種是讀取字節流的方式,一種是讀取字符的方式。數據庫

也許你會困惑何時用哪種方式會更好呢?編程

個人建議:後端

若是操做的文件內容中沒有中文,那麼通常用字節流就行(InputStream和OutputStream),固然用字符流(Reader 和Writer)也沒啥問題。api

可是若是操做的文件中有中文,那麼就不得不用字符流來操做了,使用的時候要注意字符編碼。

這是爲何呢?

由於一箇中文文字至少佔用2個字節,一個英文文字通常至少佔據一個字節便可。

Java中I/O操做主要是指使用Java進行輸入,輸出操做. Java全部的I/O機制都是基於數據流進行輸入輸出,這些數據流表示了字符或者字節數據的流動序列。

  •  字節流:數據流中最小的數據單元是字節 
  •  字符流:數據流中最小的數據單元是字符, Java中的字符是Unicode編碼,一個字符佔用兩個字節。

想要正確顯示中文漢字,則至少須要兩個字節的組合來讀寫,若是用字節流來讀寫,可能看到的就是亂碼。

當不一樣數量的字節組合就產生了不通的字符編碼。好比GB2312能完美的支持簡體中文和英文,一箇中文文字佔用2個字節,一個英文字母一樣佔用2個字節。

關於字符編碼的討論細節,當年大一那時候偶然發現寫過一篇有趣的博文,當執行下面這條命令,C語言打印出來是 「我愛你「」三個字

printf("%c%c%c%c%c%c\n",206,210,176,174,196,227);

 顯示打印結果:

有興趣能夠看下 C語言中兩位ASCLL碼能夠表示漢字

JDK6 在線中文文檔:http://tool.oschina.net/apidocs/apidoc?api=jdk-zh

JDK7: http://tool.oschina.net/apidocs/apidoc?api=jdk_7u4

2. Java 的 I/O 的基本分類

I/O 問題是任何編程語言都沒法迴避的問題,能夠說 I/O 問題是整我的機交互的核心問題,由於 I/O 是機器獲取和交換信息的主要渠道。

咱們經過高級語言編寫程序代碼來進行I/O操做, 從而實現人機交互。

在Java.io包中最重要的就是5個類和一個接口。

5個類指的是File、OutputStream、InputStream、Writer、Reader;一個接口指的是Serializable。

掌握了這些就掌握了Java I/O的精髓了。

Java 的 I/O 操做類在包 java.io 下,大概有將近 80 個類,可是這些類大概能夠分紅四組,分別是:

  1. 基於字節操做的 I/O 接口:InputStream 和 OutputStream
  2. 基於字符操做的 I/O 接口:Writer 和 Reader
  3. 基於磁盤操做的 I/O 接口:File
  4. 基於網絡操做的 I/O 接口:Socket

前兩組主要是根據傳輸數據的數據格式,後兩組主要是根據傳輸數據的方式,雖然 Socket 類並不在 java.io 包下,可是我仍然把它們劃分在一塊兒,由於我我的認爲 I/O 的核心問題要麼是數據格式影響 I/O 操做,要麼是傳輸方式影響 I/O 操做,也就是將什麼樣的數據寫到什麼地方的問題,I/O 只是人與機器或者機器與機器交互的手段,除了在它們可以完成這個交互功能外,咱們關注的就是如何提升它的運行效率了,而數據格式和傳輸方式是影響效率最關鍵的因素了。咱們後面的分析也是基於這兩個因素來展開的。————摘自IBM 學習文檔

java.io包裏有4個基本類:InputStream、OutputStream及Reader、Writer類,它們分別處理字節流和字符流。

其餘各類各樣的流都是由這4個派生出來的。

 

在JDK 1.4 以後引入了 NIO,NIO 相比傳統的IO流作了改進,其中一個亮點就是引入了緩衝區的概念。

2.1 File 類

關於 File 這個對象咱們須要注意的是,它不只能夠用來表示一個文件也能夠表示一個文件夾。

File 類能夠寫一個實用的工具類。

如今假如咱們須要查詢某一個文件夾下全部的文件中是.java 類型的文件列表

那麼咱們須要兩個參數,一個是查詢文件夾路徑名稱,第二個參數是文件的類型

若是不遞歸的話,能夠這樣調用

List<File> fileList=SmartFileUtils.lookFollder("C:\\Users\\fairy\\Pictures\\國家地理館",".jpg");//只查詢圖片文件 不遞歸
//List<File> fileList=SmartFileUtils.lookFollder("C:\\Users\\fairy\\Pictures\\國家地理館");//查詢全部文件夾和文件 不遞歸
for (File file : fileList) { System.out.println(file.getAbsolutePath()); }

遞歸查詢當前文件夾包括子文件夾下全部的java 文件列表,咱們能夠這樣調用:

public static void main(String[] args) {
        
        FileTreeInfo fileTreeInfo=SmartFileUtils.watchFolder(".",".java");//只查詢java文件 遞歸
       //FileTreeInfo fileTreeInfo=SmartFileUtils.watchFolder(".");//查詢全部文件夾和文件 遞歸
        System.out.println(fileTreeInfo.toString());
}

若是想單獨獲取查詢結果的文件夾和文件集合列表,這樣調用便可

List<File> fileList=fileTreeInfo.fileList;
List<File> folderList=fileTreeInfo.folderList;

 SmartFileUtils.java

import java.io.File;
import java.io.FilenameFilter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Pattern;

/**
 * @author fairy 查詢文件夾下的文件
 ***/
public class SmartFileUtils {
    /** 
     * 查看某個文件夾下全部文件和文件夾列表
     * 無遞歸 
     * */
    public final static List<File> lookFollder(String startDir) {
        return lookFollderInfo(new File(startDir), ".*");
    }
    /** 
     * 查看某個文件夾下指定類型的文件和文件夾列表
     * 無遞歸
     * */
    public final static List<File> lookFollder(String startDir, String regex) {
        return lookFollderInfo(new File(startDir), ".*\\" + regex);
    }
    private final static List<File> lookFollderInfo(File rootFolder, final String regex) {
        return Arrays.asList(
            rootFolder.listFiles(new FilenameFilter() {
            private Pattern pattern = Pattern.compile(regex);
            @Override
            public boolean accept(File dir, String name) {
                // TODO Auto-generated method stub
                return pattern.matcher(name).matches();
            }
        }));
    }

    /** 
     * 查看某個文件夾下全部的文件和文件夾列表
     * 遞歸遍歷
     *  */
    public final static FileTreeInfo watchFolder(String startDir) {
        return watchDirs(new File(startDir), ".*");
    }
    /** 
     * 查看某個文件夾下指定類型的文件和文件夾列表
     * 遞歸遍歷
     * */
    public final static FileTreeInfo watchFolder(String startDir, String regex) {
        return watchDirs(new File(startDir), ".*" + regex);
    }
    private final static FileTreeInfo watchDirs(File startDir, String regex) {
        FileTreeInfo resultInfo = new FileTreeInfo();

        for (File item : startDir.listFiles()) {
            if (item.isDirectory()) {
                resultInfo.folderList.add(item);
                resultInfo.addAll(watchDirs(item, regex));
            } else {
                if (item.getName().matches(regex)) {
                    resultInfo.fileList.add(item);
                }
            }
        }
        return resultInfo;
    }
    /**
     * TreeInfo
     ***/
    public static class FileTreeInfo implements Iterable<File> {
        public List<File> fileList = new ArrayList<File>();
        public List<File> folderList = new ArrayList<File>();

        public Iterator<File> iterator() {
            return fileList.iterator();
        }

        void addAll(FileTreeInfo other) {
            fileList.addAll(other.fileList);
            folderList.addAll(other.folderList);
        }

        public String toString() {
            return "dirs:" + PPrint.pFormat(folderList) + "\n\nfiles:" + PPrint.pFormat(fileList);
        }
    }
}
View Code

 

上面代碼中咱們引用了一個格式化打印集合工具類:

import java.util.Collection;

public class PPrint {

      public static String pFormat(Collection<?> c) {
          if(c.size()==0) return "[]";
          StringBuilder result=new StringBuilder();
          for (Object elem:c) {
            if(c.size()!=1) {
                result.append("\n  ");
            }
            result.append(elem);
          }
          if(c.size()!=1) {
              result.append("\n");
          }
          result.append("]");
          return result.toString();
      }
}
View Code

字節和字符之間的轉化

另外數據持久化或網絡傳輸都是以字節進行的,因此必需要有字符到字節或字節到字符的轉化。

字節到字符須要轉化,其中讀的轉化過程以下圖所示:

字節流<----讀----->字符流

圖 5. 字符解碼相關類結構

InputStreamReader 類是字節到字符的轉化橋樑,StreamDecoder 正是完成字節到字符的解碼的實現類

InputStream 到 Reader 的過程要指定編碼字符集,不然將採用操做系統默認字符集,極可能會出現亂碼問題。

寫入也是相似的過程以下圖所示:

圖 : 字節流<----寫----->字符流

圖 6. 字符編碼相關類結構

經過 OutputStreamWriter 類完成,字符到字節的編碼過程,由 StreamEncoder 完成編碼過程。

5. Java IO 流的基本方法

5.1 InputStream 的基本方法

5.2 OutputStream 的基本方法

5.3 Reader的基本方法

5.4 Writer 的基本方法

6. Java 經常使用流的使用

6.1 節點流類型

FileInputStreamTest.java

package com.xingyun.io;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URISyntaxException;

public class FileInputStreamTest {

    public final static String getCurrentFilePath =new File("").getAbsolutePath()+"\\src\\com\\xingyun\\io\\"+FileInputStreamTest.class.getSimpleName()+".java";
    //getCurrentFilePath: C:\Users\fairy\Documents\EclipseWorkspace\JavaSEBaseSample\src\com\xingyun\io\InputStreamTest.java
    
    public static void main(String[] args) throws IOException, URISyntaxException {
        // TODO Auto-generated method
        int b=0;//read byte count
        FileInputStream fileInputStream=null;    
        try {
            fileInputStream=new FileInputStream(getCurrentFilePath);
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            System.out.println("File not found");
            System.exit(-1);
        }
        try {
            long num=0;
            while((b=fileInputStream.read())!=-1) {
                System.out.print((char)b);
                num++;
            }
            System.out.println("--read over------");
            System.out.println("read "+num+" byte");
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally {
            fileInputStream.close();
        }
    }
}
View Code

FileOutputStreamTest.java

package com.xingyun.io;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class FileOutputStreamTest {

    public final static String getCurrentFilePath =new File("").getAbsolutePath()+"\\src\\com\\xingyun\\io\\"+FileOutputStreamTest.class.getSimpleName()+".java";
    public final static String writeNewFilePath=new File("").getAbsolutePath()+"\\src\\com\\xingyun\\io\\"+FileOutputStreamTest.class.getSimpleName()+"New.txt";
    
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        int b=0;
        FileInputStream fileInputStream=null;
        FileOutputStream fileOutputStream=null;
        
        try {
            fileInputStream=new FileInputStream(getCurrentFilePath);
            fileOutputStream=new FileOutputStream(writeNewFilePath);
            while ((b=fileInputStream.read())!=-1) {
                fileOutputStream.write(b);
            }
            
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
          System.out.println("can't find the file");
        } catch (IOException e) {
            // TODO Auto-generated catch block
            System.out.println("read or write error");
        }finally {
            try {
                System.out.println("read and write success");
                fileInputStream.close();
                fileOutputStream.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                System.out.println("close error");
                System.exit(-1);
            }    
        }
        

    }

}
View Code

FileReaderTest.java

package com.xingyun.io;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class FileReaderTest {

    private final static String getCurrentFilePath =new File("").getAbsolutePath()+"\\src\\com\\xingyun\\io\\"+FileReaderTest.class.getSimpleName()+".java";

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        FileReader fileReader=null;
        int c=0;
        try {
            fileReader=new FileReader(getCurrentFilePath);
            while((c=fileReader.read())!=-1) {
                System.out.print((char)c);
            }
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally {
            try {
                fileReader.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}
View Code

FileWriterTest.java

package com.xingyun.io;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class FileWriterTest {

    public final static String getCurrentFilePath =new File("").getAbsolutePath()+"\\src\\com\\xingyun\\io\\"+FileWriterTest.class.getSimpleName()+".java";
    public final static String writeNewFilePath=new File("").getAbsolutePath()+"\\src\\com\\xingyun\\io\\"+FileWriterTest.class.getSimpleName()+"New.txt";
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        int b=0;
        FileReader fileReader=null;
        FileWriter fileWriter=null;
        
        try {
            fileReader=new FileReader(getCurrentFilePath);
            fileWriter=new FileWriter(writeNewFilePath);
            while ((b=fileReader.read())!=-1) {
                fileWriter.write(b);
            }
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
          System.out.println("can't find the file");
        } catch (IOException e) {
            // TODO Auto-generated catch block
            System.out.println("read or write error");
        }finally {
            try {
                System.out.println("read and write success");
                fileReader.close();
                fileWriter.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                System.out.println("close error");
                System.exit(-1);
            }    
        }
        

    }

}
View Code

 6.2 處理流類型

6.2.1 緩衝流

BufferedInputStreamTest.java  

package com.xingyun.io;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class BufferedInputStreamTest {

    public final static String getCurrentFilePath =new File("").getAbsolutePath()+"\\src\\com\\xingyun\\io\\"+BufferedInputStreamTest.class.getSimpleName()+".java";

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        FileInputStream fileInputStream=null;
        BufferedInputStream bufferedInputStream=null;
        try {
            fileInputStream=new FileInputStream(getCurrentFilePath);
            bufferedInputStream=new BufferedInputStream(fileInputStream,100);
            int c=0;
            System.out.println(bufferedInputStream.read());
            System.out.println(bufferedInputStream.read());
            bufferedInputStream.mark(100);//jump to 100 location
            for (int i = 0; i <10&&((c=bufferedInputStream.read())!=-1); i++) {
                System.out.print((char)c+" ");
            }
            System.out.println("");
            System.out.println("------------------");
            bufferedInputStream.reset();//return to 100 location
            for (int i = 0; i <10&&((c=bufferedInputStream.read())!=-1); i++) {
                System.out.print((char)c+" ");
            }
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally {
            try {

                fileInputStream.close();
                bufferedInputStream.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

}
View Code 

BufferedWriterAndBufferedReaderTest.java

package com.xingyun.io;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class BufferedWriterAndBufferedReaderTest {

    public final static String getCurrentFilePath =new File("").getAbsolutePath()+"\\src\\com\\xingyun\\io\\"+BufferedWriterAndBufferedReaderTest.class.getSimpleName()+"New.txt";

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        BufferedWriter bufferedWriter=null;
        BufferedReader bufferedReader=null;
        try {
            bufferedWriter=new BufferedWriter(new FileWriter(getCurrentFilePath),100);
            bufferedReader=new BufferedReader(new FileReader(getCurrentFilePath),100);
            String string=null;
            for(int i=0;i<100;i++) {
                string=String.valueOf(Math.random());
                bufferedWriter.write(string);
                bufferedWriter.newLine();
            }
            bufferedWriter.flush();
            while ((string=bufferedReader.readLine())!=null) {
                System.out.println(string);
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally {
            try {
                bufferedWriter.close();
                bufferedReader.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

    }

}
View Code

 6.2.2 轉換流

OutputStreamWriterTest.java

package com.xingyun.io;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class InputStreamReaderTest {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        InputStreamReader inputStreamReader = new InputStreamReader(System.in);

        BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
        String string = null;
        try {
            string = bufferedReader.readLine();
            while (string != null) {
                if (string.equals("exit"))
                    break;
                else {
                    System.out.println(string.toUpperCase());
                    string = bufferedReader.readLine();
                }

            }
            System.out.println(bufferedReader.readLine());
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            try {
                inputStreamReader.close();
                bufferedReader.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

}
View Code

InputStreamReaderTest.java

package com.xingyun.io;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class InputStreamReaderTest {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        InputStreamReader inputStreamReader = new InputStreamReader(System.in);
        BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
        String string = null;
        try {
            string = bufferedReader.readLine();
            while (string != null) {
                if (string.equals("exit"))
                    break;
                else {
                    System.out.println(string.toUpperCase());
                    string = bufferedReader.readLine();
                }

            }
            System.out.println(bufferedReader.readLine());
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            try {
                inputStreamReader.close();
                bufferedReader.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

}
View Code

6.2.3 打印流

PrintStreamTest.java

package com.xingyun.io;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;

public class PrintStreamTest {

    public final static String getCurrentFilePath = new File("").getAbsolutePath() + "\\src\\com\\xingyun\\io\\"
            + PrintStreamTest.class.getSimpleName() + "New.txt";

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        PrintStream printStream = null;
        FileOutputStream fileOutputStream=null;
        try {
            fileOutputStream = new FileOutputStream(getCurrentFilePath);
            printStream = new PrintStream(fileOutputStream);
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        if (printStream != null) {
            System.setOut(printStream);
        }
        //it will write into a file but not console screen
        int line = 0;
        for (char c = 0; c <= 60000; c++) {
            System.out.print(c + "");
            if (line++ >= 100) {
                System.out.println();
                line = 0;
            }
        }
        //it will write into a file but not console screen
        System.out.println("write into file success");
        try {
            fileOutputStream.close();
            printStream.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}
View Code

 

PrintStreamTest2.java

package com.xingyun.io;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintStream;

public class PrintStreamTest2 {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        String filename = args[0];    
        //you must type the file path as args
        //C:\Users\fairy\Documents\EclipseWorkspace\JavaSEBaseSample\src\com\xingyun\io\PrintStreamTest2.java
        System.out.println("please type file path which one file you need to print");
        if (filename != null) {
            list(filename, System.out);
        }
    }

    public static void list(String f, PrintStream printStream) {
        BufferedReader bufferedReader = null;
        try {
            bufferedReader = new BufferedReader(new FileReader(f));
            String string = null;
            while ((string = bufferedReader.readLine()) != null) {
                printStream.println(string);
            }
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            try {
                bufferedReader.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

}
View Code

PrintStreamTest3.java

package com.xingyun.io;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Date;

public class PrintStreamTest3 {

    public final static String getCurrentFilePath =new File("").getAbsolutePath()+"\\src\\com\\xingyun\\io\\"+PrintStreamTest3.class.getSimpleName()+"New.log";

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        String string=null;
        System.out.println("Please type message:");
        BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(System.in),100);
        FileWriter fileWriter=null;
        PrintWriter printWriter=null;
        
        try {
            fileWriter=new FileWriter(getCurrentFilePath,true);
            printWriter=new PrintWriter(fileWriter);
            
            while((string=bufferedReader.readLine())!=null) {
                if(string.equals("exit"))break;
                System.out.println(string.toUpperCase());
                printWriter.println("-------------------");
                printWriter.println(string.toUpperCase());
                printWriter.flush();
            }
            printWriter.println("-------------"+new Date()+"--------");
            printWriter.flush();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally {
            printWriter.close();
        }
    }
}
View Code

6.2.4  Object 流

Tips: 

transient 序列化時不處理這個關鍵字修飾的變量

serializable 使得本身的實體類支持序列化和反序列化

 

externalizable 接口,本身處理序列化和反序列化

ObjectOutputStreamTest.java

package com.xingyun.io;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class ObjectOutputStreamTest {

    public final static String getCurrentFilePath =new File("").getAbsolutePath()+"\\src\\com\\xingyun\\io\\"+ObjectOutputStreamTest.class.getSimpleName()+"New.log";

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        // TODO Auto-generated method stub
        TestObject testObject=new TestObject();
        testObject.k=8;
        
        //write
        FileOutputStream fileOutputStream=new FileOutputStream(getCurrentFilePath);
        ObjectOutputStream objectOutputStream=new ObjectOutputStream(fileOutputStream);
        objectOutputStream.writeObject(testObject);
        objectOutputStream.flush();
        objectOutputStream.close();
        fileOutputStream.close();
        
        //read
        FileInputStream fileInputStream=new FileInputStream(getCurrentFilePath);
        ObjectInputStream objectInputStream=new ObjectInputStream(fileInputStream);
        TestObject tReaderObject= (TestObject)objectInputStream.readObject();
        System.out.println("------"+tReaderObject.i+"----------"+tReaderObject.j+"------"+tReaderObject.d+"---------"+tReaderObject.k);
        objectInputStream.close();
        fileInputStream.close();

    }
    
    static class TestObject implements Serializable{
        /**
         * 
         */
        private static final long serialVersionUID = -5736467218763256621L;
        int i=10;
        int j=9;
        double d=2.30;
       // int k=18;
       transient int k=18;//don't deal with the value 
    }
}
View Code

 

7. IO調優

下面就磁盤 I/O 和網絡 I/O 的一些經常使用的優化技巧進行總結以下:

磁盤 I/O 優化

性能檢測

咱們的應用程序一般都須要訪問磁盤讀取數據,而磁盤 I/O 一般都很耗時,咱們要判斷 I/O 是不是一個瓶頸,咱們有一些參數指標能夠參考:

如咱們能夠壓力測試應用程序看系統的 I/O wait 指標是否正常,例如測試機器有 4 個 CPU,那麼理想的 I/O wait 參數不該該超過 25%,若是超過 25% 的話,I/O 極可能成爲應用程序的性能瓶頸。Linux 操做系統下能夠經過 iostat 命令查看。

一般咱們在判斷 I/O 性能時還會看另一個參數就是 IOPS,咱們應用程序須要最低的 IOPS 是多少,而咱們的磁盤的 IOPS 能不能達到咱們的要求。每一個磁盤的 IOPS 一般是在一個範圍內,這和存儲在磁盤的數據塊的大小和訪問方式也有關。可是主要是由磁盤的轉速決定的,磁盤的轉速越高磁盤的 IOPS 也越高。

如今爲了提升磁盤 I/O 的性能,一般採用一種叫 RAID 的技術,就是將不一樣的磁盤組合起來來提升 I/O 性能,目前有多種 RAID 技術,每種 RAID 技術對 I/O 性能提高會有不一樣,能夠用一個 RAID 因子來表明,磁盤的讀寫吞吐量能夠經過 iostat 命令來獲取,因而咱們能夠計算出一個理論的 IOPS 值,計算公式以下因此:

( 磁盤數 * 每塊磁盤的 IOPS)/( 磁盤讀的吞吐量 +RAID 因子 * 磁盤寫的吞吐量 )=IOPS

這個公式的詳細信息請查閱參考資料 Understanding Disk I/O

提高 I/O 性能

提高磁盤 I/O 性能一般的方法有:

  1. 增長緩存,減小磁盤訪問次數
  2. 優化磁盤的管理系統,設計最優的磁盤訪問策略,以及磁盤的尋址策略,這裏是在底層操做系統層面考慮的。
  3. 設計合理的磁盤存儲數據塊,以及訪問這些數據塊的策略,這裏是在應用層面考慮的。如咱們能夠給存放的數據設計索引,經過尋址索引來加快和減小磁盤的訪問,還有能夠採用異步和非阻塞的方式加快磁盤的訪問效率。
  4. 應用合理的 RAID 策略提高磁盤 IO,每種 RAID 的區別咱們能夠用下表所示:
表 2.RAID 策略

網絡 I/O 優化

網絡 I/O 優化一般有一些基本處理原則:

  1. 一個是減小網絡交互的次數:要減小網絡交互的次數一般咱們在須要網絡交互的兩端會設置緩存,好比 Oracle 的 JDBC 驅動程序,就提供了對查詢的 SQL 結果的緩存,在客戶端和數據庫端都有,能夠有效的減小對數據庫的訪問。關於 Oracle JDBC 的內存管理能夠參考《 Oracle JDBC 內存管理》。除了設置緩存還有一個辦法是,合併訪問請求:如在查詢數據庫時,咱們要查 10 個 id,我能夠每次查一個 id,也能夠一次查 10 個 id。再好比在訪問一個頁面時經過會有多個 js 或 css 的文件,咱們能夠將多個 js 文件合併在一個 HTTP 連接中,每一個文件用逗號隔開,而後發送到後端 Web 服務器根據這個 URL 連接,再拆分出各個文件,而後打包再一併發回給前端瀏覽器。這些都是經常使用的減小網絡 I/O 的辦法。
  2. 減小網絡傳輸數據量的大小:減小網絡數據量的辦法一般是將數據壓縮後再傳輸,如 HTTP 請求中,一般 Web 服務器將請求的 Web 頁面 gzip 壓縮後在傳輸給瀏覽器。還有就是經過設計簡單的協議,儘可能經過讀取協議頭來獲取有用的價值信息。好比在代理程序設計時,有 4 層代理和 7 層代理都是來儘可能避免要讀取整個通訊數據來取得須要的信息。
  3. 儘可能減小編碼:一般在網絡 I/O 中數據傳輸都是以字節形式的,也就是一般要序列化。可是咱們發送要傳輸的數據都是字符形式的,從字符到字節必須編碼。可是這個編碼過程是比較耗時的,因此在要通過網絡 I/O 傳輸時,儘可能直接以字節形式發送。也就是儘可能提早將字符轉化爲字節,或者減小字符到字節的轉化過程。
  4. 根據應用場景設計合適的交互方式:所謂的交互場景主要包括同步與異步阻塞與非阻塞方式,下面將詳細介紹。

知識擴展

新的輸入/輸出 (NIO) 庫是在 JDK 1.4 中引入的。NIO 彌補了原來的 I/O 的不足,它在標準 Java 代碼中提供了高速的、面向塊的 I/O。經過定義包含數據的類,以及經過以塊的形式處理這些數據,NIO 不用使用本機代碼就能夠利用低級優化,這是原來的 I/O 包所沒法作到的。

參考文章

Java I/O 總結   http://www.importnew.com/23708.html 

深刻分析 Java I/O 的工做機制 https://www.ibm.com/developerworks/cn/java/j-lo-javaio/

NIO入門 https://www.ibm.com/developerworks/cn/education/java/j-nio/j-nio.html

 Java NIO與IO 對比 : http://ifeve.com/java-nio-vs-io/

相關文章
相關標籤/搜索