尽管可以通过不同的方式组合I/O流泪,但可能也就只用到其中的几种组合。下面的例子可以作为典型的I/O流用法的基本参考,这些示例中异常处理简化为简单的抛出。
1、缓冲输入文件
如果想要打开一个文件用于字符输入,可以使用以String或File对象作为文件名的FileInputReader,为了提高速度,对那个文件进行缓冲,可将产生的引用传给一个BufferedReader构造器。当readLine()返回null时,就达到了文件的末尾。
- import java.io.BufferedReader;
- import java.io.FileReader;
- import java.io.IOException;
- public class BufferedInputFile {
- public static String read(String filename) throws IOException {
- BufferedReader in = new BufferedReader(new FileReader(filename));
- String s;
- StringBuilder sb = new StringBuilder();
- while ((s = in.readLine()) != null) {
- sb.append(s+"\n");
- }
- in.close();
- return sb.toString();
- }
- public static void main(String[] args) throws IOException {
- System.out.print(read("BufferedInputFile.java"));
- }
- }
2、从内存输入
- import java.io.*;
- public class MemoryInput {
- public static void main(String[] args) throws IOException {
- StringReader in = new StringReader(read("MemoryInput.java"));
- int c;
- while ((c = in.read()) != -1)
- System.out.print((char) c);
- }
- public static String read(String filename) throws IOException {
- BufferedReader in = new BufferedReader(new FileReader(filename));
- String s;
- StringBuilder sb = new StringBuilder();
- while ((s = in.readLine()) != null) {
- sb.append(s + "\n");
- }
- in.close();
- return sb.toString();
- }
- }
3、格式化的内存输入
要读取格式化数据,可以使用DataInputStream,它是一个面向字节的I/O类,因此必须使用InputStream类而不是Reader类。当然,可以用InputStream以字节形式读取任何数据(例如一个文件),不过这里使用的是字符串。
- import java.io.*;
- public class FormattedMemoryInput {
- public static String read(String filename) throws IOException {
- BufferedReader in = new BufferedReader(new FileReader(filename));
- String s;
- StringBuilder sb = new StringBuilder();
- while ((s = in.readLine()) != null) {
- sb.append(s + "\n");
- }
- in.close();
- return sb.toString();
- }
- public static void main(String[] args) throws IOException{
- try {
- DataInputStream in = new DataInputStream(new ByteArrayInputStream(read("FormattedMemoryInput.java").getBytes()));
- while (true) {
- System.out.print((char)in.readByte());
- }
- } catch (EOFException e) {
- System.err.println("End of stream");
- }
- }
- }
- import java.io.*;
- public class FormattedMemoryInput {
- public static String read(String filename) throws IOException {
- BufferedReader in = new BufferedReader(new FileReader(filename));
- String s;
- StringBuilder sb = new StringBuilder();
- while ((s = in.readLine()) != null) {
- sb.append(s + "\n");
- }
- in.close();
- return sb.toString();
- }
- public static void main(String[] args) throws IOException{
- try {
- DataInputStream in = new DataInputStream(new ByteArrayInputStream(read("FormattedMemoryInput.java").getBytes()));
- while (in.available() != 0) {
- System.out.print((char)in.readByte());
- }
- } catch (EOFException e) {
- System.err.println("End of stream");
- }
- }
- }
也可以通过异常捕获来检测输入的末尾。但是,使用异常进行流控制,被认为是对异常特性的错误使用。
4、基本的文件输出
FileWriter对象可以向文件写入数据。首先,创建一个与指定文件连接的FileWriter,实际上通常会用BufferedWriter将其包装起来用以缓冲输出,本例中为了提供格式化机制,它被装饰成PrintWriter。按照这种方式创建的数据文件可作为普通文本文件读取。
- import java.io.*;
- public class BasicFileOutput {
- public static String read(String filename) throws IOException {
- BufferedReader in = new BufferedReader(new FileReader(filename));
- String s;
- StringBuilder sb = new StringBuilder();
- while ((s = in.readLine()) != null) {
- sb.append(s + "\n");
- }
- in.close();
- return sb.toString();
- }
- static String file = "BasicFileOutput.out";
- public static void main(String[] args) throws IOException {
- BufferedReader in = new BufferedReader(new StringReader(read("BasicFileOutput.java")));
- PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(file)));
- int lineCount = 1;
- String s;
- while ((s = in.readLine()) != null) {
- out.println(lineCount++ + ": "+s);
- }
- out.close();
- System.out.println(read(file));
- }
- }
Java SE5在PrintWriter中添加了一个辅助构造器,使得不必每次希望创建文本文件并向其中写入时,都去执行所有的装饰工作,如下例所示:
- import java.io.*;
- public class FileOutputShortcut {
- public static String read(String filename) throws IOException {
- BufferedReader in = new BufferedReader(new FileReader(filename));
- String s;
- StringBuilder sb = new StringBuilder();
- while ((s = in.readLine()) != null) {
- sb.append(s + "\n");
- }
- in.close();
- return sb.toString();
- }
- static String file = "FileOutputShortcut.out";
- public static void main(String[] args) throws IOException {
- BufferedReader in = new BufferedReader(new StringReader(read("FileOutputShortcut.java")));
- // Here's the shortcut:
- PrintWriter out = new PrintWriter(file);
- int lineCount = 1;
- String s;
- while ((s = in.readLine()) != null)
- out.println(lineCount++ + ": " + s);
- out.close();
- // Show the stored file:
- System.out.println(BufferedInputFile.read(file));
- }
- }
5、存储和恢复数据
PrintWriter可以对数据进行格式化,以便人们阅读。但是为了输出可供另一个“流”恢复的数据,需要用DataOutputStream写入数据,并用DataInputStream恢复数据。注意DataOutputStream和DataInputStream是面向字节的,因此要使用InputStream和OutputStream。- import java.io.*;
- public class StoringAndRecoveringData {
- public static void main(String[] args) throws IOException {
- DataOutputStream out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream("Data.txt")));
- out.writeDouble(3.1415926);
- out.writeUTF("That was pi");
- out.writeDouble(1.41413);
- out.writeUTF("Square root of 2");
- out.close();
- DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream("Data.txt")));
- System.out.println(in.readDouble());
- System.out.println(in.readUTF());
- System.out.println(in.readDouble());
- System.out.println(in.readUTF());
- }
- }
6、读写随机访问文件
使用RandomAccessFile,类似于组合使用了DataInputStream和DataOutputStream(因为它实现了相同接口)。利用seek()可以在文件中到处移动,并修改文件中的某个值。在使用RandomAccessFile时,必须知道文件排版,这样才能正确地操作它。RandomAccessFile拥有读取基本类型和UTF-8字符串的各种具体方法。下面是示例:- import java.io.*;
- public class UsingRandomAccessFile {
- static String file = "rtest.dat";
- static void display() throws IOException{
- RandomAccessFile rf = new RandomAccessFile(file, "r");
- for (int i = 0; i < 7; i++) {
- System.out.println("Value "+ i +": "+rf.readDouble());
- }
- System.out.println(rf.readUTF());
- rf.close();
- }
- public static void main(String[] args) throws IOException {
- RandomAccessFile rf = new RandomAccessFile(file, "rw");
- for (int i = 0; i < 7; i++) {
- rf.writeDouble(i*1.414);
- }
- rf.writeUTF("The end of the file");
- rf.close();
- display();
- rf = new RandomAccessFile(file, "rw");
- rf.seek(5*8);
- rf.writeDouble(47.0001);
- rf.close();
- display();
- }
- }
7、文件读写的实用工具
- import java.io.*;
- import java.util.ArrayList;
- import java.util.Arrays;
- import java.util.Collections;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- import java.util.TreeSet;
- public class TextFile extends ArrayList<String> {
- /**
- * Read a file as a single string
- * @param fileName
- * @return
- * @throws IOException
- */
- public static String read(String fileName) throws IOException {
- StringBuilder sb = new StringBuilder();
- BufferedReader in = new BufferedReader(new FileReader(new File(fileName).getAbsoluteFile()));
- try {
- String s;
- while ((s = in.readLine()) != null) {
- sb.append(s);
- sb.append("\n");
- }
- } finally {
- in.close();
- }
- return sb.toString();
- }
- /**
- * Write a single file
- * @param fileName
- * @param text
- * @throws IOException
- */
- public static void write(String fileName,String text) throws IOException {
- PrintWriter out = new PrintWriter(new File(fileName).getAbsoluteFile());
- try{
- out.print(text);
- } finally{
- out.close();
- }
- }
- /**
- * Read a file ,split by any regular expression
- * @param fileName
- * @param splitter
- * @throws IOException
- */
- public TextFile(String fileName,String splitter) throws IOException{
- super(Arrays.asList(read(fileName).split(splitter)));
- if (get(0).equals("")) {
- remove(0);
- }
- }
- public TextFile(String fileName) throws IOException{
- this(fileName, "\n");
- }
- public void write(String fileName) throws IOException {
- PrintWriter out = new PrintWriter(new File(fileName).getAbsoluteFile());
- try{
- for (String item:this) {
- out.println(item);
- }
- } finally{
- out.close();
- }
- }
- /**
- *
- * @param args
- * @throws IOException
- */
- public static void main(String[] args) throws IOException {
- String fileName = "TextFile.java";
- String file = read(fileName);
- write("test.txt", file);
- TextFile text = new TextFile("test.txt");
- text.write("test2.txt");
- TreeSet<String> words = new TreeSet<String>(new TextFile(fileName, "\\W+"));
- System.out.println(words.headSet("a"));
- //下面代码可以统计文档里各个字母出现的次数
- TextFile text2 = new TextFile(fileName,"\\W+");
- Map<Character, Integer> charsStat = new HashMap<Character, Integer>();
- for (String word:text2) {
- for (int i = 0; i < word.length(); i++) {
- Character ch = word.charAt(i);
- Integer freq = charsStat.get(ch);
- charsStat.put(ch, freq == null ? 1:freq+1);
- }
- }
- List<Character> keys = Arrays.asList(charsStat.keySet().toArray(new Character[0]));
- Collections.sort(keys);
- for (Character key:keys) {
- System.out.println(key +" =>"+charsStat.get(key));
- }
- }
- }
- import java.io.*;
- public class BinaryFile {
- public static byte[] read(File bFile) throws IOException{
- BufferedInputStream bf = new BufferedInputStream(
- new FileInputStream(bFile));
- try {
- byte[] data = new byte[bf.available()];
- bf.read(data);
- return data;
- } finally {
- bf.close();
- }
- }
- public static byte[]
- read(String bFile) throws IOException {
- return read(new File(bFile).getAbsoluteFile());
- }
- }