理解 IO 先要知道计算机对数据的输入输出是怎么处理的,下面一张图可以大致理解:
可以看出所谓输入是外部数据向 CPU 输入,而输出是 CPU 将数据输出到我们可见的地方,例如文件、屏幕等。而计算机通常是通过流来传递数据。
Java 中的 IO 包中的类可以处理不同类型的流,例如:字节流 (byte[])、字符流(character)、文件流、对象流等。
java.io 中的抽象类:
基本的字符输入流的类结构如下,每个类的作用从类名大致可以猜出:
这里想强调的是出现的设计模式————装饰器模式:
例如其中 BufferedReader 是对 Reader 接口的其他子类的一个装饰器,封装了其他 Reader 接口实现类,提供更方便的方法调用。
BufferedReader 的构造器如下,初始化时需要传入一个对 Reader 接口的实现类的对象:
- public BufferedReader(Reader in ){}
实例代码,读取指定路径的文件内容并输出:
- public class ReaderTest {
- public static String read(String path) throws IOException {
- //装饰器模式,BufferedReader包装了FileReader
- BufferedReader reader = new BufferedReader(new FileReader(path));
- String s;
- StringBuilder sb = new StringBuilder();
- while ((s = reader.readLine()) != null) {
- sb.append(s + "\n");
- }
- reader.close();
- return sb.toString();
- }
- public static void main(String[] args) throws IOException {
- System.out.println(read("D:/test.txt"));
- }
- }
可以看出 BufferedReader 封装了 FileReader 来提供更方便的文件输入功能。
类比输出流,输出流很容易理解,类关系如下:
同样也用到了装饰器模式,下面直接用代码来说明问题,这段代码目的是将 in.txt 的内容写到 out.txt 中:
- public class WriterTest {
- public static void main(String[] args) throws IOException {
- String inFile = "D:/in.txt";
- String outFile = "D:/out.txt";
- BufferedReader in =new BufferedReader(new StringReader(ReaderTest.read(inFile)));
- PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(outFile)));
- String s;
- int line = 1;
- while ((s = in.readLine()) != null) {
- out.println(line+++":" + s);
- } in .close();
- out.close();
- System.out.println(ReaderTest.read(outFile));
- }
- }
我们可以看出 BufferedReader 封装了 StringReader,BufferedWriter 封装了 FileWriter。
字符流就说这么多吧,具体的类用的时候再去了解也不迟。
InputStream 是以字节流来读取文件的,如果文件是图片或二进制等格式,则不能以字符流来读,需要 InputStream 来读取。
InputStream 的子类关系如下图:
值得注意的是,字节流也可以转换成字节流,利用的是 InputStreamReader 类,该类封装了 InputStream。下面的实例代码通过两种不同的方式来读取文件内容。其中 readByStream 是通过字节流,而 readByReader 是字符流。
- public class InputStreamTest {
- public static void readByStream(String path) {
- File f = new File(path);
- try {
- InputStream in =new FileInputStream(f);
- int b;
- while ((b = in.read()) != -1) {
- char c = (char) b;
- System.out.printf("%c", c);
- }
- } catch(FileNotFoundException e) {
- e.printStackTrace();
- } catch(IOException e) {
- e.printStackTrace();
- }
- }
- public static void readByReader(String path) {
- File f = new File(path);
- try {
- InputStream in =new FileInputStream(f);
- BufferedReader reader = new BufferedReader(new InputStreamReader( in , "utf-8"));
- String string;
- StringBuilder sb = new StringBuilder();
- while ((string = reader.readLine()) != null) {
- sb.append(string);
- }
- System.out.println(sb.toString());
- } catch(FileNotFoundException e) {
- e.printStackTrace();
- } catch(IOException e) {
- e.printStackTrace();
- }
- }
- public static void main(String[] args) {
- String path = "D:/test.txt";
- readByReader(path);
- readByStream(path);
- }
- }
另外,值得注意的是,如果要读取中文,建议使用字符流,因为一个汉字占两个字节,而 InputStream 每次只会读取一个字节,因此会乱码。而 InputStreamReader 有一个构造函数可以设置文件编码,如上述代码中的 new InputStreamReader(in,"utf-8") 指定了文件编码问 utf-8,因此可以很好的解决中文乱码问题。
输出流 OutputStream 的作用类比于 Writer,也非常容易理解,即通过字节流来把数据输出到文件、磁盘等设备中。关系如下图。
同 InputStream 一样,也有一个 OutputStreamWriter 包装了 OutputStream,代码很简单我就不举例了。
上面这两大类 IO,虽然结构清晰,但是多少还是复杂了点,于是乎,Java 封装了一个文件随机存取类————RandomAccessFile。
RandomAccessFile 实现了两个接口,DataInput 和 DataOutput,因此它同时拥有读和写两个功能,方便了我们的使用。使用时需要指定打开文件的模式,可以是 "r" 只读,"rw" 读写等。下面是实例代码:
- public class RandomAccessTest {
- public static void main(String[] args) {
- String filePath = "D:" + File.separator + "test.txt";
- File f = new File(filePath);
- try {
- RandomAccessFile write = new RandomAccessFile(f, "rw");
- String str = "abc, hello, randomAccess!";
- //把byte[]中的字节写入文件
- write.write(str.getBytes());
- System.out.println("写入文件完成...");
- RandomAccessFile read = new RandomAccessFile(f, "rw");
- String strRead;
- StringBuilder sb = new StringBuilder();
- while ((strRead = read.readLine()) != null) {
- sb.append(strRead);
- }
- System.out.println("读取文件内容:" + sb.toString());
- } catch(FileNotFoundException e) {
- e.printStackTrace();
- } catch(IOException e) {
- e.printStackTrace();
- }
- }
- }
来源: http://www.cnblogs.com/puyangsky/p/5785637.html