首页 > 代码库 > JAVA I/O系统

JAVA I/O系统

概述

对于使用过java提供了I/O来说的程序员来说,可能对其提供的api又爱又恨,爱的是java本身封装了很多功能强大的输入输出流给开发者使用,恨的是一开始开发者可能会对Java I/O系统提供了如此多的类而不知所措。本文就简要的介绍一下java的i/o,以供自己复习使用。

特殊的File 类

File类是在java I/O中常用的一个工具类,它可以帮助我们处理文件和文件目录的问题。其实File这个名字有一定的误导性,它既可以表示文件,又可以表示目录。如果其表示的是一个目录,我们就可以调用list()方法来返回文件集合的名称数组或者调用listFile()方法来返回所有的文件。File类还提供了一些常用的属性,比如File.separator表示获取所在系统的路径分隔符、File.pathSeparator表示路径之间的分隔符。但是需要注意的是:File类是针对文件或者目录的相关操作,例如删除、创建、判断文件或者目录是否存在等,但是只通过File类无法访问文件的具体内容,既只通过File既不能从文件中读取数据,也不能写入数据。这里只列出一个使用File类的demo,是有一次面试的面试题,列出指定目录下所有的内容。代码如下:

package com.vino.nio;

import java.io.File;

public class FileDemo {

    public static void main(String[] args) {
        String fileName = "D:" + File.separator;
        File file = new File(fileName);
        printAllFile(file);
    }

    // 打印一个文件下所有的文件,包括目录下的文件
    public static void printAllFile(File file) {
        if (file != null) {
            if (file.isDirectory()) {
                File[] fileArray = file.listFiles();
                if (fileArray != null) {
                    for (int i = 0; i < fileArray.length; i++) {
                        printAllFile(fileArray[i]);
                    }
                }
            } else {
                System.out.println(file);
            }
        }
    }
}

正菜开始

Java类库的I/O类分为输入和输出两部分。通过继承,任何自InputStream或Reader派生而来的类都含有read()这个基本方法,用于读取单个字节或者字节数组。同样,任何自OutputStream或Writer派生儿来的类都含有名为write()的基本方法,用于写单个字节或者字节数组。通常,我们很少使用单一的类来创建流对象,而是通过叠合多个对象来提供所提供的功能。

四种抽象类见下图所示:

  字节流  字符流
输入流 InputStream Reader
输出流 OutputStream Writer

 

 

 

这里先介绍常用的文件流:

文件流是指那些主要用于从文件操作数据源中的流,主要有4种,分别如下所示:

FileInputStream vs FileOutputStream vs FileReader vs FileWriter

FileInputStream:

  • fis.read() 从此输入流中读取一个数据字节。返回:下一个数据字节;如果已到达文件末尾,则返回 -1。 ;
  • fis.read(byte[] b) 从此输入流中将最多 b.length 个字节的数据读入一个 byte 数组中。返回读入缓冲区的字节总数,如果因为已经到达文件末尾而没有更多的数据,则返回 -1。 

Tips:在Unicode编码中,一个英文字符是用一个字节编码的,一个中文字符是2个字节编码的。所以用字节流读取中文时,肯定会出问题。
FileOutputStream:

常用的初始化该类的方式如下:

  • OutputStream ops = new FileOutputStream(File f);
  • OutputStream ops = new FileOutputStream(File f, boolean append);

第二种表示是否是追加写。默认情况下,是不追加写的。

byte[] b = str.getBytes();

  • fos.write(b)  向此输出流中写入b.lenth个字节。
  • fos.write(b[i]) 向此输出流中写入b[i],两者都返回void。

用字节文件输出流往文件中写入的中文字符没有乱码,因为程序先把中文字符转成了字节数组然后再往文件里面写。 另外,向输出流写入数据,还需要在写入操作完成后,调用flush()方法来强制写出所有缓冲的数据。调用close()的时候会调用flush()方法,所以调用close()的时候就相当于调用了flush()方法。

FileReader:

  • fr.read(); // 读取单个字符。返回作为整数读取的字符,如果已达到流末尾,则返回 -1。
  • fr.read(char[] c);//将字符读入数组。返回读取的字符数。如果已经到达尾部,则返回-1。

FileWriter:

同理与FileOutputStream,只是处理的对象是字符流。这里可以直接输入字符串,而不需要你将字符串转化为字节数组。

Writer out =new FileWriter(f);
String str="hello";
out.write(str);
out.close();

Tips:一般来说:FileInputStream vs FileOutputStream类用来操作二进制文件比较合适,如图片,声音,视频等。而FileReader vs FileWriter类用来操作文本比较合适。

 

转换流:

整个IO类中除了字节流和字符流还包括字节和字符转换流。
OutputStreramWriter将输出的字符流转化为字节流
InputStreamReader将输入的字节流转换为字符流
但是不管如何操作,最后都是以字节的形式保存在文件中的。

缓存流:

缓冲流都是过滤流,就是说缓冲流并不直接操作数据源,而是对直接操作数据源的节点流的一个包装。当使用过滤流的过程中,当关闭过滤流,它会自动关闭它所包装的节点流。常见的缓存流有BufferedReader。

BufferedReader只能接受字符流的缓冲区,因为每一个中文需要占据两个字节,所以需要将System.in这个字节输入流变为字符输入流。常见的用法如下:

BufferedReader buf = new BufferedReader(new InputStreamReader(System.in));

Scanner:

还有一个不得不提到的类是:Scanner。

其实在Java里头,我们比较常用的是采用Scanner类来进行数据的输入。具体的用法见下:

package com.vino.nio;

import java.util.Scanner;

public class ScannerDemo {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        // 读一个整数
        int temp = sc.nextInt();
        System.out.println(temp);
        // 读取浮点数
        float flo = sc.nextFloat();
        System.out.println(flo);
        // 读取字符
        // ...等等的,都是一些太基础的,就不师范了。
    }
}

 总结:

本文只是对java i/o的一个简单的总结,涉及到的主要是4中常用的文件流、转换流、缓存流的用法,对于流的高级的用法没有涉及到,博主在日常的开发过程中也没有使用到。另外还要指出的是,本文没有涉及到java的nio,在以后会补充上来。

参考:http://www.cnblogs.com/rollenholt/archive/2011/09/11/2173787.html