Java关于IO流的介绍

JDK提供的流继承了四大类:InputStream(字节输入流)、OutputStream(字节输出流)、Reader(字符输入流)、Writer(字符输出流)。

Java关于IO流的介绍

字符流和字节流的主要区别:
       1.字节流读取的时候,读到一个字节就返回一个字节;  字符流使用了字节流读到一个或多个字节(中文对应的字节数是两个,在UTF-8码表中是3个字节)时。先去查指定的编码表,将查到的字符返回。
       2.字节流可以处理所有类型数据,如:图片,MP3,AVI视频文件,而字符流只能处理字符数据。
   只要是处理纯文本数据,就要优先考虑使用字符流,除此之外都用字节流
详解如下:
一、字节流讲解
  1.用流对文件进行处理
package com.chen.test;

import java.io.*;
/**
 * 
 * @author 陈家小帅
 *
 */
public class TestIO {
    public static void main(String[] args) {
        File file = new File("E:/java.txt");
        if (!file.exists()) {        //先判断该目录文件是否存在
            try {
                //file.mkdirs();  创建该目录下指定的文件夹
                file.createNewFile(); // 当文件不存在时,创建此文件夹
                
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        //file.delete();        //删除指定的文件
        System.out.println("文件名:"+file.getName());
    }
}

 2. InputStream 和 OutputStream 是两个 abstact 类,对于字节为导向的 stream 都扩展这两个基类;

inputStream中的关键方法:

  read():方法是读取一个byte字节,但是返回的是int。
  read(byte[]):一次性读取内容到缓冲字节数组
  read(byte[],int,int):从数据流中的哪个位置offset开始读长度为len的内容到缓冲字节数组
OutputStream中的关键方法
write(int):写入一个字节到stream中
write(byte[])写入一个byte数组到stream中
write(byte[],int,int):把byte数组中从开始处写入长度为len的数据
flush():这个方法是用来刷新stream中的数据,让缓冲区中的数据强制的输出
3.FileInputStream和FileOutputStream
  FileInputStream : 从文件系统中的某个文件中获得输入字节.
Java关于IO流的介绍
  FileOutputStream : 文件输出流是用于将数据写入 FileFileDescriptor 的输出流.
Java关于IO流的介绍
下面是一个例子:
package com.chen.test;

import java.io.*;
/**
 * 
 * @author 陈家小帅
 *
 */
public class Test4 {
    public static void main(String[] args) throws Exception {
        String path1 = "E:/WorkSpace/Mouth/bin/Dest.txt";
        String path2 = "E:/WorkSpace/Mouth/bin/D.txt";
         ReadByFIS(path1, path2);
    }
/**
     * 使用FileInputStream 将一个文件的内容写入到另一个文件中,并在控制台输出
     * 
     * @param path1
     * @param path2
     * @throws Exception
     */
    public static void ReadByFIS(String path1, String path2) throws Exception {
        InputStream in = new FileInputStream(path1);        //创建文件输入流
        OutputStream out = new FileOutputStream(path2);        //创建文件输出流
        byte[] buffer = new byte[1024];                        //定义字节数组
        int len = 0;
        while ((len = in.read(buffer)) > 0) {                //将最多buffer.lenth个字节的数据读入byte数组中
            String s = new String(buffer, 0, len);            //将读入的字节转换成String类型
            System.out.println(s);                            //输出读取到的信息
            out.write(buffer, 0, len);                        //将读取到的信息写入到文件中
        }
        out.close();                    //关闭输入输出流
        in.close();
    }
}
 输出结果如下:
Java关于IO流的介绍
如果想让某个字符串写入到文件中,如下所示:
package com.chen.Two;
import java.io.*;

public class Two {
    // 编写一个Java程序将111,112,113,114,115 这5个数以写入到Dest.txt文件中
    public static void main(String[] args) throws Exception {
        String str = "111,112,113,114,115";            //定义字符串
     FileOutputStream fo = new FileOutputStream("E:/WorkSpace/Mouth/bin/Dest.txt");          //创建文件输出流
        int len = 0 ;
        byte[] buffer = str.getBytes();                //将字符串转换成byte字节
        fo.write(buffer);                                //将字节数组中的数据写出 
        fo.close();
  }
}
4.BufferedInputStream和BufferedOutputStream
  •  BufferedInputStream 为另一个输入流添加一些功能,即缓冲输入以及支持 markreset 方法的能力。
  • 在创建 BufferedInputStream 时,会创建一个内部缓冲区数组。
  • 在读取或跳过流中的字节时,可根据需要从包含的输入流再次填充该内部缓冲区,一次填充多个字节。
  • mark 操作记录输入流中的某个点,reset 操作使得在从包含的输入流中获取新字节之前,再次读取自最后一次 mark 操作后读取的所有字节。
 Java关于IO流的介绍
 BufferedOutputStream 该类实现缓冲的输出流。
通过设置这种输出流,应用程序就可以将各个字节写入底层输出流中,而不必针对每次字节写入调用底层系统。
   Java关于IO流的介绍
 下面讲一个例子:
package com.chen.test;

import java.io.*;
/**
 * 
 * @author 陈家小帅
 *
 */
public class Test4 {
    public static void main(String[] args) throws Exception {
        String path1 = "E:/WorkSpace/Mouth/bin/Dest.txt";
        String path2 = "E:/WorkSpace/Mouth/bin/D.txt";    
        ReadByBIS(path1, path2);
    }
/**
     * 使用BufferInputStream将一个文件的内容写入到另一个文件中,并在控制台输出
     * 
     * @param path1
     * @param path2
     * @throws Exception
     */
    public static void ReadByBIS(String path1, String path2) throws Exception {
        InputStream in = new BufferedInputStream(new FileInputStream(path1));    //创建文件输入流
        OutputStream out = new BufferedOutputStream(new FileOutputStream(path2));    //创建文件输出流
        byte[] buffer = new byte[1024];                    //定义字节数组
        int len = 0;
        while ((len = in.read(buffer)) > 0) {            //将最多buffer.lenth个字节的数据读入byte数组中
            out.write(buffer, 0, len);                    //将读取到的信息写入到文件中
            out.flush();                                // 刷新此缓冲的输出流
            String s = new String(buffer, 0, len);        //将读入的字节转换成String类型
            System.out.println(s);                        //输出读取到的信息
        }                
        in.close();                        //关闭输入输出流
        out.close();
    }
}

 输出结果:

Java关于IO流的介绍

如果大家学过设计模式中的装饰者模式,会很容易发现BufferedinputStreamBufferedOutputStream其实是对FileInputStream和FileOutputStream进行了包装。
为它创建一个内部缓冲区数组,应用程序就可以将各个字节读/写入底层输出流中,而不必针对每次字节读/写入调用底层系统。
 5.读写对象:ObjectInputStream ObjectOutputStream
 该流允许读取或写入用户自定义的类,但是要实现这种功能,被读取和写入的类必须实现Serializable接口,
其实该接口并没有什么方法,可能相当 于一个标记而已,但是确实不合缺少的。
 例子如下:
package com.chen.test;

import java.io.*;
/**
 * 
 * @author 陈家小帅
 *
 */
public class Test4 {
    public static void main(String[] args) throws Exception {
        String path1 = "E:/WorkSpace/Mouth/bin/Dest.txt";
        String path2 = "E:/WorkSpace/Mouth/bin/D.txt";
        ReadbyOnjiect(path2);
    }
public static void ReadbyOnjiect(String path2){
        ObjectInputStream oibs = null;
        ObjectOutputStream oobs = null;
        try {
            oobs = new ObjectOutputStream(new FileOutputStream(path2));
            oobs.writeObject(new Student("张三", 18));
            oobs.writeObject(new Student("李四", 18));
            oibs = new ObjectInputStream( new FileInputStream(path2));
            for(int i=0;i<2;i++){
                System.out.println(oibs.readObject());
            }
        } catch (Exception e) {
            // TODO: handle exception
        }
    oibs.close();
    oobs.close();
} }
//自定义的类实现了Serializable接口,可序列化 class Student implements Serializable{ private String name; private int age; public Student(String name,int age) { this.name = name; this.age = age; } @Override public String toString() { return "Student[name="+name+",age="+age+"]"; } }
 6.读写对象:DataInputStreamDataOutputStream
DataInputStreamDataOutputStream来写入或读出数据。DataInputStream的好处在于在从文件读出数据时,不用费心地自行判断读入字符串时或读入int类型时何时将停止,使用对应的readUTF()和readInt()方法就可以正确地读入完整的类型数据。
下面是一个例 子
package com.chen.test;

import java.io.*;

/**
 * 
 * @author 陈家小帅
 * 
 */
public class Test4 {
    public static void main(String[] args) throws Exception {
        String path1 = "E:/WorkSpace/Mouth/bin/Dest.txt";
        String path2 = "E:/WorkSpace/Mouth/bin/D.txt";
        DataReader(path2);
    }
/**
 * 用DataOutputStream和DataInputStream将类写入到文件中,然后读出
 * @param path1
 */
    public static void DataReader(String path1){
        Student[] student = {
                new Student("zs", 18),
                new Student("ls", 20)};
        try {
            DataOutputStream oups = new DataOutputStream(new FileOutputStream(path1));
            DataInputStream  dips = new DataInputStream(new FileInputStream(path1));
            for (Student s : student) {
                //写入数据
                oups.writeUTF(s.getName());
                oups.writeInt(s.getAge());
            }
            oups.flush();
            oups.close();
            for(int i = 0 ; i<student.length;i++){
                String name = dips.readUTF();
                int age = dips.readInt();
                student[i] = new Student(name, age);
            }
            for (Student student2 : student) {
                System.out.println(student2.getName()+"   "+student2.getAge());
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}
class Student implements Serializable {
    private String name;
    private int age;
    
    
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student[name=" + name + ",age=" + age + "]";
    }

}

 二、字符流讲解

  以字符为导向的 ------Writer和Reader(抽象类)
   1.FileReader和FileWriter
  FileReader:用来读取字符文件的便捷类。此类的构造方法假定默认字符编码和默认字节缓冲区大小都是适当的。
    FileWriter:用来写入字符文件的便捷类。此类的构造方法假定默认字符编码和默认字节缓冲区大小都是可接受的.
  下面见一个例子:
package com.chen.test;

import java.io.*;

/**
 * 
 * @author 陈家小帅
 * 
 */
public class Test4 {
    public static void main(String[] args) throws Exception {
        String path1 = "E:/WorkSpace/Mouth/bin/Dest.txt";
        String path2 = "E:/WorkSpace/Mouth/bin/D.txt";
         ReadByFR(path1, path2);
    }
/**
     * 使用FileReader将一个文件的内容写入到另一个文件中,并在控制台输出
     * 
     * @param path1
     * @param path2
     * @throws Exception
     */
    public static void ReadByFR(String path1, String path2) throws Exception {
        FileReader fr = new FileReader(path1);
        FileWriter fw = new FileWriter(path2);
        // 1.将一个文件的内容读出,写入
        char[] buffer = new char[1024];
        int len;
        while ((len = fr.read(buffer)) > -1) {        //将数据读到char数组中
            fw.write(buffer, 0, len);
       fw.flush(); String s
= new String(buffer, 0, len); System.out.println(s); } fw.close(); fr.close(); }
  2.BufferedReader和BufferedWriter

BufferedReader从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。

可以指定缓冲区的大小,或者可使用默认的大小。大多数情况下,默认值就足够大了。

BufferedWriter将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。

可以指定缓冲区的大小,或者接受默认的大小。在大多数情况下,默认值就足够大了。

该类提供了 newLine() 方法,它使用平台自己的行分隔符概念,并非所有平台都使用新行符 ('\n') 来终止各行。因此调用此方法来终止每个输出行要优于直接写入新行符。

 下面是个例子:
package com.chen.test;
import java.io.*;

/**
 * 
 * @author 陈家小帅
 * 
 */
public class Test4 {
    public static void main(String[] args) throws Exception {
        String path1 = "E:/WorkSpace/Mouth/bin/Dest.txt";
        String path2 = "E:/WorkSpace/Mouth/bin/D.txt";
        ReadByBR(path1, path2);
    }
/**
     * 使用BufferdeReader将一个文件的内容写入到另一个文件中,并在控制台输出
     * 
     * @param path1
     * @param path2
     * @throws Exception
     */
    public static void ReadByBR(String path1, String path2) throws Exception {
        BufferedReader fr = new BufferedReader(new FileReader(path1));
        BufferedWriter fw = new BufferedWriter(new FileWriter(path2));
     //PrintStream ps = new PrintStream(path2);
        String len;
        while ((len = fr.readLine()) != null) {
            fw.write(len);
            fw.flush();
        //ps.println(len);
        //ps.flush();
            System.out.println(len);
        }
        fw.close();
        fr.close();
    }
}

3.InputStreamReader和OutputStreamWriter

InputStreamReader 是字节流通向字符流的桥梁:每次调用 InputStreamReader 中的一个 read() 方法都会导致从底层输入流读取一个或多个字节。

要启用从字节到字符的有效转换,可以提前从底层流读取更多的字节,使其超过满足当前读取操作所需的字节。

  OutputStreamWriter 是字符流通向字节流的桥梁:

  每次调用 write() 方法都会导致在给定字符(或字符集)上调用编码转换器。在写入底层输出流之前,得到的这些字节将在缓冲区中累积。

  可以指定此缓冲区的大小注意,传递给 write() 方法的字符没有缓冲。

package com.chen.test;

import java.io.*;

/**
 * 
 * @author 陈家小帅
 * 
 */
public class Test4 {
    public static void main(String[] args) throws Exception {
        String path1 = "E:/WorkSpace/Mouth/bin/Dest.txt";
        String path2 = "E:/WorkSpace/Mouth/bin/D.txt";
        ReadByIS(path1, path2);
    }

    /**
     * 使用inputStreamReader将一个文件的内容写入到另一个文件中,并在控制台输出
     * 
     * @param path1
     * @param path2
     * @throws Exception
     */
    public static void ReadByIS(String path1, String path2) throws Exception {
        InputStreamReader isr = new InputStreamReader(
                new FileInputStream(path1));
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(
                path2));
        char[] cha = new char[1024];
        int len;
        while ((len = isr.read(cha)) > -1) {
            System.out.println(new String(cha, 0, len));
            osw.write(cha, 0, len);
            osw.flush();
        }
        osw.close();
        isr.close();
    }
}

 以上便是本人的一些见解,如有不对,还望指出!!!