Java核心技术,撑持Java程序对外接口的I/O
IO(Input/Output)作为Java编程语言的核心之一其重要性不言而喻,其实现了Java程序对外界的访问和输出,学好Java也是建立在熟练掌握IO的基础之上。其提供了对文件数据操作功能,在学习时要清晰掌握其可能发生特殊异常(有些异常编译器也发现不了,而IO中方法绝大多数都会抛出异常)的方法,比如read需要结束标记、缓冲流的write方法还有flush()等等。
System.out.println(data);
这段简单的输出语句是我们在Java编程时用到的最频繁的语句之一,其实这是一个标准的输出流,用于将字符串输出到屏幕上,也可以将其重定向到另一个输出目标。
流(Stream)的概念很形象,其为一组有序的数据序列。按照数据类型可以分类为字符流和字节流,字符流是对输入字符进行字符编码得到的流,字节流是指可以用计算机处理的二进制数据或者指令所组成的流。两者根据操作类型,可以大致划分为四大类,其中输入流为OutputStream(字节输出流)和Writer(字符输出流),输入流为InputStream(字节输入流)和Reader(字符输入流),这四大类均为抽象类(Abstract Class),其各自的子类全部存放在java.io包中,它们协同完成了Java对数据的操作。
OutputStream与其子类的层次结构
OutputStream是所有字节输出流的超类,其处理的是一串串二进制数据,与InputStream(字节输入流)通过byte数组传递二进制数据。我们通过一个简单地实例了解一下流在数据操作中过程。
/* 实现功能:将与java文件同目录下的in.txt中内容复制到out.txt中 */ import java.io.*; class IODemo { public static void main(String[] args) { FileInputStream input = null; FileOutputStream output = null; try { File in = new File("in.txt"); if(!in.exists()) throw new FileNotFoundException("文件in.txt不存在"); //若in.txt不存在,则抛异常退出程序 input = new FileInputStream(in); //指定输入流的源 output = new FileOutputStream("out.txt", true); //指定输出流的目标 int len; byte buff[] = new byte[4]; while((len=input.read(buff)) != -1) { //输出流将文件内容读入buff数组中,并返回读入字节总数 output.write(buff, 0, len); //将buff数组中从0开始len个字节写入输出流中 } input.close(); //关闭I/O流 output.close(); } catch(FileNotFoundException e) { //对可能抛出的异常进行预处理 e.printStackTrace(); } catch(IOException e) { e.printStackTrace(); } catch(NullPointerException e) { e.printStackTrace(); } catch(Exception e) { e.printStackTrace(); } } }
从上面代码中可以看到input输入流先将一定长度的文件内容写入在buff数组中,而后经输出流读取同样长度的字节写入到写入目标中,就这样完成了一次IO。有一点需要注意下,每个汉字字符占用两个字节,在截取操作的时候一定要做好判断是否为一个字符的二进制形式结尾,否则会出现我们常说的乱码。
缓存是IO的一种性能优化。缓存流为IO流增加了内存缓冲区。有了缓存区,使得在流上执行skip() mark() reset()方法都成为可能。在使用缓存输出流时要注意数据并没有立刻被写入至流中,而是首先进入缓存区。如果想立刻将缓存区中数据写入输出流中,一定要调用flush方法。flush方法就是用于即使缓冲区没有满的情况下,也将缓冲区的内容强制写入到输出目标中,习惯称之为刷新。该方法只对使用缓存区的OutputStream类的子类生效,当调用close方法时,系统在关闭流之前,也会将缓存区中信息刷新到输出目标中。