Java API--IO流整理

来源:互联网 发布:全国省市区街道数据库 编辑:程序博客网 时间:2024/05/29 19:57

流的概念

在Java API中,可以从其中读入一个字节序列的对象称作输入流,而可以向其中写入一个字节序列的对象称作输出流

IO流分类:

  • 输入流
    • 字节输入流–>IuputStream(抽象类)
    • 字符输入流–>Reader(抽象类)
  • 输出流
    • 字节输出流–>OutputStream(抽象类)
    • 字符输出流–>Writer(抽象类)
      注:所谓的输入和输出都是相对于程序而言,读取文件则使用输入流,写入文件则使用输出流。

1. 字节输入流

InputStream子类—-FileInputStream类
顾名思义,FileInputStream类是用于操作文件的输入流。

常用构造方法:

FileInputStream(File file):
通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的 File 对象 file 指定。
FileInputStream(String name):
通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的路径名 name 指定。

以上是项目开发中常用的两个构造方法,还有其他构造方法,请读者自行学习。

FileInputStream常用方法:

void close():
关闭此文件输入流并释放与此流有关的所有系统资源。
>int read():
从此输入流中读取一个数据字节。
>int read(byte[] b):
从此输入流中将最多 b.length 个字节的数据读入一个 byte 数组中。

API使用练习—-2种read()方法读取项目目录下的TXT文件:

import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.IOException;import java.io.InputStream;/* * 需求:读取项目目录下的TXT文件 */public class FileInputStreamDemo {    public static void main(String[] args) {        //method1();        method2();    }    public static void method1(){//使用:int read():从此输入流中读取一个数据字节。         InputStream fin = null;        try {            fin = new FileInputStream("test.txt");            int by = 0;            while((by = fin.read())!=-1){                System.out.println((char)by);            }        } catch (FileNotFoundException e) {            e.printStackTrace();            System.out.println("文件为找到!!!");        } catch (IOException e) {            e.printStackTrace();            System.out.println("文件读取异常!!!");        }finally{            if(fin!=null){                try {                    fin.close();                } catch (IOException e) {                    e.printStackTrace();                }            }        }    }    public static void method2() {        InputStream fin = null;        try {            fin = new FileInputStream("test.txt");            int len = 0;            byte[] bys = new byte[1024];            while((len = fin.read(bys))!=-1){                String str = new String(bys, 0, len);                System.out.println(str);            }        } catch (FileNotFoundException e) {            e.printStackTrace();            System.out.println("文件为找到!!!");        } catch (IOException e) {            e.printStackTrace();            System.out.println("文件读取异常!!!");        }finally{            if(fin!=null){                try {                    fin.close();                } catch (IOException e) {                    e.printStackTrace();                }            }        }    }}

2. 字节输出流

OnputStream子类—-FileOnputStream类
顾名思义,FileOnputStream类是用于操作文件的输出流。

常用构造方法:

FileOutputStream(File file):
创建一个向指定File对象表示的文件中写入数据的文件输出流。
FileOutputStream(String name):
创建一个向具有指定名称的文件中写入数据的输出文件流。

FileOutStream常用方法:

void close():
关闭此文件输出流并释放与此流有关的所有系统资源。
void write(byte[] b):
将 b.length 个字节从指定 byte 数组写入此文件输出流中。
void write(int b):
将指定字节写入此文件输出流。

API使用练习—-2种write()方法写入文件:

import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.io.OutputStream;/* * 需求:使用FileOutputStream写入文件,2种write()方法实现 */public class FileOutputStreamDemo {    public static void main(String[] args) {        //method1();        method2();    }    public static void method2() {/* void write(int b): 将指定字节写入此文件输出流。*/         OutputStream fOutput = null;        try {            fOutput = new FileOutputStream("Write.txt");            for(int i=0;i<10;i++){                fOutput.write('a'+i);            }        } catch (FileNotFoundException e) {            e.printStackTrace();        } catch (IOException e) {            e.printStackTrace();        }finally{            if(fOutput!=null){                try {                    fOutput.close();                } catch (IOException e) {                    e.printStackTrace();                }            }        }    }    public static void method1() {//void write(byte[] b): 将 b.length 个字节从指定 byte 数组写入此文件输出流中。         OutputStream fout = null;        try {            fout = new FileOutputStream("Write.txt");            fout.write("I love java.".getBytes());        } catch (FileNotFoundException e) {            e.printStackTrace();        } catch (IOException e) {            e.printStackTrace();        }finally{            if(fout!=null){                try {                    fout.close();                } catch (IOException e) {                    e.printStackTrace();                }            }        }    }}

注:如果写入的文件不存在则会创建相应文件。
FileInputStream和FileOutputStream的结合使用—-拷贝文件:

private static void method1() {//一次读取一个字节进行拷贝    InputStream fin = null;    OutputStream fout = null;    try {        fin = new FileInputStream("test.txt");        fout = new FileOutputStream("copyTest.txt");        int by = 0;        while((by=fin.read())!=-1){            fout.write(by);        }        System.out.println("拷贝完成!");    } catch (FileNotFoundException e) {        e.printStackTrace();    } catch (IOException e) {        e.printStackTrace();    }finally{        if(fout!=null&&fin!=null){            try {                fout.close();                fin.close();            } catch (IOException e) {                e.printStackTrace();            }        }    }}private static void method2() {//一次读取一个字节数组进行拷贝    InputStream fin = null;    OutputStream fout = null;    try {        fin = new FileInputStream("test.txt");        fout = new FileOutputStream("copyTest.txt");        byte[] bys = new byte[1024];        int len = 0;        while((len=fin.read(bys))!=-1){            fout.write(bys, 0, len);        }        System.out.println("拷贝完成!!");    } catch (FileNotFoundException e) {        e.printStackTrace();    } catch (IOException e) {        e.printStackTrace();    }finally{        if(fout!=null&&fin!=null){            try {                fin.close();                fout.close();            } catch (IOException e) {                e.printStackTrace();            }        }    }}

以上两种方式拷贝文件速度还是比较低的,由此引出–>BufferedInputStream和BufferedOutputStream。
将要读取(写入)的数据先填充进缓冲区中,再一次性读取(写入)。从而提高速度。

  • BufferedInputStream:
              BufferedInputStream 为另一个输入流添加一些功能,即缓冲输入以及支持 mark 和 reset 方法的能力。在创建 BufferedInputStream 时,会创建一个内部缓冲区数组。在读取或跳过流中的字节时,可根据需要从包含的输入流再次填充该内部缓冲区,一次填充多个字节。mark 操作记录输入流中的某个点,reset 操作使得在从包含的输入流中获取新字节之前,再次读取自最后一次 mark 操作后读取的所有字节。

构造方法:

BufferedInputStream(InputStream in):
创建一个 BufferedInputStream 并保存其参数,即输入流 in,以便将来使用。 BufferedInputStream(InputStream in, int size):
创建具有指定缓冲区大小的 BufferedInputStream 并保存其参数,即输入流 in,以便将来使用。

注:一般我们不设置size的大小,所以通常使用第一个。

  • BufferedOutputStream:
              该类实现缓冲的输出流。通过设置这种输出流,应用程序就可以将各个字节写入底层输出流中,而不必针对每次字节写入调用底层系统。

构造方法:

BufferedOutputStream(OutputStream out):
创建一个新的缓冲输出流,以将数据写入指定的底层输出流。 BufferedOutputStream(OutputStream out, int size):
创建一个新的缓冲输出流,以将具有指定缓冲区大小的数据写入指定的底层输出流。

注:一般我们不设置size的大小,所以通常使用第一个。

BufferedInputStream和BufferedOutputStream的使用:
使用方法特别简单:
将:

fin = new FileInputStream("test.txt");fout = new FileOutputStream("copyTest.txt");

改为:

fin = new BufferedInputStream(new FileInputStream("test.txt"));fout = new BufferedOutputStream(new FileOutputStream("copyTest.txt"));

实验:4种拷贝文件速度的比较:

  • 未使用缓冲流,一个字节拷贝方法–耗时:280毫秒
  • 未使用缓冲流,一个字节数组拷贝方法–耗时:4毫秒
  • 使用缓冲流,一个字节数组拷贝方法–耗时:49毫秒
  • 使用缓冲流,一个字节数组拷贝方法–耗时:3毫秒

3.字符输入流
Reader子类—-FileReader类(不是直接子类):
public class FileRead erextends InputStreamReader用来读取字符文件的便捷类。

常用构造方法:

FileReader(File file):
在给定从中读取数据的 File 的情况下创建一个新 FileReader。
FileReader(String fileName):
在给定从中读取数据的文件名的情况下创建一个新 FileReader。

常用方法:

public int read() throws IOException:
读取单个字符。
public int read(char[] cbuf) throws IOException:
将字符读入数组。在某个输入可用、发生 I/O 错误或者已到达流的末尾前,此方法一直阻塞。返回读取字符长度,读取到文件尾则返回-1。

API使用—-2种方法读取文件:

public static void method1() {//一次读取一个字符    Reader fReader = null;    try {        fReader = new FileReader("test2.txt");        int ch;        while((ch=fReader.read())!=-1){            System.out.println((char)ch);        }    } catch (FileNotFoundException e) {        e.printStackTrace();    } catch (IOException e) {        e.printStackTrace();    }finally{        if(fReader!=null){            try {                fReader.close();            } catch (IOException e) {                e.printStackTrace();            }        }    }}public static void method2() {    Reader fReader = null;    try {        fReader = new FileReader("test.txt");        char[] chs = new char[1024];        int len = 0;        while((len=fReader.read(chs))!=-1){            String str = new String(chs, 0, len);            System.out.println(str);        }    } catch (FileNotFoundException e) {        e.printStackTrace();    } catch (IOException e) {        e.printStackTrace();    }finally{        if(fReader!=null){            try {                fReader.close();            } catch (IOException e) {                e.printStackTrace();            }        }    }}

4.字符输出流
Writer子类—-FileWriter类(不是直接子类):
用来写入字符文件的便捷类。

常用构造方法:

FileWriter(File file):
根据给定的 File 对象构造一个 FileWriter 对象。
FileWriter(String fileName):
根据给定的文件名构造一个 FileWriter 对象。

常用方法:
public void write(int c):
写入单个字符。
public void write(char[] cbuf):
写入字符数组。
public abstract void write(char[] cbuf,int off,int len): 写入字符数组的某一部分。

API使用—-2种方法写入文件:

public static void method1(){//一次写入一个字符    Writer fWriter = null;    try {        fWriter = new FileWriter("test.txt");        int ch;        for(int i=0;i<26;i++){            fWriter.write('a'+i);        }        System.out.println("写入完成!!");    } catch (IOException e) {        e.printStackTrace();    }finally{        if(fWriter!=null){            try {                fWriter.close();            } catch (IOException e) {                e.printStackTrace();            }        }    }}public static void method2(){//一次写入一个字符数组    Writer fWriter = null;    try {        fWriter = new FileWriter("test.txt");        char[] chs = {'1','2','3','4','5','6','7','8','9','a'};        fWriter.write(chs, 0, chs.length);        System.out.println("写入完成!!");    } catch (IOException e) {        e.printStackTrace();    }finally{        if(fWriter!=null){            try {                fWriter.close();            } catch (IOException e) {                e.printStackTrace();            }        }    }}

注:与FileOutputStream一样,如果写入文件不存在,则会新创建相应文件。
FileReader和FileWriter的结合使用—-拷贝文件:

import java.io.FileNotFoundException;import java.io.FileReader;import java.io.FileWriter;import java.io.IOException;import java.io.Reader;import java.io.Writer;public class CopyFileDemo2 {    public static void main(String[] args) {        //method1();        method2();    }    public static void method1(){//一个字符进行拷贝        Reader fReader = null;        Writer fWriter = null;        try {            fReader = new FileReader("test2.txt");            fWriter = new FileWriter("test.txt");            int ch = 0;            while((ch = fReader.read())!=-1){                fWriter.write(ch);            }            System.out.println("拷贝完成!!");        } catch (FileNotFoundException e) {            e.printStackTrace();        } catch (IOException e) {            e.printStackTrace();        }finally{            if(fWriter!=null){                try {                    fReader.close();                    fWriter.close();                } catch (IOException e) {                    e.printStackTrace();                }            }        }    }    public static void method2(){//一个字符数组进行拷贝        Reader fReader = null;        Writer fWriter = null;        try {            fReader = new FileReader("copyTest3.txt");            fWriter = new FileWriter("test.txt");            char[] chs = new char[1024];            int len = 0;            while((len = fReader.read(chs))!=-1){                fWriter.write(chs,0,len);            }            System.out.println("拷贝完成!!");        } catch (FileNotFoundException e) {            e.printStackTrace();        } catch (IOException e) {            e.printStackTrace();        }finally{            if(fWriter!=null){                try {                    fReader.close();                    fWriter.close();                } catch (IOException e) {                    e.printStackTrace();                }            }        }    }}

在字节流中存在缓冲流,那么显然字符流中也存在缓冲流。

  • BufferedWriter

构造方法摘要:

BufferedWriter(Writer out):
创建一个使用默认大小输出缓冲区的缓冲字符输出流。
BufferedWriter(Writer out, int sz):
创建一个使用给定大小输出缓冲区的新缓冲字符输出流。

方法摘要:
void close():
关闭此流,但要先刷新它。
void flush():
刷新该流的缓冲。
void newLine():
写入一个行分隔符。
void write(char[] cbuf, int off, int len):
写入字符数组的某一部分。
void write(int c):
写入单个字符。

  • BufferedReader

构造方法摘要:

BufferedReader(Reader in):
创建一个使用默认大小输入缓冲区的缓冲字符输入流。
BufferedReader(Reader in, int sz):
创建一个使用指定大小输入缓冲区的缓冲字符输入流。

方法摘要:

void close():
关闭该流并释放与之关联的所有资源。
int read():
读取单个字符。
int read(char[] cbuf, int off, int len):
将字符读入数组的某一部分。
String readLine():
读取一个文本行。

使用字符缓冲流的特有方法拷贝文件:

import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.FileNotFoundException;import java.io.FileReader;import java.io.FileWriter;import java.io.IOException;public class CopyFileDemo3 {    public static void main(String[] args) {        method();    }    public static void method() {        BufferedReader fReader = null;        BufferedWriter fWriter = null;        try {            fReader = new BufferedReader(new FileReader("test.txt"));            fWriter = new BufferedWriter(new FileWriter("test2.txt"));            String string;            while((string = fReader.readLine())!=null){//读取一行,遇到换行符结束,不读取换行符                fWriter.write(string, 0, string.length());                fWriter.newLine();//手动加入换行符                fWriter.flush();//手动刷新缓冲区            }            System.out.println("拷贝完成!!");        } catch (FileNotFoundException e) {            e.printStackTrace();        } catch (IOException e) {            e.printStackTrace();        }finally{            if(fWriter!=null&&fReader!=null){                try {                    fWriter.close();                    fWriter.close();                } catch (IOException e) {                    e.printStackTrace();                }            }        }    }}

讨论:

字节流可以做任何操作,为什么要引入字符流呢?
答:字节流操作文本文件不方便,而使用字符流更加方便。


引子:标准输入输出流(了解)

(1)System类下面有这样的两个字段
in 标准输入流
out 标准输出流
(2)三种键盘录入方式
A:main方法的args接收参数
**B:System.in通过BufferedReader进行包装
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));**
C:Scanner
Scanner sc = new Scanner(System.in);
(3)输出语句的原理和如何使用字符流输出数据
A:原理
System.out.println(“helloworld”);
PrintStream ps = System.out;
ps.println(“helloworld”);
**B:把System.out用字符缓冲流包装一下使用
BufferedWriter bw = new BufferedWriter(newOutputStreamWriter(System.out));**


注意引子中的加粗部分,System.in是字节流,而br是字符流,通过InputStreamReader(),转换为字符流。—->引出:转换流
为什么需要用两种流,而且要转换,不直接用字符流。
简单说来,就是字符流不能处理所有的情况,字节流也不能处理所有的情况。所以需要两种转换。
测试转换流:

public static void method1(){    OutputStream fout = null;    try {        fout =new FileOutputStream("test3.txt");        byte[] bys = new byte[32];        fout.write("中国".getBytes());    } catch (FileNotFoundException e) {        e.printStackTrace();    } catch (IOException e) {        e.printStackTrace();    }finally{        if(fout!=null){            try {                fout.close();            } catch (IOException e) {                e.printStackTrace();            }        }    }}

由于编码问题写入的文件中是乱码。
使用转换流:

public static void method2(){    OutputStreamWriter fout = null;    try {        fout =new OutputStreamWriter(new FileOutputStream("test3.txt"),"UTF-8");        fout.write("中国");    } catch (FileNotFoundException e) {        e.printStackTrace();    } catch (IOException e) {        e.printStackTrace();    }finally{        if(fout!=null){            try {                fout.close();            } catch (IOException e) {                e.printStackTrace();            }        }    }}

设置了相应的编码格式后写入的文件不出现乱码了。


最后,贴上一张流的详细分类图,慢慢啃吧!
这里写图片描述
还有一些其他流后续继续写。。。

原创粉丝点击