Java输入输出(二)——具体操作
文本输入输出
进行文本输出的类是PrintWriter,这个类提供格式化输出字符的功能,它是Writer的子类。类似于System.out的使用,PrintWriter的实例提供了很多类似的输出功能。System.out是PrintStream的实例,PrintStream是OutputStream的子类,因此System.out与PrintWriter的实例处于同等位置,因此具有类似的操作。所不同的是System.out负责字节流输出,而PrintWriter负责字符流输出。
PrintWriter输出的目的地可以是任何地方,主要取决于与PrintWriter绑定的输出流是什么。
利用PrintWriter输出到文件:
PrintWriter out=new PrintWriter(new FileWriter(“file.txt”));
利用PrintWriter输出到标准输出(屏幕):
PrintWriter out=new PrintWriter(System.out);
//PrintWriter有一个以OutputStream对象为参数的构造器
另外还可以可用流过滤器的组合功能来实现其他的功能,例如加入BufferdWriter来加入缓存机制等。
文本的读入功能有许多实现方法,例如使用Scanner实例来绑定System.in来实现标准输入的读取。使用BufferedReader绑定一个文件进行读取:
BufferedReader br=new BufferedReader(new InputStreamReader(new FileInputStream(“file.txt”)));
同样,Scanner也可以读取文件,BufferedReader也可以读取标准输入,这些功能的实现主要利用了流过滤器的功能,不同的是Scanner可以读取数字,BufferedReader只能读取字符串。
二进制输入输出
负责写入读取二进制的类主要是DataInputStream和DataoutputStream。这两个类分别实现了DataInput和DataOutput接口。直接读写二进制可以直接将java基本数据类型读入和写出。写入是直接将数据转换为二进制形式保存,读取则是反向操作。例如保存数字1234,文本写入是将其分为4个字符写入,而二进制直接将数字1234的二进制形式写入。这样相对于文本处理速度更快,效率更高。
对象流与序列化
Java语言支持一种称为对象序列化(object serialization)的非常通用的机制,它可以将任何对象写出到流中,并在之后将其读回。这种机制特别适合应用到分布式环境下传递对象的操作。要实现对象可以被序列化的操作,对象所属的类需要实现序列化接口,即Serializable接口,这种接口中没有任何方法。这一点与Cloneable接口类似,但是为了实现克隆,需要在类中覆盖Object类中的clone方法。
为了实现对象流的输入输出,需要使用到ObjectInputStream类和ObjectOutputStream类。使用方法如下:
ObjectOutputStream out=new ObjectOutputStream(new FileOutputStream(“employee.data”));
Employee harry=new Employee();
Manager boss=new Manager();
out.write(harry);
out.write(boss);
当需要恢复对象是,使用ObjectInputStream类,使用方法如下:
ObjectInputStream in=new ObjectInputStream(new FileInputSream(“employee.data”));
Employee e1=(Employee)in.readObject();
Employee e2=(Employee)in.readObject();
在序列化对象的情况下,有一种情况是多个对象引用了同一个对象,此时序列化技术在将对象保存时不是将同一个对象保存多次,而是使用了一个称为序列号的编号来指向同一个对象的,相同的对象只保存一次。
操作文件
在java的文件I/O中,除了流处理之外,还有对文件和目录的处理,即对磁盘文件的操作。在JAVA 7之前的版本中,提供了File类来处理这些操作。在JAVA 7之后提供了Path和Files类来对文件进行操作。Path表示文件或者目录的目录结构。Files提供了很多操作文件的方法,比如文件的移动删除拷贝等方法。同时Files中也提供了可以直接处理文件内容的操作,类似于
Files.newInputStream(path);
Files.newOutputStream(path);
Files.newBufferedReader(path,charset);
Files.newBufferedWriter(path,charset);
这些操作可以使用户避免陷入处理各种流处理的情况。另外,Files提供了迭代目录中的文件的方法,walkFileTree,在使用这个方法的时候需要向其中传递一个FileVisitor类型的对象。这个对象中的方法在遇到特定的情况下可以被调用。
内存映射文件
大多数操作系统都可以利用虚拟内存技术将一个文件或者文件的一部分映射到内存中,这样就可以将文件当做内存中的数组一样访问,加快了文件访问的速度。
Java中提供了一个抽象类Buffer来与文件进行内存映射。具体的有ByteBuffer,CharBuffer等类可以来实际使用。要使用内存映射机制,需要使用FileChannel类来打开一个通道(Channel),通道是磁盘文件的一个抽象,利用通道可以访问诸如内存映射,文件加锁机制以及文件间快速数据传递等操作系统特性(具体需要操作系统的支持)。
内存映射的使用方法:
FileChannel channel=FileChannel.open(path,options);
MappedByteBuffer buffer =channel.map(FileChannel.MapMode.READ_ONlY,0,length);
正则表达式
正则表达式是一种处理字符串的机制,可以通过描述一种模式来与字符串进行匹配。关于正则表达式这里不详细描述,这里主要描述java中正则表达式的使用:
Pattern pattern=Pattern.compile(pattern);
Matcher matcher=pattern.matcher(input);
Matcher.matchs()返回true用来表示输入字符串匹配了要求的模式,Matcher.find()返回true用来表示输入字符串中有满足模式匹配的子字符串。其中input可以是任意实现了CharSequence接口的类的对象,例如String,StringBuilder,CharBuffer等。
Matcher类提供start和end方法,用来返回匹配的子字符串在输入字符串中的位置。类似于迭代器的使用,使用这两个方法获取下一个匹配子字符串时需要使用一次find()方法。