系列文章目录
JavaSE进阶01:继承、修饰符
JavaSE进阶02:多态、抽象类、接口
JavaSE进阶03:内部类、Lambda表达式
JavaSE进阶04:API中常用工具类
JavaSE进阶05:包装类、递归、数组的高级操作、异常
JavaSE进阶06:Collection集合、迭代器、List、ArrayList、LinkedList
JavaSE进阶07:泛型、Set集合、TreeSet、二叉树、红黑树
JavaSE进阶08:HashSet、Map集合、HashMap、TreeMap、可变参数、不可变集合
JavaSE进阶09:Stream流、File类
JavaSE进阶10:IO流、字节流、字节缓冲流
JavaSE进阶11:字符流、字符缓冲流、转换流、对象操作流、Properties集合
JavaSE进阶12:多线程、线程同步、线程池
JavaSE进阶13:网络编程入门、UDP通信程序、TCP通信程序、日志、枚举
JavaSE进阶14:类加载器、反射
JavaSE进阶15:XML、注解、单元测试
JavaSE进阶扩充:JDK8 HashMap底层分析(了解)
JavaSE进阶扩充:JDK8 ArrayList线程安全问题和源码分析、集合常见面试题
Java进阶作业
1.IO
1.1 IO 的概述【了解】
1.什么IO流(输入和输出站在内存方来说的)
I表示intput,是数据从硬盘进内存的过程,称之为读
O表示output,是数据从内存到硬盘的过程,称之为写
流是一种抽象概念,数据在设备间的传输称为流,流的本质是数据传输
1.2 IO流分类【重点】
IO流的体系
写=输出流
读=输入流
- 字节流的抽象基类
- InputStream:这个抽象类是表示字节输入流的所有类的超类
- OutputStream:这个抽象类是表示字节输出流的所有类的超类
- 子类名特点:子类名称都是以其父类名作为子类名的后缀
- 字节流和字符流的区别
- 字节流可以操作所有类型的文件,如音频视频图片等
- 字符流只能操作存文本文件,如java文件txt文件等
- 文件用记事本打开是乱码,用的就是字节流。
2.字节流
2.1 字节流的输出流(写)
2.1.1 字节输出流概述【重点】
- 构造方法
方法 | 说明 |
---|---|
FileOutputStream(File file)) | 创建文件输出流以写入由指定的 File对象表示的文件 |
FileOutputStream(String name) | 创建文件输出流以写入由指定路径表示的文件 |
- 写数据的方法分类
方法名 | 说明 |
---|---|
void write(int b) | 将指定的字节写入此文件输出流 一次写一个字节数据 |
void write(byte[] b) | 将 b.length字节从指定的字节数组写入此文件输出流 一次写一个字节数组数据 |
void write(byte[] b, int off, int len) | 将 len字节从指定的字节数组开始,从偏移量off开始写入此文件输出流 一次写一个字节数组的部分数据 |
- 注意事项 (了解)
- 创建字节输出流对象
- 如果文件不存在,就创建
- 如果文件存在就清空
- 但是要保证父级路径存在,否则报错FileNotFoundException
- 写数据
- 写出的整数,实际写出的整数是在码表上对应的字符。
- 释放资源 (关流)
- 每次使用完流必须要释放资源。
- 每次使用完流必须要释放资源。
- 创建字节输出流对象
import java.io.FileOutputStream;
import java.io.IOException;
public class OutputDemo1 {
public static void main(String[] args) throws IOException {
//1.创建字节输出流的对象
//注意点:如果文件不存在,会帮我们自动创建出来;如果文件存在,会把文件清空。但是要保证父级路径存在,否则报错FileNotFoundException。
FileOutputStream fos = new FileOutputStream("D:\\JavaIOSpace\\a.txt");
//2,写数据:传递一个整数时,那么实际上写到文件中的,是这个整数在码表中对应的那个字符.
fos.write(98);//文件里写b
//3,释放资源
fos.close(); //告诉操作系统,我现在已经不再用这个文件了.
}
}
2.1.2 一次写多个数据【重点】
import java.io.FileOutputStream;
import java.io.IOException;
public class OutputDemo2 {
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream("D:\\JavaIOSpace\\a.txt");
byte [] bys1 = {97,98,99};
fos.write(bys1);//写入abc
byte [] bys2 = {97,98,99,100,101,102,103};
fos.write(bys2,1,2);//写入bc
fos.close();
}
}
/*
最终a.txt里:abcbc
*/
2.1.3 写数据的换行和追加写入【重点】
- 字节流写数据如何实现换行:
- windows:\r\n
- linux:\n
- mac:\r
- 尽量什么系统用什么换行符
字节流写数据实现追加写入:
- ublic FileOutputStream(String name,boolean append)
- 创建文件输出流以指定的名称写入文件。如果第二个参数为true ,则字节将写入文件的末尾而不是开头
注意事项:
import java.io.FileOutputStream;
import java.io.IOException;
public class OutputDemo3 {
public static void main(String[] args) throws IOException {
//第二个参数就是续写开关,如果没有传递,默认就是false,
//表示不打开续写功能,那么创建对象的这行代码会清空文件.
//如果第二个参数为true,表示打开续写功能
//那么创建对象的这行代码不会清空文件.
FileOutputStream fos = new FileOutputStream("D:\\JavaIOSpace\\a.txt",true);//true打开续写
fos.write(97);
fos.write("\r".getBytes());
fos.write(98);
fos.write("\n".getBytes());
fos.write(99);
fos.write("\r\n".getBytes());
fos.write(100);
fos.close();
}
}
2.1.4 try-catch-finally捕获异常【重点】
异常可以throws抛出,也可以主动捕获,但是close方法一定要放在finally里。
- 异常处理格式
try{
可能出现异常的代码;
}catch(异常类名 变量名){
异常的处理代码;
}finally{
执行所有清除操作;
}
- 为什么要使用finally
被finally控制的语句一定会执行,不管有没有异常,也不管异常有没有被捕获,除非JVM退出外,都一定被执行。
import java.io.FileOutputStream;
import java.io.IOException;
public class OutputDemo4 {
public static void main(String[] args) {
FileOutputStream fos = null;
try {
//System.out.println(2/0); 报错
fos = new FileOutputStream("D:\\a.txt");
fos.write(97);
//fos.close();若前面报错,则不能关闭流,导致资源无法释放。
}catch(IOException e){
e.printStackTrace();
}finally {
//finally语句里面的代码,一定会被执行.
if(fos != null){
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
2.1.5 小结【重点】
步骤:
- 创建字符输出流对象
文件不存在就创建
文件存在就清空,如果不想被清空则加true - 写数据
可以写一个字节,写一个字节数组,写一个字节数组的一部分
写一个回车换行:\r\n - 释放资源
2.2 字节流的输入流(读)
2.2.1字节输入流概述【重点】
-
如何读文件?
import java.io.FileInputStream类
-
构造方法
方法 | 说明 |
---|---|
FileInputStream(File file) | 通过打开与实际文件的连接来创建一个 FileInputStream,该文件由文件系统中的 File对象 file命名。 |
FileInputStream(String name) | 通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的路径名 name命名 |
- 读数据的方法分类
方法 | 说明 |
---|---|
int read() | 从该输入流读取一个字节的数据 |
public int read(byte[] b) throws IOException | 从输入流读取最多b.length 个字节的数据放入数组中 |
public void write(byte b[], int off, int len) throws IOException | 从字节数组下标off开始,将其中len个数据写入到文件的输出流中 |
读方法返回的是字节的ascii码,若返回-1说明已经读到文件末尾。 |
- 字节输入流读取文件数据的步骤
- 创建字节输入流对象
- 调用字节输入流对象的读数据方法
- 释放资源
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
public class OutputDemo5 {
public static void main(String[] args) throws IOException {
//如果文件存在,那么就不会报错.
//如果文件不存在,那么就直接报错.
FileInputStream fis = new FileInputStream("D:\\JavaIOSpace\\a.txt");
int read = fis.read();
//一次读取一个字节,返回值就是本次读到的那个字节数据.
//也就是字符在码表中对应的那个数字.
//如果我们想要看到的是字符数据,那么一定要强转成char
System.out.println(read);//97
System.out.println((char)read);//a
//释放资源
fis.close();
File file=new File("D:\\JavaIOSpace\\b.txt");//新建b.txt什么都不写
FileInputStream fis2 = new FileInputStream(file);
System.out.println(fis2.read());//输出-1,已经读到文件尾部
fis2.close();
}
}
/*
97
a
-1
*/
2.2.2 读取多个字节 (重点)
import java.io.FileInputStream;
import java.io.IOException;
public class OutputDemo6 {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("D:\\JavaIOSpace\\a.txt");
int b=0;
while ((b = fis.read())!=-1){
System.out.print(b+":");
System.out.println((char) b);
}
}
}
/*
97:a
13:
98:b
10:
99:c
13:
10:
100:d
*/
2.2.3 复制文件【重点】
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class OutputDemo7 {
public static void main(String[] args) throws IOException {
//创建了字节输入流,准备读数据.
FileInputStream fis = new FileInputStream("D:\\JavaIOSpace\\a.txt");//路径必须存在否则报错
//创建了字节输出流,准备写数据.
FileOutputStream fos = new FileOutputStream("D:\\JavaIOSpace\\aBack.txt");//没有会自己创建
int b;
while((b = fis.read())!=-1){
fos.write(b);
}
fis.close();
fos.close();
}
}
不过一次循环读一个字符效率非常低,所以一下就定义数组来读取一块字节。
2.2.4 定义小数组拷贝文件【重点】
-
如何提高文件拷贝的速度?
- 循环一次性读写多个字节
-
有参读方法
方法 | 说明 |
---|---|
public int read(byte[] b) throws IOException | 从输入流读取最多b.length 个字节的数据放入数组中 |
public void write(byte b[], int off, int len) throws IOException | 从字节数组下标off开始,将其中len个数据写入到文件的输出流中 |
- 注意事项
- 数组长度并不越大越好,因为开辟过大的数组会占用非常多的内存,但利用率却不高。一般设置1024,若文件很大可设2048。
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class OutputDemo8{
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("D:\\JavaIOSpace\\a.txt");
FileOutputStream fos = new FileOutputStream("D:\\JavaIOSpace\\aBack.txt");
byte [] bytes = new byte[1024];
int len;//本次读到的有效字节个数 --- 这次读了几个字节
while((len = fis.read(bytes))!=-1){//一次读多个(最多1024个)字节,本次没读到末尾就进入循环,本次读到末尾跳出循环
System.out.println(bytes.toString());
fos.write(bytes,0,len);//将本次数组中的全部数据写入到目标文件
}
fis.close();
fos.close();
}
}
2.2.5 小数组拷贝的原理【难点】
3.字节缓冲流
3.1字节缓冲流-一次读写一个字节代码实现【重点】
1.字节缓冲流介绍
- BufferedOutputStream:字节缓冲输出流
- BufferedInputStream: 字节缓冲输入流
- 缓冲流仅仅是提高效率的工具,真正干活的还是字节流
2.如何使用?
- 构造方法
方法名 | 说明 |
---|---|
BufferedOutputStream(OutputStream out) | 创建字节缓冲输出流对象 |
BufferedInputStream(InputStream in) | 创建字节缓冲输入流对象 |
- 为什么构造方法需要的是字节流,而不是具体的文件或者路径?
- 字节缓冲流仅仅提供缓冲区,而真正的读写数据还是依靠基本的字节流对象进行操作
- 常用用方法
方法 | 说明 |
---|---|
public int read() throws IOException | 从输入流中读出8192个字节到缓冲数组中,再从缓冲数组中取出一个字节 |
public void write(int b) throws IOException | 将字节b写入到缓冲数组中,当缓冲数组满时,一次性写入目标文件 |
示例代码
import java.io.*;
public class OutputDemo11 {
public static void main(String[] args) throws IOException {
//就要利用缓冲流去拷贝文件
//创建一个字节缓冲输入流
//在底层创建了一个默认长度为8192的字节数组。
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("D:\\JavaIOSpace\\a.txt"));
//创建一个字节缓冲输出流
//在底层也创建了一个默认长度为8192的字节数组。
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("D:\\JavaIOSpace\\aBack.txt"));
int b;
while((b = bis.read()) != -1){
bos.write(b);
}
//缓冲流关闭,底层也会把字节流给关闭。
bis.close();
bos.close();
}
}
3.2字节缓冲流一次读写一个字节代码原理【难点 】
缓冲输入和输出的数组是在内存中,所以速度非常快。
1.字节缓冲输入流每次读取buffer长度个字节
2.字节缓冲输出流写数据时先将缓冲字节输入流缓冲数组中的数据每次转移1个字节到自己的缓冲数组中,当缓冲数组满时,字节流一次性写出缓冲数组长度个字节
3.如果缓冲数组不满时,当调用缓冲流的close()方法时会将缓冲数组中数据写出
3.3字节缓冲流一次读写一个字节数组【重点 】
- 常用方法
方法 | 说明 |
---|---|
public int read(byte b[]) throws IOException | 从输入流中读出8192个字节到缓冲数组中,再从缓冲数组中取出数组b.length个字节到数组b中 |
public void write(byte b[], int off, int len) throws IOException | 将数组b中的元素,从下标0开始,向缓冲数组中写入len个字节,当缓冲数组满时,一次性写入目的地 |
package com.itheima.output;
import java.io.*;
public class OutputDemo12 {
public static void main(String[] args) throws IOException {
//缓冲流结合数组,进行文件拷贝
//创建一个字节缓冲输入流
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("D:\\JavaIOSpace\\a.txt"));
//创建一个字节缓冲输出流
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("D:\\JavaIOSpace\\aBack.txt"));
byte [] bytes = new byte[1024];
int len;
while((len = bis.read(bytes)) != -1){
bos.write(bytes,0,len);
}
bis.close();
bos.close();
}
}
- 原理图
缓冲输入和输出的数组是在内存中,所以速度非常快。
1.字节缓冲输入流每次读取buffer长度个字节
2.字节缓冲输出流写数据时先将缓冲字节输入流缓冲数组中的数据每次转移bytes长度个字节到自己的缓冲数组中,当缓冲数组满时,字节流一次性写出缓冲数组长度个字节
3.如果缓冲数组不满时,当调用缓冲流的close()方法时会将缓冲数组中数据写出
3.4 小结 【重点】
- 字节流:
- 可以操作(拷贝)所有类型的文件
- 字节缓冲流:
- 可以提高效率
- 不能直接操作文件,需要传递字节流
- 拷贝文件的四种方式
- 字节流一次读写一个字节
- 字节流一次读写一个数组
- 字节缓冲流一次操作一个字节
- 字节缓冲流一次操作一个字节数组