JAVAI/O流

一. I/O流概述

   输入输出处理是程序设计中非常重要的一部分,从键盘中读数据或从文件中读写数据等等。

     java把这些不同类型的输入、输出源抽象为流(stream),用统一接口来表示,从而使程序简单明了。

I/O中的Exception

  进行I/O操作时可能会产生I/O例外,属于非运行时例外,应该在程序中处理。  

  如:FileNotFoundException, EOFException, IOException

java.io包中有关文件处理包括:

            类:File、FileInputStream、FileOutputStream、RamdomAccessFile和FileDescription

                接口:FilenameFilter

1. 字节流:

  从InputStream和OutputStream派生出来的一系列类,以字节(byte)为基本处理单位

2. 字符流:

  从Reader和Writer派生出来的一系列类,以16位的Unicode码表示的字符为基本处理单位

3. 对象流:

  ObjectInputStream、ObjectOutputStream

4. 其他

     文件处理:

    文件处理:

      File、RandomAccessFIle

    接口:

      DataInput、DataOutput、ObjectInput、ObjectOutput

二. 文件描述

  类File:并不代表磁盘上的文件,可以理解为文件的路径,但是比String形式的路径更为安全。

  1)文件或目录的生成

    public File(String path); // 如果path是路径,则该File对象表示的是目录;如果path是文件名,则该表示的是文件

    public File(String path, String name); // path是路径名,name是文件名

    public File(File dir, String name); // dir是路径名,name是文件名

  2)文件名的处理

    String getName(); // 得到一个文件的名称(不包括路径)

    String getPath(); // 得到一个文件的路径名

    String getAbsolutePath(); // 得到一个文件的绝对路径名

    String getParent(); // 得到一个文件的上一级目录名

    String renameTo(File newName); // 将当前文件名更名为给定文件的完整路径

  3)文件属性测试

    boolean exists(); // 测试当前FIle对象所指示的文件是否存在

    boolean canWrite(); // 测试当前文件是否可写

    boolean canRead(); // 测试当前文件是否可读

    boolean isFile(); // 测试当前文件是否是文件

    boolean isDirectory; //  测试当前文件是否是目录

  4)普通文件信息和工具

    long lastModified(); // 得到文件最近一次修改的时间

    long length(); // 得到文件的长度,以字节为单位

    boolean delete(); // 删除当前文件

  5)目录操作

    boolean mkdir(); // 根据当前对象生成以一个由该对象指定的路径

    String list(); // 列出当前目录下的文件。

           // File假如是一个Directory,可以通过list()方法得到这个目录下所有的文件和目录的名称数组。

          // 一种是没有参数,一种是实现FilenameFilter接口的参数。

   

     FilenameFilter接口,能够过滤得到指定类型的文件或者目录,其中必须重写accept(File file,String path)方法

eg: 列出C:\MyProjects下后缀为.java的文件

 1 import java.io.*;
2
3 public class FileFilterTest {
4 public static void main(String args[]) {
5 File dir = new File("C://MyProjects"); // 用File对象表示一个目录
6 Filter filter = new Filter("java"); // 生成一个名为java的过滤器
7 System.out.println("list java files in directory" + dir);
8
9 String files[] = dir.list(filter); // 列出目录dir下,文件名后缀名为java的所有文件
10
11 for (int i = 0; i < files.length; i++) {
12 File f = new File(dir, files[i]); // 为目录dir下的文件或目录创建一个File对象
13 if (f.isFile())
14 System.out.println("file " + f);
15 else
16 System.out.println("sub dirctory " + f);
17 }
18 }
19 }
20
21 class Filter implements FilenameFilter { // 必须重写accept(File file,String path)方法
22 String extent;
23
24 Filter(String extent) {
25 this.extent = extent;
26 }
27
28 public boolean accept(File dir, String name) {
29 return name.endsWith("." + extent); //返回文件的后缀名
30 }
31 }

 

二. I/O流详述

1. 字节流

InputStream类

  a) 从流中个读取数据

    int read(); // 读取一个字节,返回实际所读字节

    int read(byte b[]); // 读取字节数为b的长度,并存放在字节数组b中,返回值为实际读取的字节的数量

    int read(byte b[], int off, int len); // 读取len个字节,放置在以下标off开始的字节数组b中,返回值为实际读取的字节的数量

    int available(); // 返回值为流中尚未读取的字节的数量

    long skip(long n); // 读指针跳过n个字节不读,返回值为实际跳过的字节数量

  b) 关闭流:

    close(); // 流操作完毕后必须关闭

  c) 使用输入流中的标记:

    void mark(int readlimit); // 记录当前读指针所在位置,readlimit表示读指针读出readlimit个字节后标记的指针位置才失效

    void reset(); // 把读指针重新指向用mark方法所记录的位置

    boolean markSupported(); // 当前的流是否支持读指针的记录功能

OutputStream类

  a) 输出数据:

    void write(int b); // 往流中写一个字节b

    void write(byte b[]); // 往流中写一个字节数组b

    void write(byte b[], int off, int len); // 把字节数组b中下标off开始,长度为len的字节写入流中

    flush(); // 刷空输出流,并输出所有被缓存的字节,由于某些流支持缓存的功能,该方法将把缓存中所有内容强制输出到流中

  b) 关闭流:

    close(); // 流操作完毕后必须关闭

过滤流(包装流)

  过滤流在读写数据的同时可以对数据进行处理,它提供了同步机制,使得某一时刻只有一个线程可以访问一个I/O流

  防止多个线程同时对一个I/O流进行操作带来的意想不到的结果。

  类FilterInputStream和FilterOutputStream分别作为所有过滤输入流和输出流的父类

   a) 使用过滤流的步骤:

    连接到某个输入输出流上,通过在构造方法的参数中指定所要连接的输入输出流上来实现

    FilterInputStream(InputStream in);

    FilterOutputStream(OutputStream out);

   b) 几种常见的过滤流

    BufferedInputStream和BufferedOutputStream 缓冲流,用于提高输入输出处理的效率

    DataInputStream和DataOutputStream 不仅能读写数据流,而且读写各种java语言的基本类型

    LineNumberInputStream 除了对输入处理的支持外,可以记录当前的行号

    PushbackInputStream 提供了一个方法可以把刚读的字节退回到输入流中,以便重新再读一遍

    PrintStream 打印流的作用是吧java语言的内构类型以其字符表示形式动到相应的输出流

2. 字符流

字符流的处理

  java提供16位Unicode码表示的字符流的类,即以Reader和Writer为基类派生出的一系列类

  Reader和Writer:这两个类是抽象类,只是提供了一系列用于字符流处理的接口,不能生成实例。

Reader类:是处理所有字符流输入类的父类

  a) 读取字符

    public int read() throws IOException; // 读取一个字符,返回值为读取的字符

    public int read(char cbuf[]) throws IOException; // 读取一系列字符到cbuf数组,返回值为实际读取的字符数量

    public abstract int read(char cbuf[], int off, int len) throws IOException; // 读取len个字符,存入off开始的cbuf中,返回实际读取的    // 的字数,必须由子类实现

   b) 标记流

    public boolean markSupported(); // 判断当前流是否支持做标记

    public void mark(int readAheadLimit) throws IOException; // 给当前流作标记,最多支持readAheadLimit个字符的回溯

    public void reset() throws IOException; // 将当前流重置到做标记处

  c) 关闭流

    public abstract void close() throws IOExeption;

Writer类:是处理所有字符流输出类的父类

  a) 向输出流写入字符

    public void write(int c) throws IOException; // 将整型值c的低16位写入输出流

    public void write(char cbuf[]) throws IOException; // 将cbuf数组写入输出流

    public abstract void write(char cbuf[], int off, int len); // 将字符数组cbuf中的从索引off开始的len个字符写入输出流

    public void write(String str) throws IOException; // 将字符串str中的字符写入输出流

    public void write(String str, int off, int len) throws IOException; // 将字符串str中从索引off开始处的len个字符写入输出流

    flush() 刷空输出流,并输出所有被缓冲的字节

  b) 关闭流

    public abstract void close() throws IOException;

java.io包中用于处理字符流的最基本的类:InputStreamReader OutputStreamWriter,此外还有FileReader和FileWriter

  a) 生成流对象

      public InputStreamReader(InputStream in); // in是字节流,即将字节流转换成字符流来处理

      public InputStreamReader(InputStream in, String enc) throws UnsupportedEncodingExceptio; // enc是编码方式:ISO8859-1,UTF-8,UTF-16

      public OutputStreamWriter(OutputStream out); // out是字节流

      public OutputStreamWriter(OutputStream out, String enc) throws UnsupportedEncodingException; // enc是编码方式

  b) 读写字符

    基本与Reader和Writer一致

  c) 获取当前编码方式

    public String getEncoding();

  d) 关闭流

    public void close() throws IOException;

BufferedReader和BufferedWriter

  a) 生成流对象

    public BufferedReader(Reader in); 

    public BufferedReader(Reader in, int sz); // sz为缓冲区的大小

    public BufferedWriter(Writer out); 

    public BufferedWriter(Writer out, int sz); 

  b) 读写字符

    增加对整行字符的处理

    public String readline() throws IOException; // 读一行字符

    public void newLine() throws IOException; // 写一行字符

   

 1 // 从键盘读入数字,并输出
2 import java.io.*;
3
4 public class NumberInput {
5 public static void main(String args[]) {
6 try {
7 InputStreamReader ir;
8 BufferedReader in;
9 ir = new InputStreamReader(System.in);
10 // 从键盘接受一个字符串的输入,并创建了一个字符输入流的对象
11 in = new BufferedReader(ir); // 用字符输入流ir创建一个BufferedReader对象
12 String s = in.readLine(); // 从输入流in中读入一行
13 System.out.println("Input value is: " + s);
14 int i = Integer.parseInt(s); // 转换成int
15 i *= 2;
16 System.out.println("Input value changed after doubled: " + i);
17 }
18 catch (IOException e) {
19 System.out.println(e);
20 }
21 }
22 }

3. 对象流

  串行

    对象通过描述自己状态的数值来记录自己,这个过程叫对象的串行化(Serialization)

    a) 串行化方法:

      java.io包中,接口Serializable用来作为对象串行化的工具,只有实现了Serializable的对象才可以被串行化

      串行化步骤:

 1         1. 定义一个可串行化的对象
 2 
 3           public class Student implements Serializable {...}
 4 
 5         2. 通过ObjectInputStream和ObjectOutputStream这两个对象流存取可串行化对象
 6 
 7           Student stu = new Student();
 8 
 9           FileOutputStream fo = new FileOutputStream("data.ser");
10 
11           ObjectOutputStream so = new ObjectOutputStream(fo);
12 
13           try {
14 
15             so.writeObject(stu);
16 
17             so.close();
18 
19           } catch (IOException e) {
20 
21             System.out.println(e);
22 
23           }
24 
25           FileInputStream fi = new FileInputStream("data.ser");
26 
27           ObjectInputStream si = new ObjectInputStream(fi);
28 
29           try {
30 
31             stu = (student)si.readObject();
32 
33             si.close();
34 
35           } catch (IOException e) {
36 
37             System.out.println(e);
38 
39           }        

注意事项:

1. 只能保存非静态成员变量,不能保存任何成员方法和静态成员变量,保存的只是变量的值,对于变量的任何修饰符都无法保存

2. transient关键字,对于某些瞬时对象(Thread对象,FileInputStream对象),无法保存,必须用transient关键字表明

3. 定制串行化,缺省机制为按名称升序,想定制就要重写writeObject()和readObject()

4. 其他常用的流

管道流

  用来把一个程序、线程或代码块的输出连接到另一个程序、线程或代码块的输入

  在使用管道前,管道输出流和管道输入流必须进行连接。

  a) 构造方法连接

    PipedInputStream(PipedOutputstream src);

    PipedOutputStream(PipedInputStream snk);

  b) connect方法进行连接

    类PipedInputStream中定义为:

    void connect(PipedOutputSream src);

    类PipedOutputStream中定义为:

      void connect(PipedInputSream snk);

小结: 

字节流:

  抽象类 InputStream OutputStream
  跟数据源直接接触的类: FileInputStream FileOutputStream
  装饰类: BufferedInputStream: 提供了缓冲功能 BufferedOutputStream: 提供缓冲功能

  重要方法:
    read();
    read(byte[] b);
    read(byte[] b, int off, int len);

    write(int b);
    write(byte[] b);
    write(byte[] b, int off, int len);

字符流:

  抽象类 Reader Writer
  跟数据源直接接触的类 FileReader FileWriter
  装饰类 BufferedReader: 缓冲,readLine() BufferedWriter: 缓冲

  重要方法:
    read(char[] cbuf);
    read(char[] cbuf, int off, int len);
    read(CharBuffer target);

    write(char[] cbuf);
    write(char[] cbuf, int off, int len);
    write(int c);
    write(String str);
    write(String str, int off, int len);

对象流
  需要被序列化的对象必须实现Serializable接口
  调用ObjectOutputStream的writeObject()方法,通过装饰FileOutputstream
  调用ObjectInputStream的readObject()方法,通过装饰FileInputStream

原文地址:https://www.cnblogs.com/forstudy/p/2436643.html