0.写在前面
- 本笔记用作复习查看用,基础完整总结部分,基础不牢,地动山摇!
🔥Java帝国之行🔥 | 地址 |
---|---|
Java核心编程总结(一、继承) 🔥 | https://blog.csdn.net/Augenstern_QXL/article/details/116209463 |
Java核心编程总结(二、抽象类与接口)🔥 | https://blog.csdn.net/Augenstern_QXL/article/details/116209487 |
Java核心编程总结(三、多态与内部类)🔥 | https://blog.csdn.net/Augenstern_QXL/article/details/116209507 |
Java核心编程总结(四、异常与线程) 🔥 | https://blog.csdn.net/Augenstern_QXL/article/details/116209529 |
Java核心编程总结(五、线程池与死锁)🔥 | https://blog.csdn.net/Augenstern_QXL/article/details/116209580 |
Java核心编程总结(六、常用API与集合)🔥 | https://blog.csdn.net/Augenstern_QXL/article/details/116209607 |
Java核心编程总结(七、Stream流)🔥 | https://blog.csdn.net/Augenstern_QXL/article/details/116209624 |
Java核心编程总结(八、IO输入输出流)🔥 | https://blog.csdn.net/Augenstern_QXL/article/details/116209648 |
Java核心编程总结(九、File文件类)🔥 | https://blog.csdn.net/Augenstern_QXL/article/details/116209674 |
Java核心编程总结(十、反射) 🔥 | https://blog.csdn.net/Augenstern_QXL/article/details/117744497 |
1.基础回顾+面试
1.1字符集/编码集
字符集:各个国家为自己国家的字符取的一套编号规则
计算机底层是不能直接存储字符的,计算机底层只能存储二进制。010101
- ASCII编码:英文和数字在底层存储的时候都是采用1个字节存储的
- GBK编码:一个中文字符一般占用2个字节
- UTF-8:一个中文字符一般占3个字节
1.2IO流读写数据
-
为什么要学IO流?
答:File类只能操作文件对象本身,不能读写文件对象的内容
读写数据内容,应该使用IO流
-
IO流的分类
按照流的方向分为:
- 输入流:读取数据到内存
- 输出流:写数据到文件
按照流的内容分为:
- 字节流:流中的是数据的最小单位是一个一个的字节,这个流就是字节流
- 字符流:流中的数据的最小单位是一个一个的字符,这个流就是字符流
-
所以流大体分为四大类:
- 字节输入流:以内存为基准,把磁盘文件中的数据或者网络中的数据以一个一个字节的形式读入到内存中取的流称为字节输入流
- 字节输出流:以内存为基准,把内存中的数据以一个一个字节写出到磁盘文件或者网络介质中去的流称为字节输出流
- 字符输入流:以内存为基准,把磁盘文件的数据或者网络中的数据以一个一个字符的形式读入到内存中去的流称为字符输入流
- 字符输出流:以内存为基准,把内存中的数据以一个一个字符的形式写出到磁盘文件或者网络介质中去的流称为字符输出流
1.3字节输入流
字节输入流 | |
---|---|
InputStream | 抽象类 |
FileInputStream | 子类实现类(文件字节输入流) |
文件字节输入流作用:按照字节读取文件数据到内存
构造器:
public FileInputStream(File path)
:创建一个字节输入流管道与源文件对象接通public FileInputStream(String pathName)
: 创建一个字节输入流管道与文件路径对接
方法:
public int read()
:每次读取一个字节返回!读取完毕会返回-1public int read(byte[] buffer)
:从字节输入流中读取字节到字节数组中去,返回读取的字节数量,没有字节可读返回 -1
字节输入流的使用 - 按照一个字节读取
public class FileInputStreamDemo01 {
public static void main(String[] args) throws Exception {
// 1.创建文件对象定位dlei01.txt
File file = new File("Day09Demo/src/dlei01.txt");
// 2.创建一个字节输入流管道与源文件接通
InputStream is = new FileInputStream(file);
// 3.读取一个字节的编号返回,读取完毕返回-1
// int code1 = is.read(); // 读取一滴水,一个字节
// System.out.println((char)code1);
//
// int code2 = is.read(); // 读取一滴水,一个字节
// System.out.println((char)code2);
//
// int code3 = is.read(); // 读取一滴水,一个字节
// System.out.println((char)code3);
//
// int code4 = is.read(); // 读取一滴水,一个字节 ,读取没有字节返回-1
// System.out.println(code4);
// 4.使用while读取字节数
// 定义一个整数变量存储字节
int ch = 0 ;
while((ch = is.read())!= -1){
System.out.print((char) ch);
}
}
}
- 一个一个字节读取英文和数字没有问题。因为UTF-8中英文和数字占一个字节
- 但是一旦读取中文输入无法避免乱码,因为会截断中文的字节
- 一个一个字节的读取,性能较差,所以禁止使用此方案
字节输入流的使用 - 按照字节数组读取
public class FileInputStreamDemo02 {
public static void main(String[] args) throws Exception {
// 需求:读取文件中的数据输出。
// 1.创建一个文件对象
//File srcFile = new File("Day09Demo/src/dlei02.txt");
// 2.创建一个字节输入流管道与源文件对象接通。
//InputStream is = new FileInputStream(srcFile);
// 3.简化写法:直接创建一个字节输入流管道与源文件路径接通。
InputStream is = new FileInputStream("Day09Demo/src/dlei02.txt");
// a.定义一个字节数组代表桶 // ooo ooo o
byte[] buffer = new byte[3];
int len ; // 存储每次读取的字节数。
while((len = is.read(buffer)) != -1){
// 读取了多少就倒出多少!
String rs = new String(buffer , 0 , len);
System.out.print(rs);
}
}
}
- 使用字节数组读取内容,效率可以
- 但是字节数组读取文本内容输出,也无法避免中文读取输出乱码的问题
- 字节流并不适合读取文本文件内容输出,读写文件内容建议使用字符流
1.4字节输出流
字节输出流 | |
---|---|
OutputStream | 抽象类 |
FileOutputStream | 实现类(文件字节输出流) |
FileOutputStream
: 把内存数据按照字节写出到磁盘文件中去
构造器:
public FileOutputStream(File file)
: 创建一个字节输出流管道通向目标文件对象public FileOutputStream(String file)
: 创建一个字节输出流管道通向目标文件路径public FileOutputStream(File file,boolean append)
:创建一个追加数据的字节输出流管道通向目标文件对象public FileOutputStream(String file,boolean append)
:创建一个追加数据的字节输出流管道通向目标文件路径
方法:
public void write(int a)
:写一个字节出去public void write(byte[] buffer)
:写一个字节数组出去public void write(byte[] buffer,int pos,int len)
:写一个字节数组的一部分出去- 参数一:字节数组
- 参数二:起始字节索引位置
- 参数三:写多少个字节数出去
public class OutputStreamDemo04 {
public static void main(String[] args) throws Exception {
// 1. 创建一个文件对象定位目标文件(写数据到文件,文件会自动创建)
// File file = new File("Day09Demo/src/dlei04.txt");
// 2. 创建一个字节输出流管道与目标文件对象接通
// OutputStream os = new FileOutputStream(file);
// 3.简化写法:创建一个字节输出流管道与目标文件路径接通
// 追加数据管道,第二个参数是true,这样在写入字节进去就不会清空管道
// OutputStream os = new FileOutputStream("Day09Demo/src/dlei04.txt",true);
OutputStream os = new FileOutputStream("Day09Demo/src/dlei04.txt");
// 4. 写数据出去
// a.写一个字节出去(写一滴水出去)
os.write(97); // 字节a
os.write('b'); // 字节b
// os.write('磊'); // [ooo] 只会写出中文的第一个字节,写出去就乱码!
os.write("\r\n".getBytes()); // 换行
// b.写一个字节数组出去(写一个桶出去)
byte[] bytes = new byte[]{99,100,101,104};
os.write(bytes);
byte[] bytes1 = "Java语言很优美".getBytes(); // 默认以当前代码编码UTF-8提取字节数组
// byte[] bytes1 = "Java语言很优美".getBytes("GBK"); // 指定编码获取字节数组
os.write(bytes1);
// c. 写一个字节数组的一部分出去
byte[] bytes2 = "Java是很优美的语言".getBytes();
os.write(bytes2,0,19);
os.write("\r\n".getBytes()); // 换行
// os.flush(); // 立即刷新数据到文件中去,刷新后管道可以继续使用
os.close(); // 关闭资源管道,关闭包含了刷新,关闭后管道不能使用
}
}
- 字节输出流可以写字节数据到文件中去
- 字节输出流默认是覆盖数据管道(每次启动写数据的时候都会先清空之前的全部数据,重新写入)
- 换行用:
os.write("\r\n".getBytes())
- 写一个字节,写一个字节数组,写一个字节数组的一部分出去
- 管道用完需要关闭,数据生效需要刷新,关闭包含刷新,刷新后流可以继续使用,关闭后流无法继续使用
1.5字符输入流
字符输入流 | |
---|---|
Reader | 抽象类 |
FileReader | 实现类(文件字符输入流) |
FileReader文件字符输入流作用:读取文本文件内容到内存中去
构造器:
public FileReader(File file)
:创建一个字符输入流与源文件对象接通public FileReader(String filePath)
:创建一个字符输入流与源文件路径接通
方法:
public int read()
: 读取一个字符的编号返回!读取完毕返回-1public int read(char[] buffer)
: 读取一个字符数组,读取多少个字符就返回多少个数量,读取完毕返回-1
字符流一个一个字符的读取文本内容输入
public class FileReaderDemo01 {
public static void main(String[] args) throws Exception {
// 1.创建一个文件对象定位源文件
// File f = new File("Day10Demo/src/dlei01.txt");
// 2.创建一个字符输入流管道与源文件接通
// Reader fr = new FileReader(f);
// 3.简化写法:创建一个字符输入流管道与源文件路径接通
Reader fr = new FileReader("Day10Demo/src/dlei01.txt");
// 4.按照字符读取,每次读取一个字符的编号返回。
// int code1 = fr.read();
// System.out.print((char)code1);
// int code2 = fr.read();
// System.out.print((char)code2);
// int code3 = fr.read();
// System.out.print((char)code3);
// int code4 = fr.read(); // 读取完毕返回-1
// System.out.print(code4);
// 5.while循环一个一个字符读取。
// 定义一个变量存储一个字符的编号
int ch ;
while ((ch = fr.read()) != -1){
System.out.print((char)ch);
}
}
}
- 字符流一个一个字符的读取文本内容输入,可以解决中文读取输出乱码的问题
- 字符流很适合操作文本文件内容
- 但是一个一个字符读取文本内容性能较差
字符流按照字符数组循环读取数据
public class FileReaderDemo02 {
public static void main(String[] args) throws Exception {
// 1.创建一个字符输入流管道与源文件接通
Reader fr = new FileReader("Day10Demo/src/dlei02.txt");
// 2.按照字符数组读取内容
// a.按照字符数组读取数据使用循环
char[] buffer = new char[1024]; // 1K
// b.定义一个整数记录每次桶读取的字符数据量。
int len;
while((len = fr.read(buffer)) != -1 ) {
// 读取多少倒出多少字符
System.out.print(new String(buffer, 0 , len));
}
}
}
1.6字符输出流
字符输出流 | |
---|---|
Writer | 抽象类 |
FileWriter | 实现类(文件字符输出流) |
FileWriter文件字符输出流作用:把内存的数据以字符的形式写出到文件中去
构造器:
public FileWriter(File file)
: 创建一个字符输出流管道通向目标文件对象public FileWriter(String filePath)
:创建一个字符输出流管道通向目标文件路径public FileWriter(File file,boolean append)
:创建一个追加数据的字符输出流管道通向目标文件对象public FileWriter(String filePath,boolean append)
:创建一个追加数据的字符输出流管道通向目标文件路径
方法:
public void write(int c)
:写一个字符出去public void write(String c)
:写一个字符串出去public void write(String c,int pos,int len)
:写字符串的一部分出去public void write(char[] buffer,int pos,int len)
:写字符数组的一部分出去
public class FileWriterDemo03 {
public static void main(String[] args) throws Exception {
// 1.创建一个字符输出流管道通向目标文件路径
//Writer fw = new FileWriter("Day10Demo/src/dlei03.txt"); // 覆盖数据管道
Writer fw = new FileWriter("Day10Demo/src/dlei03.txt",true); // 追加数据管道
// 2.写一个字符出去:public void write(int c):写一个字符出去
fw.write(97); // 字符a
fw.write('b'); // 字符b
fw.write('磊'); // 字符磊,此时没有任何问题。
fw.write("\r\n"); // 换行
// 3.写一个字符串出去:public void write(String c)写一个字符串出去:
fw.write("Java是最优美的语言!");
fw.write("我们在黑马学习它!");
fw.write("\r\n"); // 换行
// 4.写一个字符数组出去:public void write(char[] buffer):写一个字符数组出去
fw.write("我爱中国".toCharArray());
fw.write("\r\n"); // 换行
// 5.写字符串的一部分出去: public void write(String c ,int pos ,int len):写字符串的一部分出去
fw.write("Java是最优美的语言!",0,9);
fw.write("\r\n"); // 换行
// 6.写字符数组的一部分出去:public void write(char[] buffer ,int pos ,int len):写字符数组的一部分出去
fw.write("我爱中国".toCharArray(),0 ,2);
fw.write("\r\n"); // 换行
fw.close();
}
}
1.7缓冲流
-
什么是缓冲流?
答:缓冲流可以提高字节流和字符流的读写数据的性能
1.8字节缓冲输入流
字节缓冲输入流 | |
---|---|
BufferedInputStream | 实现类 |
字节缓冲输入流:BufferedInputStream
作用:可以把低级的字节输入流包装成一个高级的缓冲字节输入流管道,从而提高字节输入流读数据的性能
构造器:
public BufferedInputStread(InputStream in)
原理:
- 缓冲字节输入流管道自带了一个8KB的缓冲池,每次可以直接借用操作系统的功能最多提取8KB的数据到缓冲池中去,以后我们直接从缓冲池读取数据,所以性能较好
public class BufferedInputStreamDemo01 {
public static void main(String[] args) throws Exception {
// 1.定义一个低级的字节输入流与源文件接通
InputStream is = new FileInputStream("Day10Demo/src/dlei04.txt");
// 3.把低级的字节输入流包装成一个高级的缓冲字节输入流。
BufferedInputStream bis = new BufferedInputStream(is);
// 2.定义一个字节数组按照循环读取。
byte[] buffer = new byte[3];
int len ;
while((len = is.read(buffer)) != -1){
String rs = new String(buffer, 0 , len);
System.out.print(rs);
}
}
}
1.9字节缓冲输出流
字节缓冲输出流 | |
---|---|
BufferedOutputStream | 实现类(字节缓冲输出流) |
字节缓冲输出流作用:可以把低级的字节输出流包装成一个高级的缓冲字节输出流,从而提高读写数据的性能
构造器:
public BufferedOutputStream(OutputStream os)
原理:
- 缓冲字节输出流自带了8KB缓冲池,数据就直接写入到缓冲池中去,性能极高了
public class BufferedOutputStreamDemo02 {
public static void main(String[] args) throws Exception {
// 1.写一个原始的字节输出流
OutputStream os = new FileOutputStream("Day10Demo/src/dlei05.txt");
// 3.把低级的字节输出流包装成一个高级的缓冲字节输出流
BufferedOutputStream bos = new BufferedOutputStream(os);
// 2.写数据出去
bos.write('a');
bos.write(100);
bos.write('b');
bos.write("我爱中国".getBytes());
bos.close();
}
}
1.10字符缓冲输入流
字符缓冲输入流 | |
---|---|
BufferedReader | 实现类 |
字符缓冲输入流作用:字符缓冲输入流可以把字符输入流包装成一个高级的缓冲字符输入流,可以提高字符输入流读数据的能力
构造器:
public BufferedReader(Reader reader)
原理:
-
缓冲字符输入流默认会有一个8K的字符缓冲池,可以提高读字符的性能
-
除了提高字符输入流的读数据性能,缓冲字符输入流还多了一个按照行读取数据的功能
-
public String readLine()
: 读取一行数据返回,读取完毕返回null
public class BufferedReaderDemo01 {
public static void main(String[] args) throws Exception {
// 1.定义一个原始的字符输入流读取源文件
Reader fr = new FileReader("Day10Demo/src/dlei06.txt");
// 3.把低级的字符输入流管道包装成一个高级的缓冲字符输入流管道
BufferedReader br = new BufferedReader(fr);
// 定义一个字符串变量存储每行数据
String line;
// 使用一个循环读取数据(经典代码)
while((line = br.readLine())!=null){
System.out.println(line);
}
br.close();
}
}
1.11字符缓冲输出流
字符缓冲输出流 | |
---|---|
BufferedWriter | 实现类 |
字符缓冲输出流的作用:把字符输出流包装成一个高级的缓冲字符输出流,提高写字符数据的性能
构造器:
public BufferedWriter(Writer writer)
原理:
- 高级的字符缓冲输出流多了一个8KB的字符缓冲池,写数据性能极大提高了
- 多了一个换行功能
public void newLine()
:新建一行
public class BufferedWriterDemo02 {
public static void main(String[] args) throws Exception {
// 1.定义一个低级的字符输出流写数据出去,要追加数据的话第二个参数为 true
Writer fw = new FileWriter("Day10Demo/src/dlei07.txt",true);
// 3.把低级的字符输出流包装成高级的缓冲字符输出流
BufferedWriter bw = new BufferedWriter(fw);
// 2.写字符输出
bw.write("我在学校学IO流~~~~");
bw.newLine(); // 换行
bw.write("我在学校学IO流~~~~");
bw.newLine();// 换行
bw.close();
}
}
1.12字符输入转换流
字符输入转换流 | |
---|---|
InputStreamReader | 实现类(转换流) |
字符输入转换流作用:
- 可以解决字符读取不同编码乱码的问题
- 可以把原始的字节流按照当前默认的代码编码转换成字符输入流
- 也可以把原始的字节流按照指定编码转换成字符输入流
构造器:
public InputStreamReader(InputStream is)
: 可以使用当前代码默认转换成字符流,几乎不用!public InputStreamReader(InputStream is,String charset)
:可以指定编码把字节流转换成字符流
public class InputStreamReaderDemo01 {
public static void main(String[] args) throws Exception {
// 代码:UTF-8 文件:GBK(ab我爱你: o o [oo] [oo] [oo])
// 1.提取GBK文件的原始字节流
InputStream is = new FileInputStream("D:\\itcast\\网络编程公开课\\Netty.txt");
// 2.把原始字节输入流通过转换流,转换成 字符输入转换流InputStreamReader
//Reader isr = new InputStreamReader(is); // 使用当前代码默认编码UTF-8转换成字符流,几乎不用!
Reader isr = new InputStreamReader(is,"GBK"); // 指定编码把字节流转换成字符流
// 3.包装成缓冲流
BufferedReader br = new BufferedReader(isr);
// 4.定义一个字符串变量存储每行数据
String line;
// 使用一个循环读取数据(经典代码)
while((line = br.readLine())!=null){
System.out.println(line);
}
}
}
1.13字符输出转换流
字符输出转换流 | |
---|---|
OutputStreamWriter | 实现类(转换流) |
==字符输出转换流作用:==可以指定编码把字节输出流os转换成字符输出流Writer,可以指定写出去的字符的编码
构造器:
public OutputStreamWriter(OutputStream os)
: 用当前默认编码UTF-8把字节输出流转换成字符输出流public OutputStreamWriter(OutputStream os,String charset)
: 指定编码把字节输出流转换成字符输出流
public class OutputStreamWriterDemo02 {
public static void main(String[] args) throws Exception {
// 1.写一个字节输出流通向文件
OutputStream os = new FileOutputStream("Day10Demo/src/dlei07.txt");
// 2.把字节输出流转换成字符输出流。
// Writer fw = new OutputStreamWriter(os); // .把字节输出流按照默认编码UTF-8转换成字符输出流。
Writer fw = new OutputStreamWriter(os,"GBK"); // . 把字节输出流按照指定编码GBK转换成字符输出流。
fw.write("abc我是中国人");
fw.close();
}
}
1.14对象字节输出流
-
什么是对象序列化?
答:对象序列化就是把Java对象数据直接存储到文件中去 (对象 => 文件中)
-
对象序列化流(也就是对象字节输出流)
对象字节输出流(对象序列化) | |
---|---|
ObjectOutputStream | 实现类(序列流) |
对象字节输出流的作用: 把内存中的Java对象数据保存到文件中去
构造器:
public ObjectOutputStream(OutputStream out)
序列化方法:
public final void writeObject(Object obj)
注意:
如果对象想参与序列化,对象必须实现序列化接口 implements Serializable
,否则序列化失败
public class SerializeDemo01 {
public static void main(String[] args) throws Exception {
// 1.创建User用户对象
User user = new User("tsgz","003197","铁扇公主");
// 2.创建低级的字节输出流通向目标文件
OutputStream os = new FileOutputStream("Day10Demo/src/obj.dat");
// 3.把低级的字节输出流包装成高级的对象字节输出流ObjectOutputStream,因为低级的字节输出流没有保存对象的能力
ObjectOutputStream oos = new ObjectOutputStream(os);
// 4.通过对象字节输出流序列化对象:
oos.writeObject(user);
// 6.释放资源
oos.close();
System.out.println("序列化对象成功~~~~");
}
}
1.15对象字节输入流
对象字节输入流(对象反序列化) | |
---|---|
ObjectInputStream | 实现类(序列流) |
对象字节输入流作用:把Java对象的文件恢复到Java对象中(文件中 => 对象)
构造器:
public ObjectInputStream(InputStrean is)
方法:
public final Object readObject()
如果一个字段不想参数序列化:
transient
修饰该成员变量,它将不参与序列化
public class SerializeDemo02 {
public static void main(String[] args) throws Exception {
// 1.定义一个低级的字节输入流通向源文件
InputStream is = new FileInputStream("Day10Demo/src/obj.dat");
// 2.把字节输入流包装成高级对象字节输入流
ObjectInputStream ois = new ObjectInputStream(is);
// 3.反序列化
User user = (User) ois.readObject();
System.out.println(user);
System.out.println("反序列化完成!");
}
}
1.16打印流
打印流 | |
---|---|
PrintStream | 不光可以打印数据,还可以写"字节数据"出去 |
PrintWriter | 不光可以打印数据,还可以写"字符数据"出去 |
打印流的作用:
- 可以方便,快速的写数据出去
- 可以实现打印啥出去,就是啥出去
构造器:
public PrintStream(OutputStream os)
public PrintStream(String filepath)
public class PrintStreamDemo01 {
public static void main(String[] args) throws Exception {
// 1.打印流PrintStream
//OutputStream os = new FileOutputStream("Day10Demo/src/dlei08.txt");
//PrintStream ps = new PrintStream(os);
PrintStream ps = new PrintStream("Day10Demo/src/dlei08.txt");
//PrintWriter pw = new PrintWriter("Day10Demo/src/dlei08.txt");
ps.println(97); // 写97
ps.println(110); // 写110
ps.println("我在学校快乐的调皮~~");
ps.println(99.8);
ps.println(false);
ps.println('徐');
// 写字节数据出去
// ps.write("我爱你".getBytes());
ps.close();
}
}
1.17重定向
打印流可以改变输出的流向
public static void setOut(PrintStream out)
: 让系统的输出流向打印流
public class PrintStreamDemo02 {
public static void main(String[] args) throws Exception {
System.out.println("==itheima0==");
PrintStream ps = new PrintStream("Day10Demo/src/log.txt");
System.setOut(ps); // 让系统的输出流向打印流。
// system.out.println 流向ps,ps流向文件里面去
System.out.println("==itheima1==");
System.out.println("==itheima2==");
System.out.println("==itheima3==");
System.out.println("==itheima4==");
System.out.println("==itheima5==");
}
}
1.12总结
字节输入流 | 字节输出流 | 字符输入流 | 字符输出流 | |
---|---|---|---|---|
InputStream | OutputStream | Reader | Writer | 抽象类 |
FileInputStream | FileOutputStream | FileReader | FileWriter | 实现类 |
BufferedInputStream | BufferedOutputStream | BufferedReader | BufferedWriter | 实现类(缓冲流) |
InputStreamReader | OutputStreamWriter | 实现类(转换流) | ||
ObjectInputStream | ObjectOutputStream | 实现类(序列化流) |
- 基本上只会用字符缓冲输入流读取数据
- 基本上只会用字符缓冲输出流写数据