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机制都是基于数据流进行输入输出,这些数据流表示了字符或者字节数据的流动序列。
想要正确显示中文汉字,则至少须要两个字节的组合来读写,若是用字节流来读写,可能看到的就是乱码。
当不一样数量的字节组合就产生了不通的字符编码。好比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
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 个类,可是这些类大概能够分红四组,分别是:
前两组主要是根据传输数据的数据格式,后两组主要是根据传输数据的方式,虽然 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流作了改进,其中一个亮点就是引入了缓冲区的概念。
关于 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); } } }
上面代码中咱们引用了一个格式化打印集合工具类:
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(); } }
另外数据持久化或网络传输都是以字节进行的,因此必需要有字符到字节或字节到字符的转化。
字节到字符须要转化,其中读的转化过程以下图所示:
InputStreamReader 类是字节到字符的转化桥梁,StreamDecoder 正是完成字节到字符的解码的实现类
InputStream 到 Reader 的过程要指定编码字符集,不然将采用操做系统默认字符集,极可能会出现乱码问题。
写入也是相似的过程以下图所示:
经过 OutputStreamWriter 类完成,字符到字节的编码过程,由 StreamEncoder 完成编码过程。
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(); } } }
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); } } } }
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(); } } } }
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); } } } }
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(); } } } }
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(); } } } }
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(); } } } }
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(); } } } }
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(); } } }
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(); } } } }
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(); } } }
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 } }
下面就磁盘 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 性能一般的方法有:
网络 I/O 优化一般有一些基本处理原则:
知识扩展
新的输入/输出 (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/