Java中的输入输出流根据格式又可以分为字节流和字符流:(成对)
字节流:FileInputStream,FileOutputStream ; BufferedInputStream,BufferedOutputStream ;
字符流:FileReader,FileWriter ; BufferedReader,BufferedWriter
字符流和字节流的主要区别:
1.字节流读取的时候,读到一个字节就返回一个字节;(一个英文字符是一个字节);字符流使用了字节流读到一个或多个字节(一个中文是两个字节,在UTF-8码表中是3个字节,这要看编码方式,不同的编码中文是不同的大小)时。先去查指定的编码表,将查到的字符返回。
2.字节流可以处理所有类型数据,如:图片,MP3,AVI视频文件,而字符流只能处理字符数据。只要是处理纯文本数据,就要优先考虑使用字符流,除此之外都用字节流。
下面根据字节流和字符流来依次说明:
字节流:
1. FileInputStream,FileOutputStream( 这两个都是成对出现,前者进行输入(读文件)操作,后者进行输出(写文件)操作)
FileInputStream类称为文件输入流。它的作用是将文件中的数据输入到内存中,我们可以利用它来读文件。由于它属于字节流,因此在读取Unicode字符(如中文)的文件时可能会出现问题。
该类的构造方法:
·FileInputStream(File file):打开一个到实际文件的连接来创建一个FileInputStream,该文件通过文件系统中的File对象file指定。
·FileInputStream(String name):打开一个到实际文件的连接来创建一个FileInputStream,该文件通过文件系统中的路径名name指定。
这里提一下File类,File类的对象不但可以表示文件,还可以表示目录;当创建一个文件对象后,就可以利用它来对文件或目录的属性进行操作,如:文件名、最后修改日期、文件大小等等;需要注意的是,File对象并不能直接对文件进行读/写操作,只能查看文件的属性;创建格式:File file = new File("test.txt");
FileOutputStream类称为文件输出流,他的作用是将数据写到文件中,我们可以利用它来写文件。
该类的构造方法:
·FileOutputStream(File file):创建一个向指定File对象表示的文件中写入数据的文件输出流。
·FileOutputStream(String name):创建一个向具有指定名称的文件中写入数据的输出文件流。
常用到的方法:
·void write(byte[] b):将b.length个字节从指定byte数组写入此文件输出流中。
·void write(byte[] b,int off,int len):将指定byte数组中从偏移量off开始的len个字节写入此文件输出流。
·void write(int b):将指定字节写入此文件输出流。
2. BufferedInputStream,BufferedOutputStream(这对可以和上面一组对比着看,主要就是相差了一个缓冲区)
BufferedInputStream类称为缓冲输入流,其本身带有一个缓冲区,在读取数据时,先放到缓冲区中,可以减少对数据源的访问,提高运行的效率。
构造方法:
·BufferedInputStream(InputStream in):创建一个BufferedInputStream并保存其参数,即输入流in,以便将来使用。
·BufferedInputStream(InputStream in,int size):创建一个具有指定缓冲区大小的BufferedInputStream并保存其参数,即输入流in,以便将来使用。
常用方法:
·int read():从输入流中读取数据的下一个字节。
·int read(byte[] b,int off,int len):从此字节输入流中给定偏移量处开始将各字节读取到指定的byte数组中。
BufferedOutputStream类称为缓冲输出流,其本身也带有一个缓冲区,在写入数据时,先放到缓冲区中,实现缓冲的数据流。要注意在使用BufferedOutputStream
写完数据后,要调用flush()
方法或close()
方法,强行将缓冲区中的数据写出。否则可能无法写出数据。
构造方法:
·BufferedOutputStream(OutputStream out):创建一个新的缓冲输出流,来将数据写入指定的底层输入流。
·BufferedOutputStream(OutputStream out,int size):创建一个新的缓冲输出流,来将具有指定缓冲区大小的数据写入指定的底层输出流。
常用方法:
·void flush():刷新此缓冲的输出流。
·void write(byte[] b,int off,int len):将指定byte数组中从偏移量off开始的len个字节写入此缓冲的输出流。
·void write(int b):将指定的字节写入此缓冲的输出流。
字符流:
FileReader,FileWriter ; BufferedReader,BufferedWriter(放在一起说)
FileReader类称为文件读取流,允许以字符流的形式对文件进行读操作(该类将从文件中逐个地读取字符,效率比较低下,因此一般将该类对象包装到缓冲流中进行操作。BufferedReader类主要为字符流提供缓冲,所以FileReader一般配合BufferReader来用)
构造方法:
FileReader(String fileName)
FileReader(File file)
常用方法://都是继承自Reader的方法
int read()
int read(char[] b)
int read(char[] b , int off ,int len)
FileWriter类称为文件写入流,以字符流的形式对文件进行写操作与FileReader类相似,FileWriter类同样需要使用缓冲流进行包装,所以FileWriter一般配BufferedWriter来用
构造方法:
FileWriter(String fileName)
FileWriter(String fileName, boolean append) //boolean append是否在原有基础上继续写
FileWriter(File file)
FileWriter(File file, boolean append)//boolean append是否在原有基础上继续写
常用方法:
void write(char[] b)
void write(char[] b, int off, int len)
void write(int b)
void write(String str)
void write(String str, int off, int len)
Writer append(char c)
Writer append(CharSequence csq)
Writer append(CharSequence csq, int start, int end)
为了提高字符流读写的效率,引入了缓冲机制,进行字符批量的读写,提高了单个字符读写的效率。BufferedReader用于加快读取字符的速度,BufferedWriter用于加快写入的速度。BufferedReader和BufferedWriter类各拥有8192个字符的缓冲区。当BufferedReader在读取文本文件时,会先尽量从文件中读入字符数据并放满缓冲区,而之后若使用read()方法,会先从缓冲区中进行读取。如果缓冲区数据不足,才会再从文件中读取,使用BufferedWriter时,写入的数据并不会先输出到目的地,而是先存储至缓冲区中。如果缓冲区中的数据满了,才会一次对目的地进行写出。
BufferedReader
是为了提供读的效率而设计的一个包装类,它可以包装字符流。可以从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。
构造方法:
BufferedReader(Reader in) //创建一个使用默认大小输入缓冲区的缓冲字符输入流。
BufferedReader(Reader in, int sz) //
创建一个使用指定大小输入缓冲区的缓冲字符输入流。
常用方法:
int read() //读取单个字符。
int read(char[] cbuf, int off, int len) //将字符读入数组的某一部分。
String readLine() //读取一个文本行。(不包括换行符)
BufferedWriter:
构造方法:
BufferedWriter(Writer out) //创建一个缓冲字符输出流,使用默认大小的输出缓冲区
BufferedWriter(Writer out, int sz) //创建一个缓冲字符输出流,使用给定大小的输出缓冲区
常用方法:
void write(int c) //写入单个字符。
void write(char[] cbuf, int off, int len) //写入字符数组的某一部分。
void write(String s, int off, int len) //写入字符串的某一部分。
void newLine() //写入一个行分隔符。
void close() //关闭此流,但要先刷新它
void flush() //刷新该流的缓冲
乱码问题:
虽然前面提到处理纯文本数据,就要优先考虑使用字符流,但是考虑到编码的因素,可以使用包装InputStreamReader
的BufferedReader
,包装OutputStreamWriter
的BufferedWriter
来复制文件,好处就是可以指定复制文件的时候使用的字符编码使不产生乱码。下面讲一下InputStreamReader
和OutputStreamWriter
:
InputStreamReader:
它使用指定的字符集读取字节并将它们解码为字符。 它使用的字符集可以通过名称指定,也可以明确指定,或者可以接受平台的默认字符集。每次调用一个InputStreamReader的read()方法都可能导致从底层字节输入流中读取一个或多个字节。为了获得最高效率,通常在BufferedReader中包装InputStreamReader。
使用格式: BufferedReader
reader = new BufferedReader(new InputStreamReader(new FileInputStream(srcFile),"UTF-8"));
OutputStreamWriter:
它使用指定的字符集将字符编码为字节(是
InputStreamReader的逆过程
)。它的字符集可以由名称指定,也可以接受平台的默认字符集。
使用格式:
BufferedWriter
writer = new BufferedWriter(new OutputStreamWriter( new FileOutputStream(destFile),
"UTF-8"
));