字符流操作的是文本文件,操作其他的例如mp3之类的文件就没什么意义,非文本文件只能是用字节流进行读写。
一、概念引入
1、编码问题
在“文件编码”篇章中对编码有介绍,此处不做介绍。
2、文本和文本文件
文本:文本就是字符,java的文本(char)是16位无符号整数,是字符的unicode编码(双字节编码)
文件:文件就是字节序列,byte byte byte byte ……
文本文件:文本文件是文本(char)序列按照某种编码方案(utf8、utf-16be、gbk……)序列化为byte的存储
3、字符流
字符流与字节流相似,只是以字符为单位进行处理(字符的底层任然是基本的字节序列)
二、InputStreamReader 和 OutputStreamWriter
InputStreamReader :按照某种编码格式完成byte流到char流的解析。
OutputStreamWriter:按照某种编码格式完成char流到byte流的解析。
InputStreamReader常用方法介绍:
InputStreamReader(InputStream in)
创建一个使用默认字符集的InputStreamReader。默认使用项目的编码格式进行编码处理
InputStreamReader(InputStream in, Charset cs)
创建一个使用给定字符集的InputStreamReader。
InputStreamReader(InputStream in, CharsetDecoder dec)
创建一个使用给定字符集解码器的InputStreamReader。
InputStreamReader(InputStream in, String charsetName)
创建一个使用命名字符集的InputStreamReader。
void close()
关闭流并释放与之相关联的任何系统资源。
String getEncoding()
返回此流使用的字符编码的名称。
int read()
读一个字符,以整形的方式返回读取的字符,如果已经达到流的结尾,则返回-1
int read(char[] cbuf, int offset, int length)
将字符读入数组的一部分。cbuf - 目的缓冲区;offset - 开始存储字符的偏移量;length - 要读取的最大字符数。返回读取的字符数,如果已经达到流的结尾,则返回-1
boolean ready()
告诉这个流是否准备好被读取。
OutputStreamWriter常用方法介绍:
OutputStreamWriter(OutputStream out)
创建一个使用默认字符编码的OutputStreamWriter。(默认使用项目的编码格式进行编码)
OutputStreamWriter(OutputStream out, Charset cs)
创建一个使用给定字符集的OutputStreamWriter。
OutputStreamWriter(OutputStream out, CharsetEncoder enc)
创建一个使用给定字符集编码器的OutputStreamWriter。
OutputStreamWriter(OutputStream out, String charsetName)
创建一个使用命名字符集的OutputStreamWriter。
void close()
关闭流,先刷新。
void flush()
刷新流。
String getEncoding()
返回此流使用的字符编码的名称。
void write(char[] cbuf, int off, int len)
写入字符数组的一部分。
void write(int c)
写一个字符
void write(String str, int off, int len)
写一个字符串的一部分。
示例:
public static void main(String[] args) throws IOException {
FileInputStream fileInputStream = new FileInputStream("test02.txt");
InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream);
FileOutputStream fileOutputStream = new FileOutputStream("test04.txt");
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream);
char[] chars = new char[1024 * 6];
int c = 0;
while((c = inputStreamReader.read(chars, 0, chars.length)) > 0){
outputStreamWriter.write(chars, 0, c);
}
outputStreamWriter.flush();
inputStreamReader.close();
outputStreamWriter.close();
}
三、字符流之文件输入输出流
字符流之文件输入输出流FileReader(继承自InputStreamReader)、FileWriter(继承自OutputStreamWriter) 是无法指定编码格式的,也就是只有文本文件的编码格式和项目的编码格式相同时才能正常读取。
FileReader、FileWriter除了在构造方法和InputStreamReader 、 OutputStreamWriter不同之外,剩余的读写方法完全一样,所以这里不再对读写方法做介绍。
FileReader的构造方法:
FileReader(File file)
创建一个新的 FileReader ,给出 File读取。
FileReader(FileDescriptor fd)
创建一个新的 FileReader ,给定 FileDescriptor读取。
FileReader(String fileName)
创建一个新的 FileReader ,给定要读取的文件的名称。
FileWriter的构造方法:
FileWriter(File file)
给一个File对象构造一个FileWriter对象。
FileWriter(File file, boolean append)
给一个File对象构造一个FileWriter对象。
FileWriter(FileDescriptor fd)
构造与文件描述符关联的FileWriter对象。
FileWriter(String fileName)
构造一个给定文件名的FileWriter对象。
FileWriter(String fileName, boolean append)
构造一个FileWriter对象,给出一个带有布尔值的文件名,表示是否附加写入的数据。
示例:
public static void main(String[] args) throws IOException {
FileReader fileReader = new FileReader("test02.txt");
FileWriter fileWriter = new FileWriter("test06.txt");
char[] chars = new char[1024 * 8];
int c = 0;
while((c = fileReader.read(chars, 0, chars.length)) != -1){
fileWriter.write(chars, 0, c);
}
fileReader.close();
fileWriter.close();
}
四、BufferedReader和BufferedWriter
为了提高字符流读写的效率,引入了缓冲机制,进行字符批量的读写,提高了单个字符读写的效率。BufferedReader用于加快读取字符的速度,BufferedWriter用于加快写入的速度
BufferedReader和BufferedWriter类各拥有8192个字符的缓冲区。当BufferedReader在读取文本文件时,会先尽量从文件中读入字符数据并放满缓冲区,而之后若使用read()方法,会先从缓冲区中进行读取。如果缓冲区数据不足,才会再从文件中读取,使用BufferedWriter时,写入的数据并不会先输出到目的地,而是先存储至缓冲区中。如果缓冲区中的数据满了,才会一次对目的地进行写出。
BufferedReader
BufferedReader
是为了提供读的效率而设计的一个包装类,它可以包装字符流。可以从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。
注意:BufferedReader的rendLine()是不读入换行符的,所以写入换行时须用BufferedWriter的newLine()方法。否则内容就连成一行了;
构造方法
方法 | 描述 |
---|---|
BufferedReader(Reader in) | 创建一个使用默认大小输入缓冲区的缓冲字符输入流。 |
BufferedReader(Reader in, int sz) | 创建一个使用指定大小输入缓冲区的缓冲字符输入流。 |
成员方法
void close()
关闭流并释放与之相关联的任何系统资源。
Stream<String> lines()
返回一个 Stream ,其元素是从这个 BufferedReader读取的行。
void mark(int readAheadLimit)
标记流中的当前位置。
boolean markSupported()
告诉这个流是否支持mark()操作。
int read()
读一个字符
int read(char[] cbuf, int off, int len)
将字符读入数组的一部分。 返回读取的字符数,如果已经达到流的结尾,则为-1
String readLine()
读一行文字。如果有一行字符就返回该行字符串,没有就返回null
boolean ready()
告诉这个流是否准备好被读取。
void reset()
将流重置为最近的标记。
long skip(long n)
跳过字符
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)
写一个字符
void write(String s, int off, int len)
写一个字符串的一部分。
示例:
public static void main(String[] args) throws IOException {
FileInputStream fileInputStream = new FileInputStream("test02.txt");
InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
FileOutputStream fileOutputStream = new FileOutputStream("test07.txt");
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream);
BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter);
String line;
while ((line = bufferedReader.readLine()) != null) {
bufferedWriter.write(line, 0, line.length());
bufferedWriter.newLine();
}
bufferedWriter.flush();
bufferedReader.close();
bufferedWriter.close();
}