字节流
IO流(定义小数组的标准格式)
IO流(利用缓冲区实现)IO流利用缓冲区实现
IO流(给图片加密)
IO流(字节流读写中文)
字符流
IO流(自定义字符数组的拷贝)
IO流(字符流的拷贝)
IO流(自定义字符数组的拷贝)
IO流(带缓冲的字符流)
IO流(以行为单位读取)
– IO流(LineNumberReader(行号相关处理))
IO流(使用指定的码表读写字符)
20.01_IO流(IO流概述及其分类)
- 1.概念
- IO流用来处理设备之间的数据传输
- Java对数据的操作是通过流的方式
- Java用于操作流的类都在IO包中
- 流按流向分为两种:输入流,输出流。
- 流按操作类型分为两种:
- 字节流 :字节流可以操作任何数据,因为在计算机中任何数据都是以字节的形式存储的
- 字符流 :字符流只能操作纯字符数据,比较方便。
- 2.IO流常用父类
- 字节流的抽象父类:
*InputStream
*OutputStream - 字符流的抽象父类:
- Reader
- Writer
- 字节流的抽象父类:
- 3.IO程序书写
- 使用前,导入IO包中的类
- 使用时,进行IO异常处理
- 使用后,释放资源
20.02_IO流(FileInputStream)
read()一次读取一个字节
*
FileInputStreamfis = new FileInputStream(“aaa.txt”); //创建一个文件输入流对象,并关联aaa.txt
int b; //定义变量,记录每次读到的字节
while((b= fis.read()) != -1) { //将每次读到的字节赋值给b并判断是否是-1
System.out.println(b); //打印每一个字节
}fis.close(); //关闭流释放资源
20.03_IO流(read()方法返回值为什么是int)
- read()方法读取的是一个字节,为什么返回是int,而不是byte
*
因为字节输入流可以操作任意类型的文件,比如图片音频等,这些文件底层都是以二进制形式的存储的,如果每次读取都返回byte,有可能在读到中间的时候遇到111111111
那么这11111111是byte类型的-1,我们的程序是遇到-1就会停止不读了,后面的数据就读不到了,所以在读取的时候用int类型接收,如果11111111会在其前面补上
24个0凑足4个字节,那么byte类型的-1就变成int类型的255了这样可以保证整个数据读完,而结束标记的-1就是int类型
20.04_IO流(FileOutputStream)
- write()一次写出一个字节
*
FileOutputStreamfos = new FileOutputStream(“bbb.txt”); //如果没有bbb.txt,会创建出一个
//fos.write(97); //虽然写出的是一个int数,但是在写出的时候会将前面的24个0去掉,所以写出的一个byte
fos.write(98);
fos.write(99);
fos.close();
20.05_IO流(FileOutputStream追加)
- A:案例演示
*FileOutputStream的构造方法写出数据如何实现数据的追加写入
*
FileOutputStreamfos = new FileOutputStream(“bbb.txt”,true); //如果没有bbb.txt,会创建出一个
//fos.write(97); //虽然写出的是一个int数,但是在写出的时候会将前面的24个0去掉,所以写出的一个byte
fos.write(98);
fos.write(99);
fos.close();
20.06_IO流(拷贝图片)
- FileInputStream读取
FileOutputStream写出
FileInputStreamfis = new FileInputStream("致青春.mp3"); //创建输入流对象,关联致青春.mp3 FileOutputStreamfos = new FileOutputStream("copy.mp3");//创建输出流对象,关联copy.mp3 int b; while((b= fis.read()) != -1) { fos.write(b); } fis.close(); fos.close();
20.07_IO流(拷贝音频文件画原理图)
- A:案例演示
- 字节流一次读写一个字节复制音频
- 弊端:效率太低
20.08_IO流(字节数组拷贝之available()方法)
- A:案例演示
- intread(byte[] b):一次读取一个字节数组
*write(byte[] b):一次写出一个字节数组 - available()获取读的文件所有的字节个数
- intread(byte[] b):一次读取一个字节数组
弊端:有可能会内存溢出
FileInputStreamfis = new FileInputStream("致青春.mp3"); FileOutputStreamfos = new FileOutputStream("copy.mp3"); byte[]arr = new byte[fis.available()]; //根据文件大小做一个字节数组 fis.read(arr); //将文件上的所有字节读取到数组中 fos.write(arr); //将数组中的所有字节一次写到了文件上 fis.close(); fos.close();
20.09_IO流(定义小数组)
- write(byte[] b)
- write(byte[] b, int off, int len)写出有效的字节个数
20.10_IO流(定义小数组的标准格式)
A:案例演示
字节流一次读写一个字节数组复制图片和视频
FileInputStreamfis = new FileInputStream(“致青春.mp3”);
FileOutputStreamfos = new FileOutputStream(“copy.mp3”);
int len;
byte[]arr = new byte[1024 * 8]; //自定义字节数组while((len= fis.read(arr)) != -1) {
//fos.write(arr);
fos.write(arr,0, len); //写出字节数组写出有效个字节个数
}fis.close();
fos.close();
20.11_IO流(BufferedInputStream和BufferOutputStream拷贝)
IO流利用缓冲区实现
* A:缓冲思想
* 字节流一次读写一个数组的速度明显比一次读写一个字节的速度快很多,
* 这是加入了数组这样的缓冲区效果,java本身在设计的时候,
* 也考虑到了这样的设计思想(装饰设计模式后面讲解),所以提供了字节缓冲区流
* B.BufferedInputStream
*BufferedInputStream内置了一个缓冲区(数组)
* 从BufferedInputStream中读取一个字节时
*BufferedInputStream会一次性从文件中读取8192个, 存在缓冲区中, 返回给程序一个
* 程序再次读取时, 就不用找文件了, 直接从缓冲区中获取
* 直到缓冲区中所有的都被使用过, 才重新从文件中读取8192个
* C.BufferedOutputStream
*BufferedOutputStream也内置了一个缓冲区(数组)
* 程序向流中写出字节时, 不会直接写到文件, 先写到缓冲区中
* 直到缓冲区写满, BufferedOutputStream才会把缓冲区中的数据一次性写到文件里
* D.拷贝的代码
FileInputStreamfis = new FileInputStream("致青春.mp3"); //创建文件输入流对象,关联致青春.mp3
BufferedInputStreambis = new BufferedInputStream(fis); //创建缓冲区对fis装饰
FileOutputStreamfos = new FileOutputStream("copy.mp3"); //创建输出流对象,关联copy.mp3
BufferedOutputStreambos = new BufferedOutputStream(fos); //创建缓冲区对fos装饰
int b;
while((b= bis.read()) != -1) {
bos.write(b);
}
bis.close(); //只关装饰后的对象即可
bos.close();
- E.小数组的读写和带Buffered的读取哪个更快?
- 定义小数组如果是8192个字节大小和Buffered比较的话
- 定义小数组会略胜一筹,因为读和写操作的是同一个数组
- 而Buffered操作的是两个数组
20.12_IO流(flush和close方法的区别)
- flush()方法
- 用来刷新缓冲区的,刷新后可以再次写出
- close()方法
- 用来关闭流释放资源的的,如果是带缓冲区的流对象的close()方法,不但会关闭流,还会再关闭流之前刷新缓冲区,关闭后不能再写出
20.13_IO流(字节流读写中文)
- 字节流读取中文的问题
- 字节流在读中文的时候有可能会读到半个中文,造成乱码
- 字节流写出中文的问题
- 字节流直接操作的字节,所以写出中文必须将字符串转换成字节数组
“你好”.getBytes(); - 写出回车换行 write(“\r\n”.getBytes());
- 字节流直接操作的字节,所以写出中文必须将字符串转换成字节数组
20.14_IO流(流的标准处理异常代码1.6版本及其以前)
try finally嵌套
FileInputStreamfis = null; FileOutputStreamfos = null; try { fis =new FileInputStream("aaa.txt"); fos =new FileOutputStream("bbb.txt"); intb; while((b= fis.read()) != -1) { fos.write(b); } } finally{ try { if(fis!= null) fis.close(); }finally{ if(fos!= null) fos.close(); } }
20.15_IO流(流的标准处理异常代码1.7版本)
try close
try( FileInputStreamfis = new FileInputStream("aaa.txt"); FileOutputStreamfos = new FileOutputStream("bbb.txt"); MyClosemc = new MyClose(); ){ intb; while((b= fis.read()) != -1) { fos.write(b); } }
- 原理
- 在try()中创建的流对象必须实现了AutoCloseable这个接口,如果实现了,在try后面的{}(读写代码)执行后就会自动调用,流对象的close方法将流关掉
20.16_IO流(图片加密)
给图片加密
同一个文件异或两次就等于原来的数,即等于本身
BufferedInputStreambis = new BufferedInputStream(new FileInputStream(“a.jpg”));
BufferedOutputStreambos = new BufferedOutputStream(new FileOutputStream(“b.jpg”));int b; while((b= bis.read()) != -1) { bos.write(b^ 123); } bis.close(); bos.close();
20.17_IO流(拷贝文件)
在控制台录入文件的路径,将文件拷贝到当前项目下
Scannersc = new Scanner(System.in); System.out.println("请输入一个文件路径"); String line= sc.nextLine(); //将键盘录入的文件路径存储在line中 File file= new File(line); //封装成File对象 FileInputStreamfis = new FileInputStream(file); FileOutputStreamfos = new FileOutputStream(file.getName()); int len; byte[]arr = new byte[8192]; //定义缓冲区 while((len= fis.read(arr)) != -1) { fos.write(arr,0,len); } fis.close(); fos.close();
20.18_IO流(录入数据拷贝到文件)
将键盘录入的数据拷贝到当前项目下的text.txt文件中,键盘录入数据当遇到quit时就退出
Scannersc = new Scanner(System.in); FileOutputStreamfos = new FileOutputStream("text.txt"); System.out.println("请输入:"); while(true){ Stringline = sc.nextLine(); if("quit".equals(line)) break; fos.write(line.getBytes()); fos.write("\r\n".getBytes()); } fos.close();
21.01_IO流(字符流FileReader)
- 1.字符流是什么
- 字符流是可以直接读写字符的IO流
- 字符流读取字符, 就要先读取到字节数据, 然后转为字符.如果要写出字符, 需要把字符转为字节再写出.
2.FileReader
FileReader类的read()方法可以按照字符大小读取
*
FileReader fr = new FileReader(“aaa.txt”); //创建输入流对象,关联aaa.txt
int ch;
while((ch =fr.read()) != -1) { //将读到的字符赋值给ch
System.out.println((char)ch); //将读到的字符强转后打印
}fr.close(); //关流
21.02_IO流(字符流FileWriter)
FileWriter类的write()方法可以自动把字符转为字节写出
FileWriterfw = new FileWriter("aaa.txt"); fw.write("aaa"); fw.close();
21.03_IO流(字符流的拷贝)
FileReader fr= new FileReader("a.txt");
FileWriter fw= new FileWriter("b.txt");
int ch;
while((ch =fr.read()) != -1) {
fw.write(ch);
}
fr.close();
fw.close();
21.04_IO流(什么情况下使用字符流)
- 字符流也可以拷贝文本文件, 但不推荐使用. 因为读取时会把字节转为字符, 写出时还要把字符转回字节.
- 程序需要读取一段文本, 或者需要写出一段文本的时候可以使用字符流
- 读取的时候是按照字符的大小读取的,不会出现半个中文
- 写出的时候可以直接将字符串写出,不用转换为字节数组
21.05_IO流(字符流是否可以拷贝非纯文本的文件)
- 不可以拷贝非纯文本的文件
- 因为在读的时候会将字节转换为字符,在转换过程中,可能找不到对应的字符,就会用?代替,写出的时候会将字符转换成字节写出去
- 如果是?,直接写出,这样写出之后的文件就乱了,看不了了
21.06_IO流(自定义字符数组的拷贝)
FileReaderfr = new FileReader("aaa.txt"); //创建字符输入流,关联aaa.txt FileWriterfw = new FileWriter("bbb.txt"); //创建字符输出流,关联bbb.txt int len; char[]arr = new char[1024*8]; //创建字符数组 while((len= fr.read(arr)) != -1) { //将数据读到字符数组中 fw.write(arr,0, len); //从字符数组将数据写到文件上 } fr.close(); //关流释放资源 fw.close();
21.07_IO流(带缓冲的字符流)
- BufferedReader的read()方法读取字符时会一次读取若干字符到缓冲区, 然后逐个返回给程序, 降低读取文件的次数, 提高效率
BufferedWriter的write()方法写出字符时会先写到缓冲区, 缓冲区写满时才会写到文件, 降低写文件的次数, 提高效率
*
BufferedReaderbr = new BufferedReader(new FileReader(“aaa.txt”)); //创建字符输入流对象,关联aaa.txt
BufferedWriterbw = new BufferedWriter(new FileWriter(“bbb.txt”)); //创建字符输出流对象,关联bbb.txtint ch; while((ch= br.read()) != -1) { //read一次,会先将缓冲区读满,从缓冲去中一个一个的返给临时变量ch bw.write(ch); //write一次,是将数据装到字符数组,装满后再一起写出去 } br.close(); //关流 bw.close();
21.08_IO流(readLine()和newLine()方法)
IO流(以行为单位读取
* BufferedReader的readLine()方法可以读取一行字符(不包含换行符号)
* BufferedWriter的newLine()可以输出一个跨平台的换行符号”\r\n”
*
BufferedReaderbr = new BufferedReader(new FileReader(“aaa.txt”));
BufferedWriterbw = new BufferedWriter(new FileWriter(“bbb.txt”));
Stringline;
while((line= br.readLine()) != null) {
bw.write(line); //读取文件遇到换行时,不会主动换行
//bw.write(“\r\n”); //只支持windows系统
bw.newLine(); //跨平台的
}
br.close();
bw.close();
21.09_IO流(将文本反转)
- 将一个文本文档上的文本反转,第一行和倒数第一行交换,第二行和倒数第二行交换
21.10_IO流(LineNumberReader(行号相关处理))
LineNumberReader是BufferedReader的子类, 具有相同的功能, 并且可以统计行号
- 调用getLineNumber()方法可以获取当前行号
调用setLineNumber()方法可以设置当前行号
*
LineNumberReaderlnr = new LineNumberReader(new FileReader(“aaa.txt”));
String line;
lnr.setLineNumber(100); //设置行号
while((line= lnr.readLine()) != null) { //显示时行号从101开始
System.out.println(lnr.getLineNumber()+ “:” + line);//获取行号
}lnr.close();
21.11_IO流(装饰设计模式)
*
interfaceCoder {
publicvoid code();
}
classStudent implements Coder {
@Override
publicvoid code() {
System.out.println("javase");
System.out.println("javaweb");
}
}
classHeiMaStudent implements Coder {
privateStudent s; //获取到被包装的类的引用
publicItcastStudent(Student s) { //通过构造函数创建对象的时候,传入被包装的对象
this.s= s;
}
@Override
publicvoid code() { //对其原有功能进行升级
s.code();
System.out.println("数据库");
System.out.println("ssh");
System.out.println("安卓");
System.out.println(".....");
}
}
21.12_IO流(使用指定的码表读写字符)
- FileReader是使用默认码表读取文件, 如果需要使用指定码表读取, 那么可以使用InputStreamReader(字节流,编码表)
FileWriter是使用默认码表写出文件, 如果需要使用指定码表写出, 那么可以使用OutputStreamWriter(字节流,编码表)
*InputStreamReader和OutputStreamWriter是字符流,作用就是将字节流转换为字符流BufferedReaderbr = //高效的用指定的编码表读 newBufferedReader(new InputStreamReader(newFileInputStream("UTF-8.txt"), "UTF-8")); BufferedWriterbw = //高效的用指定的编码表写 newBufferedWriter(new OutputStreamWriter(newFileOutputStream("GBK.txt"), "GBK")); int ch; while((ch= br.read()) != -1) { bw.write(ch); } br.close(); bw.close();
21.13_IO流(转换流图解)
- 画图分析转换流
21.14_IO流(获取文本上字符出现的次数)
- 获取一个文本上每个字符出现的次数,将结果写在times.txt上
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
public class Test3 {
/**
- 获取一个文本上每个字符出现的次数,将结果写在times.txt上
- 分析:
- 1,创建带缓冲的输入流对象
- 2,创建双列集合对象TreeMap
- 3,将读到的字符存储在双列集合中,存储的时候要做判断,如果不包含这个键,就将键和1存储,如果包含这个键,就将该键和值加1存储
- 4,关闭输入流
- 5,创建输出流对象
- 6,遍历集合将集合中的内容写到times.txt中
- 7,关闭输出流
- @throws IOException
*/
public static void main(String[] args) throws IOException {
//1,创建带缓冲的输入流对象
BufferedReader br = new BufferedReader(new FileReader(“zzz.txt”));
//2,创建双列集合对象TreeMap
TreeMap
21.15_IO流(试用版软件)
- 当我们下载一个试用版软件,没有购买正版的时候,每执行一次就会提醒我们还有多少次使用机会用学过的IO流知识,模拟试用版软件,试用10次机会,执行一次就提示一次您还有几次机会,如果次数到了提示请购买正版
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public static void main(String[] args) throws IOException {
//1,创建带缓冲的输入流对象,因为要使用readLine方法,可以保证数据的原样性
BufferedReader br = new BufferedReader(new FileReader(“config.txt”));
//2,将读到的字符串转换为int数
String line = br.readLine();
int times = Integer.parseInt(line); //将数字字符串转换为数字
//3,对int数进行判断,如果大于0,就将其–写回去,如果不大于0,就提示请购买正版
if(times > 0) {
//4,在if判断中要将–的结果打印,并将结果通过输出流写到文件上
System.out.println(“您还有” + times– + “次机会”);
FileWriter fw = new FileWriter(“config.txt”);
fw.write(times + “”);
fw.close();
}else {
System.out.println(“您的试用次数已到,请购买正版”);
}
//关闭流
br.close();
}
21.16_File类(递归)
- 5的阶乘
21.17_File类(练习)
- 需求:从键盘输入接收一个文件夹路径,打印出该文件夹下所有的.java文件名
21.18_IO流(总结)
- 1.会用BufferedReader读取GBK码表和UTF-8码表的字符
- 2.会用BufferedWriter写出字符到GBK码表和UTF-8码表的文件中
- 3.会使用BufferedReader从键盘读取一行