IO流
IO流用来处理设备之间的数据传输
java对数据的操作是通过流的方式
java用于操作流的对象都在IO包中
流按操作数据分为两种:字节流和字符流
按流向分为输入流和输出流
字符编码
一、ASCII: 美国(国家)信息交换标准(代)码,一种使用7个或8个二进制位进行编码的方案,最多可以给256个字符(包括字母、数字、标点符号、控制字符及其他符号)分配(或指定)数值
二、GBK-2312: 是中华人民共和国国家汉字信息交换用编码,全称《信息交换用汉字编码字符集——基本集》,1980年由国家标准总局发布。基本集共收入汉字6763个和非汉字图形字符682个,通行于中国大陆。新加坡等地也使用此编码。
三、UNICODE:如果有一种编码,将世界上所有的符号都纳入其中,无论是英文、日文、还是中文等,大家都使用这个编码表,就不会出现编码不匹配现象。每个符号对应一个唯一的编码,乱码问题就不存在了。这就是Unicode编码。Unicode所有字符都用2个字节表示。
四、UTF-8:为了提高Unicode的编码效率,于是就出现了UTF-8编码。UTF-8可以根据不同的符号自动选择编码的长短。比如英文字母可以只用1个字节就够了。
IO流常用基类
字节流的抽象基类:InputStream,OutputStream
字符流的抽象基类:Reader,Writer
由这四个类派生出来的子类名称都以其父类名作为子类名的后缀
字符流融合了字符编码表,用于处理文字类
FileWriter 往文件中写入数据
public static void main(String[] args) throws IOException {
// 创建FileWriter流对象
// 在指定位置创建文件
// 如果在该目录下有同名文件,将被覆盖
FileWriter fw = new FileWriter("a.txt");
// 添加字符串到内存中或者说流的缓冲中
fw.write("as");
// 将流缓冲中的数据写入文件
fw.flush();
// 将流缓冲中的数据写入文件
// 关闭流对象
fw.close();
// 创建FileWriter流对象
// 在指定位置创建文件
// 如果在该目录下有同名文件,追加文件内容
FileWriter fw2 = new FileWriter("a.txt", true);
fw2.close();
}
IO异常处理方式
标准写法:
public static void main(String[] args) {
FileWriter fw=null;
try{
fw = new FileWriter("a.txt");
fw.write("as");
fw.flush();
}catch (IOException e){
System.out.println(e.getMessage());
}finally {
try{
if(fw!=null){
fw.close();
}
}catch (IOException e){
System.out.println(e.getMessage());
}
}
}
win的换行是\r\n,linux的换行是\n
FileReader 读取单个字符
· FileReader是InputStreamReader的子类
· FileReader的编码固定是GBK
public static void main(String[] args) {
FileReader fr=null;
try{
// 创建文件读取流对象,和指定名称的文件相关联
// 要保证文件已经存在,否则会发生FileNotFoundException异常
fr = new FileReader("a.txt");
while (true){
// 读取单个字符,而且会自动往下读
// 字符以整数返回
int ch = fr.read();
// -1表示读到末尾
if(ch==-1){
break;
}
System.out.println(fr.read());
}
// 简单写法
// int ch = 0;
// while((ch=fr.read()) != -1){
// System.out.println(ch);
// }
}catch (IOException e){
System.out.println(e.getMessage());
}finally {
try{
if(fr!=null){
fr.close();
}
}catch (IOException e){
System.out.println(e.getMessage());
}
}
}
FileReader 将字符读入数组
int read(char[] cbuf):发生IO错误或者已到达流的末尾前,此方法一直阻塞
参数cbuf:目标缓存区;
返回:读取的字符数;如果已到达流的末尾,则返回-1;
public static void main(String[] args) throws IOException {
// 创建文件读取流对象,和指定名称的文件相关联
// 要保证文件已经存在,否则会发生FileNotFoundException异常
FileReader fr = new FileReader("a.txt");
// 一般会定义1024的整数倍
char[] buff = new char[7];
int num = 0;
while ((num=fr.read(buff)) != -1){
System.out.println(new String(buff,0,num));
}
fr.close();
}
拷贝文本文件
字符流的缓冲区
一、缓冲区用于提高数据的读写效率
二、缓冲区对应的类,BufferWriter,BufferReader
三、缓冲区要结合流才可以使用,在流的基础上对流的功能加强
BufferWriter
一、将文本写入字符输出流,缓冲各个字符,从而提高单字符、数字、字符串的高效写入。
public static void main(String[] args) throws IOException {
// 创建一个字符写入流对象
FileWriter fw = new FileWriter("a.txt");
// 添加缓冲区,缓冲区的本质是数组
BufferedWriter bw = new BufferedWriter(fw);
bw.write("asdfg");
// 跨平台的换行符,
// linux 换行是\n,win的换行是\r\n
// newLine()支持跨平台
bw.newLine();
bw.flush();
// 关闭缓冲区,就是关闭缓冲区的流对象
bw.close();
}
BufferReader
public static void main(String[] args) throws IOException {
// 创建一个字符读取流对象
FileReader fr = new FileReader("a.txt");
// 添加缓冲区,缓冲区的本质是数组
BufferedReader br = new BufferedReader(fr);
// 读一行
String line = null;
while ((line=br.readLine())!=null){
System.out.println(line);
}
// 读一个字符
System.out.println(br.read());
// 关闭缓冲区,就是关闭缓冲区的流对象
br.close();
}
readLine()的原理
LineNumberReader
BufferReader的子类,也是用于增强Read类功能的。但是增加了设置行号和获取行号的功能
class Demo {
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("");
LineNumberReader inr = new LineNumberReader(fr);
inr.setLineNumber(0);
String line= null;
while((line=inr.readLine())!=null){
System.out.println(inr.getLineNumber() + ":"+line);
}
}
}
FileOutputStream
写字节,可操作文件
public static void main(String[] args) throws IOException {
FileOutputStream fi = new FileOutputStream("out.txt");
// 使用字节流,没有使用缓存区的话不需要使用fi.flush()
fi.write("s".getBytes());
fi.close();
}
FileInputStream
读字节,可操作文件
public static void main(String[] args) throws IOException {
FileInputStream fi = new FileInputStream("a.txt");
// 读一个字节
fi.read();
// 将字符读入byte数组
byte[] buf = new byte[1024];
int leng=0;
while ((leng=fi.read(buf))!=-1){
System.out.println(new String(buf, 0, leng));
}
// fi.available() 获取字节总数
// 虚拟机启动,默认是64M内存。new 一个大的数组容易导致内存溢出,所以数据大时不建议使用此方式
byte[] buf2 = new byte[fi.available()];
fi.read(buf2);
System.out.println(new String(buf2));
fi.close();
}
字节流缓存区
BufferedInputStream
BufferedOutputStream
public static void main(String[] args) throws IOException {
BufferedInputStream bufis = new BufferedInputStream(new FileInputStream("c:\\a.mp3"));
BufferedOutputStream bufos = new BufferedOutputStream(new FileOutputStream("c:\\1.mp3"));
int by = 0;
// BufferedInputStream 中已经定义了byte数组,不需要再定义byte数组
while ((by=bufis.read())!=-1){
bufos.write(by);
}
bufis.close();
bufos.close();
}
读取键盘录入
System.in: 对应的标准输入设备是键盘,返回类型为InputStream
System.out: 对应的标准输出设备是控制台
System.in和System.out属于字节流
InputStream in = System.in;
int by = 0;
try {
by = in.read();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(by);
读取转换流
· InputStreamReader是字符流
· InputStreamReader:是字节流转向字符流的桥梁
· 可以指定编码
· 构造方法
InputStreamReader(InputStream in) 创建一个使用默认字符集的 InputStreamReader。
InputStreamReader(InputStream in, String charsetName) 创建使用指定字符集的 InputStreamReader。
参数:InputStream in:字节输入流,用来读取文件中保存的字节;String charsetName:指定的编码表名称,不区分大小写,可以是utf-8/UTF-8,gbk/GBK,…不指定默认使用UTF-8
写入转换流
· OutputStreamWriter是字符流
· OutputStreamWriter是字符流通向字节流的桥梁
OutputStreamWriter流的作用就是利用字节流(OutputStream)作为”底层“输出流然后构建字符内输出流,字符输出流输出字符到流中,然后通过指定的字符集把流中的字符编码成字节输出到字节流中。
· 可以指定编码
public void hello() throws IOException {
InputStream in = System.in;
InputStreamReader isr = new InputStreamReader(in);
BufferedReader br = new BufferedReader(isr);
OutputStream os = System.out;
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw);
while (true){
String a = null;
if((a=br.readLine())=="over"){
break;
}
bw.write(a);
bw.newLine();
bw.flush();
}
}
流操作的基本规律
一、
1、明确源和目的
源:输入流 InputStream Reader
目的:输出流 OutputStream Writer
2、明确操作的数据是否是纯文本
是:字符流
否:字节流
3、明确设备
输入设备:内存、硬盘、键盘
输出设备:内存、硬盘、控制台
二、常见需求:
1、将一个文本文件中的数据存储到另一个文本文件中
源:读取数据,可选InputStream Reader ;是纯文本,所以使用Reader;设备是硬盘文件,所以使用FileReader;提高效率使用BufferReader
BufferedReader br = new BufferedReader(new FileReader(“s.txt”));
目的:写数据,可选OutputStream Writer ;操作的是文件,所以使用Writer;设备是硬盘文件,所以使用FileWriter
BufferedWriter bw = new BufferedWriter(new FileWriter(“s.txt”));
2、将键盘录入的数据存储到文本文件中
源:读取数据,可选InputStream Reader ;是纯文本,所以使用Reader;设备是键盘,键盘是字节流(System.in),字节流转换字符流用InputStreamReader;提高效率使用BufferReader
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
目的:写数据,可选OutputStream Writer ;是纯文件,所以使用Writer;设备是硬盘文件,所以使用FileWriter
BufferedWriter bw = new BufferedWriter(new FileWriter(“s.txt”));
扩展:将键盘录入的数据按照指名的编码表 存储到文本文件中
FileWriter使用的是默认编码表GBK,只有转化流OutputStreamWriter可以指定编码表
目的:写数据,可选OutputStream Writer ;是纯文件,所以使用Writer;设备是硬盘文件,所以使用FileWriter;需要指定编码表,OutputStreamWrite可以指定编码;OutputStreamWriter的参数是字节输出流,OutputStreamWriter将字符流转换为字节流;FileOutputStream写字节,可操作文件。
BufferedWriter bw = new BufferedWriter(OutputStreamWriter(new FileOutputStream(“s.txt”), “utf-8”))
修改标准输入输出设备
System.setIn(new FileOutputStream(“ss.txt”));
System.setOut(new PrintStream(“aa.txt”));
可实现复制,不常用。