分为字符流和字节流
字符流:
Reader、Writer
字节流:
InputStream、OutputStream
利用FileWriter类创建文件并写入数据
FileWriter fw = null;
try {
//续写:fw = new FileWriter("H:\\a.txt",true);
fw = new FileWriter("H:\\a.txt");
fw.write("我");
fw.flush();
} catch (Exception e) {
// TODO: handle exception
} finally {
try {
if (fw != null) {
fw.close();
}
} catch (Exception e2) {
}
}
}
利用FileReader类读取文件中的数据
package com.itheima;
import java.io.*;
public class IO {
public static void main(String[] args) throws Exception {
method1();
}
public static void method1(){
FileReader fr = null;
try {
fr = new FileReader("H:\\a.txt");
int num;
//读取方法一:该方法返回的是字符,读到末尾返回-1
// while((num=fr.read())!=-1){
// System.out.println((char)num);
// }
// System.out.println(num);
//读取方法二:该方法返回的是读取到的字符个数,读到末尾返回-1
/*该方法把数据读取后按照数组的大小进行存
char[] arrs = new char[1024];
int nums = fr.read(arrs);*/
char[] arrs = new char[2];
int nums;
//下一次读取的数据存入数组时会覆盖上一次的数据
while((nums =fr.read(arrs))!=-1){
System.out.println(nums);
//这里为了控制打印的真实数据
System.out.println(new String(arrs,0,nums));
}
} catch (Exception e) {
// TODO: handle exception
} finally {
try {
if (fr != null) {
fr.close();
}
} catch (Exception e2) {
}
}
}
}
FileWriter和FileReader结合复制文件
package com.itheima;
import java.io.*;
public class IODemo {
public static void main(String[] args) {
FileReader fr = null;
FileWriter fw = null;
try {
fr = new FileReader("J:\\beishu.java");
fw = new FileWriter("D:\\脑经伤.java");
char[] c = new char[1024];
int num;
while((num=fr.read(c))!=-1){
fw.write(c,0,num);
}
} catch (Exception e) {
} finally{
try {
if(fr!=null){
fr.close();
}
if(fw!=null){
fw.close();
}
} catch (Exception e2) {
}
}
}
}
BufferedWriter类
写入流缓冲区,
作用:为了提高流的写入效率
BufferedWriter bw = new BufferedWriter(new FileWriter("D\\a.txt));
特有方法:newLine()
作用:换行,相当于Windows里面的 \r\n
BufferedReader类
读取流缓冲区,
作用:为了提高流读取效率
BufferedReader br = new BufferedReader(new FileReader("D:\\a.txt"));
特有方法:readLine(),返回值类型是String,读取到最后一行,返回值为null
作用:一次读取一行数据
BufferedWriter和BufferedReader结合复制文件
package com.itheima;
import java.io.*;
public class IODemo {
public static void main(String[] args) {
BufferedReader br = null;
BufferedWriter bw = null;
try {
br = new BufferedReader(new FileReader("J:\\beishu.java"));
bw = new BufferedWriter(new FileWriter("D:\\脑经伤.java"));
String str;
while((str=br.readLine())!=null){
bw.write(str);
bw.newLine();
bw.flush();
}
} catch (Exception e) {
} finally{
try {
if(br!=null){
br.close();
}
if(bw!=null){
bw.close();
}
} catch (Exception e2) {
}
}
}
}
装饰设计模式:
想要对已有的对象进行功能增强时,就要用到装饰设计模式。
定义一个类,将已有对象作为参数传入,基于已有的功能,并提供加强功能,这就是装饰设计模式。该类被称为装饰类。
例如BufferedReader或BufferedWriter类都是装饰类,都是基于原有的对象提供新的功能如newLine方法和readLine方法。
装饰类一般都是由构造方法传入被装饰的对象,并基于被装饰对象的功能,增加更强的功能。
LineNumberReader类
getLineNumber方法:获取行号
setLineNumber方法:设置行号的起始值
此类的作用是在打印的数据的每一行最前面加上行号,一般从1开始
字符流与字节流的区别:
1、字符流操作数据时其实底层是调用了字节流的缓冲区,例如当写入一个汉字时,一个汉字是两个字节,字符流先写入一个字节到缓冲区,然后再写入另一个字节,再去查表,这样才有了汉字的复制。
2、字符流写入数据时需要刷新缓冲区的原因是两个字节才是一个汉字字符
3、字节流写入数据时不需要刷新缓冲区内
FileInputStream类
与FileReader功能基本一致
特殊方法:available(),是用来定义一个刚刚好的缓冲区大小,也就是表示数组的长度,这个方法不常用。
复制MP3思路:
BufferedInputStream字节流读取缓冲区和BufferedOutputStream 字节流写入缓冲区
BufferedInputStream bws = new BufferedInputStream (new FileInputStream("D:\\a.mp3"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("D:\\b.mp3"));
缓冲区原理:
首先由FileInputStream读取流读取硬盘上的数据到缓冲区中,当缓冲区存满以后,再由BufferedReader的read方法从缓冲区中读取数据,每读一个字节,就把该字节写入此缓冲的输出流,最后存储到硬盘,完成Mp3的复制。
自定义BufferedInputStream的思路:
1、首先定义被装饰类对象引用,然后定义一个数组,也就是模拟的缓冲区,然后再定义一个计数器和指针
2、通过装饰类的构造方法传入被装饰类的对象进行实例化
3、定义Myread方法,方法里首先调用FileInputStream类的read方法把数据读取到缓冲区,也就是数组中
4、然后当数组存满时,再调用BufferedInputStream的read方法从缓冲区也就是数组中依次读取每个字节,根据指针也就是数组下标进行读取,每读一个字节计数器自增1
5、并由BufferedOutputStream的write方法把字节写入到输出流中
6、这里用计数器表明,当写完后再次继续往数组里存,这样重复下去,直到数据复制完。
通过自定义的Myread方法Mp3没有复制的原因:
因为Mp3文件都是由二进制数据组成的,可能在前八位都是1,每个字节由八位组成,这样读取到的第一个字节转换成十进制就是-1,int类型返回后,那么while循环就停止了,数据根本没有写入。
read方法返回值类型是int而不是byte的原因:
因为,在读取一个字节数据时,容易出现连续8个1的情况,连续8个1是-1.正好符合了流结束标记。所以为了避免流操作数据提前结束,
将读到的字节进行int类型的提升。解决的办法是在前面都补0,也就是把读取到的字节和255&一下,这样返回值就不是-1了,在保留该字节数据的同时,又避免-1的情况。
转换流什么时候用?
当涉及到字符编码转换时,需要用到转换流。