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/

相关文章
相关标签/搜索