文本数据IO操作
流的拓展:字符流
java将流按照读写单位划分为字节流和字符流
我们前面学的文件流、缓冲流、对象流
字符流是为了方便我们读写文本
字符流介绍:
java.io.Reader
java.io.Writer
上述两个类是所以字符流的超类,规定了所有字符流都必须具备的读写字符的相关方法
字符流是以字符(char)为单位读写数据的
一次处理一个unicode
字符流的底层仍然是基本的字节流,只是字符与字节的转换,字符流自行完成
字符流封装了字符的编码解码算法
字符流仅仅用于文本数据IO操作
下面为常见文本流
一、转换流(高级流)
java.io.InputStreamReader
java.io.OutputStreamWriter
转换流是一对字符流,同时他们也是高级流,而且是唯一能连接字节流的字符流(相当于转换器)
在实际开发时,我们通常不会直接操作这两个流
但是在读写文本数据时,流连接中,他们是重要的一环
负责衔接其他字符高级流与字节流
在使用转换流时,要注意需要先创建低级流,转换流是高级流,依附于低级流实现
步骤:
- 创建低级流(为流的管道,是高级流的依附条件,一般为文件流)
- 创建高级流(这里传入参数为低级流对象和字符集编码格式)
- 写出:write(字符串)
读入:可单字符或字符数组读入
- 关闭高级流
注意事项:
- 在写出操作中创建转换流时,注意在创建转换流时设置字符集
转换流在创建时通常会传入第二个参数,这个参数用来指定字符集
这样一来,通过当前流写出的文本数据都会按照该字符集转换为字节后写出 - 转换流是知道编码规则的,所以他会按需读取,能把字符按中英文分开成单个字符
所以他可以单独读一个字符,会自动按中英文字节分开为一个字符读取
使用转换流写出文本数据:
package io;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
public class OSDemo {
public static void main(String[] args) throws IOException {
//创建低级流(文件流)
FileOutputStream fos = new FileOutputStream("./osw.txt");
//创建高级流(字符流:转换流)
//注意:设置字符集在创建转换流时设置
/*
* 转换流在创建时通常会传入第二个参数,这个参数用来指定字符集
* 这样一来,通过当前流写出的文本数据都会按照该字符集转换为字节后写出
*/
OutputStreamWriter osw = new OutputStreamWriter(fos,"utf-8");
//转换流提供了转换方法,可以直接写入字符串,无需我们字节转换
osw.write("我李淳罡要甚天道?一剑足矣!");
osw.write("生平仅有三尺剑,有蛟龙处杀蛟龙");
System.out.println("写出完毕!");
osw.close();
}
}
使用转换流读入文本数据:
package io;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.RandomAccessFile;
public class ISRDemo {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("./osw.txt");
InputStreamReader isr = new InputStreamReader(fis,"utf-8");
//注意:转换流是知道编码规则的,所以他会按需读取,
//可以单独读一个字符,会自动按中英文字节分开为一个字符读取
//单字符读取
// int d = -1;
// while((d = isr.read())!=-1){
// System.out.print((char)d);
// }
//字符数组读取方法
char[] data = new char[1024*10];
int len = -1;
String str = "";
while((len=isr.read(data))!=-1){
//将字符数组写在一个字符串里面
str = str.concat(new String(data,0,len));
}
System.out.println(str);
isr.close();
}
}
二、缓冲字符流(高级流)PW
缓冲字符流
java.io.BufferedWriter
java.io.BufferedReader
缓冲流是块读写文本数据,提高读写效率,并且可以按行读写字符串
1、缓冲字符输出流
java.io.BufferedWriter (实现PW需要传入这个的对象)
java.io.PrintWriter (一般用这个 pw)
具有自动 行刷新 的缓冲字符输出流
PrintWriter的构造方法传入参数为流和是否开启自动行刷新功能,默认关闭
根据具体需求,看是否需要打开该功能
内部总是连接BufferedWriter作为其缓冲加速操作
注意:这个高级流不用自己创建低级流,因为在这个高级流底层为我们实现了流连接
但是我们根据需求,如果要用其他的流连接线路,我们需要自行完成流连接
看着好像是低级流,其实是因为在这个类的构造方法中已经实现了
查看该类源码我们发现,该类构造方法内部会自动进行流连接操作,
分别连接缓冲字符流、转换流、文件流
/* Private constructor */
private PrintWriter(Charset charset, File file)
throws FileNotFoundException
{
this(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), charset)),
false);
}
步骤:
- 创建pw对象,传入路径和编码格式(也可自行创建流连接)
- 写出数据(print,和输出到控制台的语句相似)
- 关闭pw
package io;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
public class PWDemo1 {
public static void main(String[] args) throws FileNotFoundException, UnsupportedEncodingException {
/*
* 向pw.txt文件中写出字符串
*/
PrintWriter pw = new PrintWriter("./pw.txt","utf-8");
pw.println("西楚曹长卿,落子太安城");
pw.println("唯我大楚:");
pw.print("宁在雨中高歌死,");
pw.print("不去寄人篱下活!");
System.out.println("写出完毕!");
pw.close();
}
}
自行完成流连接,使用PW写出文本数据
package io;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
public class PWDemo2 {
public static void main(String[] args) throws FileNotFoundException, UnsupportedEncodingException {
//基础的低级流,文件流
FileOutputStream fos = new FileOutputStream("pw2.txt");
//转换流,这里需要设置编码格式
OutputStreamWriter osw = new OutputStreamWriter(fos,"utf-8");
//缓冲字符流
BufferedWriter bw = new BufferedWriter(osw);
PrintWriter pw = new PrintWriter(bw);
pw.print("生而为人且善良,");
pw.print("长亦成芒");
System.out.println("写出完毕!");
pw.close();
}
}
练习:实现简易记事本工具
程序启动后,要求输入文件名,然后对文件写入内容
将后续在控制台输入的每行字符串都按行写入到该文件中
当单独输入了exit时,程序退出
要求:自行使用流连接创建pw
package io;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.Scanner;
public class PWdemo3 {
public static void main(String[] args) throws UnsupportedEncodingException, FileNotFoundException {
Scanner input = new Scanner(System.in);
//接收文件名
System.out.print("请输入文件名:");
String path = input.nextLine()+".txt";
//创建低级流,文件流,接收文件路径
FileOutputStream fos= new FileOutputStream(path);
//创建高级流,转换流,转换字节流为字符流,接收文件编码格式
OutputStreamWriter osw = new OutputStreamWriter(fos,"utf-8");
//创建缓冲字符流
BufferedWriter bw = new BufferedWriter(osw);
PrintWriter pw = new PrintWriter(bw,true);
//提示用户记事本已经打开,提示输入
System.out.println("请输入内容:(单行输出exit退出记事本)");
while(true){
//创建字符串容器,接收控制台输入的值
String str = input.nextLine();
if("exit".equals(str)){
break;
}
pw.println(str);
//如果想要写一句存一句,可以调用flush方法
//清空缓冲区,写一句存一句
//pw.flush();
}
//写出完毕
System.out.println("写出完毕!");
//关闭pw,关闭时会自动调用缓冲流中的flush方法清空缓冲区,所以要记得写关闭
pw.close();
}
}
PW的自动行刷新功能
PrintWriter的构造方法,还可以再传入一个boolean值的参数,传入true表示打开了自动行刷新功能
会每输入一行,就存入一行,类似于每输入一行就调用一次flush清空缓冲区
PrintWriter pw = new PrintWriter(bw,true);
2、缓冲字符输入流
java.io.BufferedReader
块读取文本数据,并且可以按行读取字符串
其读取方法含有行读取
String readLine()
该方法会:连续读取若干字符,直到读取到换行符为止,将换行符之前的字符组成一个字符串返回
如果返回值为null,表示流读取到文件末尾了
package io;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
public class BRDemo {
public static void main(String[] args) throws IOException {
/*
* 将当前源代码内容输出到控制台
*/
FileInputStream fis= new FileInputStream("./src/io/BRDemo.java");
InputStreamReader isr = new InputStreamReader(fis);
BufferedReader br = new BufferedReader(isr);
//String readLine(),读取行文件方法
String line = null;
while((line = br.readLine())!=null){
System.out.println(line);
}
br.close();
}
}
IO操作主要的流表格(java中io流的体系)
字节流 | 字符流 | |||
低级流 | InputStream | OutputStream | Reader | Writer |
FileInputStream(负责从文件中读取字节) | FileOutputStream(负责从文件中写入字节) | |||
高级流 | BufferedInputStream(块读字节,加快读取效率) | BufferedOutputStream(块写字节,加快写入效率) | InputStreamReader(衔接字符流与字节流,将字节转换为字符) | OutputStreamWriter(衔接字节流与字符流,将字符转换为字节) |
ObjectInputStream(对象反序列化) | ObjectOutputStream(对象序列化) | BufferedReader(块读文本数据,按行读取字符串) | BufferedWriter/PrintWriter(块写文本数据,按行写入) |
io流和raf有什么区别
raf更灵活,有指针,想读文件哪里读哪里
io流适用于网络数据传输