目录
1.IO流概念
用于读写数据的(可以读写文件,或网络中的数据)
I指Input,称为输入流:负责把数据读到内存中去
O指Output,称为输出流:负责写数据出去
分类:
字节输入流:以内存为基准,来自磁盘文件/网络中的数据以字节的形式读入到内存中去的流
字节输出流:以内存为基准,把内存中的数据以字节的形式写出到磁盘文件或者网络中去的流。
字符输入流:以内存为基准,来自磁盘文件/网络中的数据以字符的形式读入到内存中去的流。
字符输出流:以内存为基准,把内存中的数据以字符的形式写出到磁盘文件或者网络介质中去的流。
2.IO流-字节流
1.文件字节输入流:每次读取一个字节
作用:以内存为基准,可以把磁盘文件中的数据以字节的形式读入到内存中去。
特点:使用FileInputStream每次读取一个字节,读取性能较差,并且读取汉字输出会乱码。
package com.itheima.day09.teacher.io;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
/*
一次读一个字节 原始循环写法
*/
public class FileInputStreamDemo {
/*
字节输入流
抽象父类 InputStream 定义了很多进行读取的方法
子类
FileInputStream 操作的文件 进行文件的读取操作流
每次 最小读取单位是字节,
*/
public static void main(String[] args) throws IOException {
/*
构造方法:
FileInputStream(文件对象)
FileInputStream(文件路径)
*/
// 封装 heihei.txt
// 创建了一个字节输入流 由 文件 ====>======>通向内存 对于内存是读取操作
FileInputStream fis = new FileInputStream("day09\\src\\heihei.txt");
//通过流 读取数据
// int read() 每次读取一个字节 读完之后再调用读取下一个
// int b1 = fis.read();
// System.out.println(b1);//字节 97
// int b2 = fis.read();
// System.out.println(b2);//字节 98
// 也就是 如果调用 read方法读取的结果是-1的时候 说明读完了....
//提升大家能力到了 将上述操作改查循环处理 while...
while(true){
//读一个字节
int b = fis.read();//int 可以接收byte (short char)
if(b==-1){
break;
}
System.out.println(b);
}
//优秀的程序员 使用完之后 关闭流 节约内存
fis.close();
}
}
--------------
package com.itheima.day09.teacher.io;
import java.io.FileInputStream;
import java.io.IOException;
public class FileInputStreamDemo02 {
/*
一次一个字节形式读取 优化循环写法
*/
public static void main(String[] args) throws IOException {
// 封装 heihei.txt
// 创建了一个字节输入流 由 文件 ====>======>通向内存 对于内存是读取操作
FileInputStream fis = new FileInputStream("day09\\src\\heihei.txt");
//通过流 读取数据
// while(true){
// //读一个字节
// int b = fis.read();//int 可以接收byte (short char)
// if(b==-1){
// break;
// }
// System.out.println(b);
// }
int b ;
// b=fis.read() 将读取数据给了b ()!=-1 对b的结果进行判断
while((b=fis.read())!=-1){
System.out.println(b);//解析 输出
}
//优秀的程序员 使用完之后 关闭流 节约内存
fis.close();
}
}
2.文件字节输入流:每次读取多个字节
作用:以内存为基准,把文件中的数据以字节的形式读入到内存中去。
特点:使用FileInputStream每次读取多个字节,读取性能得到了提升,但读取汉字输出还是会乱码。
package com.itheima.day09.teacher.io;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Arrays;
public class FileInputStreamDemo03 {
/*
一次一个字节数组形式读取
*/
public static void main(String[] args) throws IOException {
// 封装 heihei.txt
// 创建了一个字节输入流 由 文件 ====>======>通向内存 对于内存是读取操作
FileInputStream fis = new FileInputStream("day09\\src\\heihei.txt");
//通过流 读取数据
/*
int read(byte[] bys)
每次使用一个字节数组去读取, 数据放在数组中。
返回值读取 真实 数据的 个数!!!
如果数组读取的是没有 内容了 就是 -1
*/
byte[] buffer = new byte[3];
//容量为3的数组
int read1 = fis.read(buffer);
// read1
System.out.println(read1);//3
System.out.println(Arrays.toString(buffer));//97 98 99
int read2 = fis.read(buffer);
// read2
System.out.println(read2);//3
System.out.println(Arrays.toString(buffer));//100 101 -26
int read3 = fis.read(buffer);
// read3
System.out.println(read3);//2
System.out.println(Arrays.toString(buffer));//-120, -111, -26
int read4 = fis.read(buffer);
// read4
System.out.println(read4);//-1
//优秀的程序员 使用完之后 关闭流 节约内存
fis.close();
}
}
------------------------
package com.itheima.day09.teacher.io;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Arrays;
public class FileInputStreamDemo04 {
/*
一次一个字节数组形式读取 --- 循环写法
*/
public static void main(String[] args) throws IOException {
// 创建了一个字节输入流 由 文件 ====>======>通向内存 对于内存是读取操作
FileInputStream fis = new FileInputStream("day09\\src\\heihei.txt");
//通过流 读取数据
/*
int read(byte[] bys)
每次使用一个字节数组去读取, 数据放在数组中。
返回值读取 真实 数据的 个数!!!
如果数组读取的是没有 内容了 就是 -1
学习两个转换字符串的方法
new String(byte[] bys);
new String(byte[] bys,int begin,int length);
*/
byte[] buffer = new byte[3];
int len;//表达每次读取的长度
// 长度为-1不能读
while((len= fis.read(buffer))!=-1){
// buffer是 一个用来存储读取数据的数组
// 那么请问 该数组中 里面的元素 都是本次读取的吗?不一定
// 真实的读取个数 是 len个
// buffer 索引 0 1 2 3 ....buffer.length-1
// 请问 真实读取个数 len 那部分是 真实读取数据 前len个!!!
// 交给大家一个好玩的方法 String(byte[] buffer,int 起始索引,int 长度)
// 将字节数组一部分 按照默认的编码 转换成字符
// 将真实数据转成字符串
String s = new String(buffer, 0, len);//转换真实读取的字节数
System.out.println(s);
}
// a b c d e ? ??
// 在转换字符的时候 出现了? 为什么呢 第二次读的时候 1/3 个汉字 所以出现了乱码
// 建议以后 读取带有中文的文件 不要直接使用字节输入流 ---字符输入流
//优秀的程序员 使用完之后 关闭流 节约内存
fis.close();
}
}
3.文件字节输入流:一次读取完全部字节
方式一:自己定义一个字节数组与被读取的文件大小一样大,然后使用该字节数组,一次读完文件的全部字节。
方式二:Java官方为InputStream提供了如下方法,可以直接把文件的全部字节读取到一个字节数组中返回。
特点:可以避免乱码问题,但如果文件过大,创建的字节数组也会过大,可能引起内存溢出。
package com.itheima.day09.teacher.io;
import java.io.FileInputStream;
import java.io.IOException;
public class FileInputStreamDemo05 {
/*
一次一个字节数组形式读取 --- 循环写法
*/
public static void main(String[] args) throws IOException {
// 创建了一个字节输入流 由 文件 ====>======>通向内存 对于内存是读取操作
FileInputStream fis = new FileInputStream("day09\\src\\heihei.txt");
//通过流 读取数据
/*
字节流不适合读取中文,因为可能会在读取过程 造成 字符的切割 出现乱码
执意要做 就创建一个超过 文件的字节数组 解决乱码问题
创建的字节数组长度 浪费。。。
有
*/
// byte[] buffer = new byte[8];
// int len = fis.read(buffer);
// System.out.println(new String(buffer,0,len));
byte[] bytes = fis.readAllBytes();
System.out.println(new String(bytes));
//优秀的程序员 使用完之后 关闭流 节约内存
fis.close();
}
}
4.文件字节输出流:写字节出去
作用:以内存为基准,把内存中的数据以字节的形式写出到文件中去。
package com.itheima.day09.teacher.io2;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileOutputStreamDemo01 {
/*
字节输出流
OutputStream 定义跟写相关的方法
FileOutputStream 文件字节输出流
创建一个内存和指定文件的 通道(流) 可以将内存中的数据
内存 ======> 文件
方法 都是跟写相关
*/
public static void main(String[] args) throws IOException {
/*
构造
FileOutputStream(目标文件对象)
FileOutputStream(目标文件路径)
创建一个有内存 通向 目标文件的 流 我们可以将内存的数据通过流写到目标文件中
如果目标文件不存在,会自动创建。
存在 会先清空再写
*/
FileOutputStream fos = new FileOutputStream("day09\\src\\hehe.txt");
// fos 写数据
// 一次写一个字节
fos.write(97);//97 字节-- a
// 一次写一个字节数组--- 字符串--字节数组
byte[] bytes = "abcd".getBytes();
fos.write(bytes);// 97 98 99 100 abcd
// 一次写一个字节数组的一部分
// fos.write(bytes,起始位值,长度);
fos.write(bytes,1,2);
//最后还要释放资源
fos.close();
}
}
-------------------------
package com.itheima.day09.teacher.io2;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileOutputStreamDemo02 {
/*
字节输出流
OutputStream 定义跟写相关的方法
FileOutputStream 文件字节输出流
创建一个内存和指定文件的 通道(流) 可以将内存中的数据
内存 ======> 文件
方法 都是跟写相关
*/
public static void main(String[] args) throws IOException {
/*
构造
FileOutputStream(目标文件对象)
FileOutputStream(目标文件路径)
创建一个有内存 通向 目标文件的 流 我们可以将内存的数据通过流写到目标文件中
如果目标文件不存在,会自动创建。
存在 会先清空再写
想追加 构造需要加入一个参数 true
*/
FileOutputStream fos = new FileOutputStream("day09\\src\\hehe.txt",true);
fos.write("\n".getBytes());
fos.write("你好吗".getBytes());
//最后还要释放资源
fos.close();
}
}
5.案例:文件复制
任何文件的底层都是字节,字节流做复制,是一字不漏的转移完全部字节,只要复制后的文件格式一致就没问题!
package com.itheima.day09.teacher.io2;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class CopyDemo {
/*
文件复制:
将源文件的内容 copy 到 目标文件中
读到内存 从内存写到目标文件
*/
public static void main(String[] args) throws IOException {
/*
文件复制 5步
1:创建字节输入流 关联源文件。
2:创建字节输出流 关联目标文件。
边读边写
3:将源文件内容读取到内存中。
4:将内存中数据 写到目标文件中。
5:释放资源
*/
// 1:创建字节输入流 关联源文件。
FileInputStream in = new FileInputStream("D:\\upload\\img\\帅照.jpg");
// 2:创建字节输出流 关联目标文件。
FileOutputStream out = new FileOutputStream("E:\\418\\点名\\小伙子真帅.jpg");
// 边读边写
// 3:将源文件内容读取到内存中。
//采用字节数组
byte[] buffer = new byte[1024*8];
int len ;
while((len=in.read(buffer))!=-1){
// 数组 0 到len是真实数据
// 4:将内存中数据 写到目标文件中。
out.write(buffer,0,len);
}
//
// 5:释放资源
out.close();
in.close();
//从后往前不会丢
//从小到大 不会错
}
}
释放资源的方式
1.try-catch-finally
finally代码区的特点:无论try中的程序是正常执行了,还是出现了异常,最后都一定会执行finally区,除非JVM终止。
作用:一般用于在程序执行完成后进行资源的释放操作
package com.itheima.day10.teacher.exception;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileCopy {
//jdk7之前的 完成释放资源方案
public static void main(String[] args) {
FileInputStream fis = null;
FileOutputStream fos = null;
try{
//运行的代码---会试着抓取 出现的异常
//1: 创建字节输入流关联源文件 (作用:用于将源文件数据读取到内存中)
fis = new FileInputStream("E:\\414\\resource\\meinv\\mote.jpg");
//2: 创建字节输出流关联目标文件 (作用:将内存中读取到数据 写到目标文件中)
fos = new FileOutputStream("E:\\414\\resource\\shoucang\\mote.jpg");
System.out.println(1/0);//遇到问题
System.out.println("下面的操作就不会执行");
// 用效率高一点的 使用数组形式
byte[] buffer = new byte[1024*8];
int len;
//3: 读
while((len=fis.read(buffer))!=-1){
//4: 写
// 读取真实数据 buffer 从0开始 取len个
// 真实数据 通过字节输出流 写到 收藏里面
fos.write(buffer,0,len);
}
}catch (Exception e){//如果上面代码出现该异常类可以接收的对象
// 遇到异常之后的 处理方案
e.printStackTrace();//打印出异常信息 但是程序不终止
}finally { // u不管有没有异常都会执行
//5: 释放资源 (从后往前不会丢 从小到大不会错)
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
2.try-with-resource
该资源使用完毕后,会自动调用其close()方法,完成对资源的释放!
() 中只能放置资源,否则报错 什么是资源呢? 资源一般指的是最终实现了AutoCloseable接口的类产生的对象。
package com.itheima.day10.teacher.exception;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileCopy2 {
//jdk7之前的 完成释放资源方案
/*
try{
}catch(){
}finally{
}
jdk7之后
try(资源对象1;资源对象2;){
使用资源的代码
}catch(异常类 e){
处理异常的代码;
}
*/
public static void main(String[] args) {
try(
//运行的代码---会试着抓取 出现的异常
//1: 创建字节输入流关联源文件 (作用:用于将源文件数据读取到内存中)
FileInputStream fis = new FileInputStream("E:\\414\\resource\\meinv\\mote.jpg");
//2: 创建字节输出流关联目标文件 (作用:将内存中读取到数据 写到目标文件中)
FileOutputStream fos = new FileOutputStream("E:\\414\\resource\\shoucang\\mote.jpg");
){
System.out.println(1/0);//遇到问题
System.out.println("下面的操作就不会执行");
// 用效率高一点的 使用数组形式
byte[] buffer = new byte[1024*8];
int len;
//3: 读
while((len=fis.read(buffer))!=-1){
//4: 写
// 读取真实数据 buffer 从0开始 取len个
// 真实数据 通过字节输出流 写到 收藏里面
fos.write(buffer,0,len);
}
}catch (Exception e){//如果上面代码出现该异常类可以接收的对象
// 遇到异常之后的 处理方案
e.printStackTrace();//打印出异常信息 但是程序不终止
}
}
}
3.IO流-字符流
1.FileReader:文件字符输入流
作用:以内存为基准,可以把文件中的数据以字符的形式读入到内存中去。
特点:一次读取一个字符,可以避免中文乱码问题
package com.itheima.day10.teacher.a_charStream;
import java.io.FileReader;
public class FileReaderDemo {
/*
掌握
字符输入流 FileReader
*/
public static void main(String[] args) throws Exception{
/*
流的操作规律
创建流对象
读、写
释放资源
*/
/*
学习创建对象
FileReader(File 源文件对象)
FileReader(File 源文件路径)
*/
FileReader fr = new FileReader("day10\\src\\heihei.txt");
//2:读取数据
// int read() 一次读一个字符 只不是使用int接收 int数据怎么变成char数据 (char)
//循环形式 一次读一个字符
// int c;//c接收读取的字符
// while((c=fr.read())!=-1){
// System.out.println((char)c);//转换成字符展示
// }
//采用字符数组读取 一次读取一个字符数组
char[] chs = new char[3];//每次最多读取3个长度的字符
int len;//读取字符数组的实际长度
while((len=fr.read(chs))!=-1){
//chs 字符数组 len 读取到字符长度
// new String(字符数组,起始索引,取的长度)
String s = new String(chs, 0, len);
System.out.println(s);
}
//3:释放资源
fr.close();
}
}
2.FileWriter:文件字符输出流
作用:以内存为基准,把内存中的数据以字符的形式写出到文件中去。
特点:字符输出流写出数据后,必须刷新流,或者关闭流,写出去的数据才能生效
package com.itheima.day10.teacher.a_charStream;
import java.io.FileWriter;
public class FileWriterDemo {
public static void main(String[] args) throws Exception{
/*
学习 字符输出流
每次都可以按照 字符形式写出去
内存--->文件
FileWriter
构造有四个
一个参数 传递目标文件对象 目标文件路径
两个参数 实现追加的 后面的参数写true就是追加
*/
//创建流对象
FileWriter fw = new FileWriter("day10\\src\\hehe.txt");
//写数据---灵活
// 一次写一个字符出去
fw.write('雷');
fw.write(97);//'a'
fw.write("\r\n");
// 一次写一个字符数组出去
char[] chs = {'鱼','虾','蟹','龟'};
fw.write(chs);
fw.write("\r\n");
// 一次写一个字符数组一部分出去
fw.write(chs,3,1);//龟
fw.write("\r\n");
// 一次写一个字符串出去
fw.write("我是如来佛祖玉皇大帝观音菩萨取西经特派使者");
fw.write("\r\n");
// 一次写一个字符串一部分出去
fw.write("abcde",2,2);//cd
fw.write("\r\n");
//释放资源
fw.close();
}
}
-----------------
package com.itheima.day10.teacher.a_charStream;
import java.io.FileWriter;
public class FileWriterNotice {
public static void main(String[] args) throws Exception{
//创建流对象
FileWriter fw = new FileWriter("day10\\src\\haha.txt");
//写数据---灵活
// 一次写一个字符出去
fw.write('雷');
//除了字节流以外其他流需要刷新 才能 到文件中 '雷'在通道动 没有 移动到文件中
//需要刷新
// fw.flush();//刷新
fw.write('神');
// fw.flush();//刷新
fw.close();//包含了刷新
}
}
字节流、字符流的使用场景小结:
字节流适合做一切文件数据的拷贝(音视频,文本);字节流不适合读取中文内容输出。
字符流适合做文本文件的操作(读,写)。
4.IO流-缓冲流
特点:对原始流进行包装,以提高原始流读取数据的性能
1.字节缓冲流
作用:提高字节流读取数据的性能
原理:字节缓冲输入流自带了8KB缓冲池;字节缓冲输出流也自带了8KB缓冲池。
package com.itheima.day10.teacher.b_buffered;
import java.io.*;
public class BufferedByteDemo {
/*
字节缓冲流
BufferedInputStream 字节缓冲输入流
BufferedOutputStream 字节缓冲输出流
特点
对原始流进行包装,没有进行功能上的扩展,只进行性能提升(速度)
*/
public static void main(String[] args) throws Exception {
// 缓冲流构造中 传入基本流 原始流
FileInputStream fis = new FileInputStream("src\\b.txt");
FileOutputStream fos = new FileOutputStream("src\\day10.txt");
//缓冲流创建
BufferedInputStream bis = new BufferedInputStream(fis);
BufferedOutputStream bos = new BufferedOutputStream(fos);
//使用跟以前一样
byte[] buffer = new byte[1024];
int len;
while((len=bis.read(buffer))!=-1){
bos.write(buffer,0,len);
}
//释放资源
bos.close();
bis.close();
fos.close();
fis.close();
}
}
2.字符缓冲流
作用:提高字符流读取数据的性能
原理:自带8K(8192)的字符缓冲池
package com.itheima.day10.teacher.b_buffered;
import java.io.BufferedReader;
import java.io.FileReader;
public class BufferedReaderDemo {
public static void main(String[] args) throws Exception{
//创建 基本字符输入流
FileReader fr = new FileReader("day10\\src\\咏鹅.txt");
//创建 包装流 字符缓冲输入流
BufferedReader br = new BufferedReader(fr);
// String readLine() 每次读一行 如果读到结果是null 代表读完了
String line ;
while((line=br.readLine())!=null){
System.out.println(line);//读一行 输出一行
}
br.close();
fr.close();
}
}
package com.itheima.day10.teacher.b_buffered;
import java.io.BufferedWriter;
import java.io.FileWriter;
public class BufferedWriterDemo {
public static void main(String[] args) throws Exception {
// BufferedWriter 字符缓冲输出流 提供了一个换行的方法
//基本流 原始流 字符输出流
FileWriter fw = new FileWriter("day10\\src\\草.txt");
BufferedWriter bw = new BufferedWriter(fw);
bw.write("离离原上草");
// bw.write("\r\n");
bw.newLine();//这是换行 newLine()
bw.write("一岁一枯荣");
bw.newLine();
bw.write("野火烧不尽");
bw.newLine();
bw.write("春风吹又生");
bw.close();
}
}
推荐使用哪种方式提高字节流读写数据的性能?
建议使用字节缓冲输入流、字节缓冲输出流,结合字节数组的方式,目前来看这是性能最优的组合。
5.IO流-转换流
如果代码编码和被读取的文本文件的编码是一致的,使用字符流读取文本文件时不会出现乱码!
如果代码编码和被读取的文本文件的编码是不一致的,使用字符流读取文本文件时就会出现乱码!
1.InputStreamReader:字符输入转换流
解决不同编码时,字符流读取文本内容乱码的问题。
解决思路:先获取文件的原始字节流,再将其按真实的字符集编码转成字符输入流,这样字符输入流中的字符就不乱码了。
package com.itheima.day10.teacher.c_change;
import java.io.*;
public class InputStreamReaderDemo01 {
/*
字符流= 字节流+编码表
*/
public static void main(String[] args) throws Exception{
// FileReader 操作文件字符输入流的便捷类!!
// 文件底层都是字节!! 底层遵循的一个编码表---程序默认编码表UTF-8
// UTF-8 的编(解)码规则 ---- GBK 编(解)码规则
// 如果文件是UTF-8 使用默认编码表 读取没有乱码。
// 如果文件是GBK 使用默认编码表UTF-8 有乱码 。 码表不对应!!
FileReader fr = new FileReader("src\\gbk文件哦.txt");
//包装--因为包装流可以一次读一行
BufferedReader br = new BufferedReader(fr);
//使用
String line;
while((line=br.readLine())!=null){
System.out.println(line);
}
br.close();
fr.close();
}
}
-----------------------
package com.itheima.day10.teacher.c_change;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.InputStreamReader;
public class InputStreamReaderDemo02 {
/*
字符流= 字节流+编码表
*/
public static void main(String[] args) throws Exception{
/*
使用字符输入转换流 解决 读取文件和程序编码不一致问题
使用套路
1:先获取原始的字节流。
2:按照真实的字符集编码转换成 字符输入流(字符输入转换流)
// 字符输入转换流== 字符输入流 方法API都一样
*/
// 1:先获取原始的字节流。
FileInputStream fis = new FileInputStream("src\\gbk文件哦.txt");
// 2:按照真实的字符集编码转换成 字符输入流(字符输入转换流)
InputStreamReader isr = new InputStreamReader(fis, "GBK");
//isr 是字符流 字符输入流 字符输入转换流
//包装--因为包装流可以一次读一行
BufferedReader br = new BufferedReader(isr);
//使用
String line;
while((line=br.readLine())!=null){
System.out.println(line);
}
br.close();
isr.close();
fis.close();
}
}
2.OutputStreamWriter:字符输出转换流
作用:可以控制写出去的字符使用什么字符集编码。
解决思路:获取字节输出流,再按照指定的字符集编码将其转换成字符输出流,以后写出去的字符就会用该字符集编码了。
package com.itheima.day10.teacher.c_change;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
public class OutputStreamWriterDemo {
/*
学习使用 字符输出转换流
OutputStreamWriter
作用 将 字符数据 按照指定的编码格式 写到文件中。
使用
字符流 = 字节流+编码表
构造
OutputStreamWriter(字节输出流,编码表的字符串形式)
方法 跟 字符流学习的方法一致。
write(一个字符串)
*/
public static void main(String[] args) throws Exception{
//1:创建字节输出流
FileOutputStream fos = new FileOutputStream("src\\hello.txt");
//2:创建字符输出转换流
OutputStreamWriter osw = new OutputStreamWriter(fos,"GBK");
//3:写
osw.write("你好");// utf-8 6个字节 GBK 4个字节
osw.close();
fos.close();
}
}
FileReader和FileWrite的新特性:JDK11
自己定义编码,在构造路径后写编码Charset.forname("编码")
package com.itheima.day10.teacher;
import java.io.*;
import java.nio.charset.Charset;
public class JDK11Demo {
public static void main(String[] args) throws Exception{
// reader();
write();
}
/*
FileReader新特性
*/
public static void reader() throws Exception{
// 如果文件是GBK 使用默认编码表UTF-8 有乱码 。 码表不对应!!
Charset gbk = Charset.forName("GBK");
FileReader fr = new FileReader("day10\\src\\gbk文件哦.txt",gbk);
//包装--因为包装流可以一次读一行
BufferedReader br = new BufferedReader(fr);
//使用
String line;
while((line=br.readLine())!=null){
System.out.println(line);
}
br.close();
fr.close();
}
public static void write() throws Exception{
FileWriter fw = new FileWriter("day10\\src\\gbk2.txt",Charset.forName("GBK"));
//3:写
fw.write("你好");// utf-8 6个字节 GBK 4个字节
fw.close();
}
}
6.IO流-打印流
PrintStream/PrintWriter
作用:打印流可以更方便、更高效的把数据打印出去,能实现将指定的内容打印出去的功能。
PrintStream提供的打印数据的方案
package com.itheima.day10.teacher.d_other;
import java.io.PrintStream;
public class PrintTest02 {
public static void main(String[] args) throws Exception{
System.out.println("数据到控制台");
//为什么 System.out是一个打印流对象 这个流通向 控制台
//System中有个 setOut()方法 改变 out属性的流向 之前流向 控制 改变之后你想流那就流那
PrintStream ps = new PrintStream("day10\\我的控制台.txt");
System.setOut(ps);
System.out.println("你猜猜我在哪????");
System.out.println("赛乐你说....");
ps.close();
}
}
PrintWriter提供的打印数据的方案
package com.itheima.day10.teacher.d_other;
import java.io.PrintStream;
import java.io.PrintWriter;
public class PrintTest {
/*
打印流是一种输出流
作用:
更方便 更高效的把数据打印出去。可以将内容原封不动的写出去
PrintStream 字节打印流
PrintWriter 字符打印流
他们都是 字节输出流 字符输出流的儿子 该具备的write功能都有。
*/
public static void main(String[] args) throws Exception{
//1: c创建一个PrintStream对象
// PrintStream ps = new PrintStream("day10\\src\\鸡你太美.txt");
PrintWriter ps = new PrintWriter("day10\\src\\鸡你太美.txt","GBK");
// ps 字节输出流的儿子
ps.write(97);
// ps.write("嘿嘿嘿~~你是我的宝贝".getBytes());
//提供大量的 print pringln 方法
ps.println();
ps.println(97);
ps.print("想你的滋味,隐隐作祟.....");
ps.close();
}
}
PrintStream和PrintWriter的区别
打印数据的功能上是一模一样的:都是使用方便,性能高效(核心优势)
PrintStream继承自字节输出流OutputStream,因此支持写字节数据的方法。
PrintWriter继承自字符输出流Writer,因此支持写字符数据出去。
7.IO流-数据流
1.DataOutputStream:数据输出流
允许把数据和其类型一并写出去。
package com.itheima.day10.teacher.d_other;
import java.io.DataOutputStream;
import java.io.FileOutputStream;
public class DataOutputStreamDemo {
/*
数据数据流
就是将各种数据 按照字节形式写出去
底层依赖字节输出流
构造
DataOutputStream(字节输出流)
*/
public static void main(String[] args) throws Exception{
DataOutputStream dos = new DataOutputStream(new FileOutputStream("day10\\data.txt"));
//写 整数
dos.writeInt(123);
// 写小数
dos.writeDouble(3.14);
//写个 bollean
dos.writeBoolean(true);
//写一个字符串---按照 UTF8的形式
dos.writeUTF("醒醒吧!");
dos.close();
}
}
2.DataInputStream:数据输入流
用于读取数据输出流写出去的数据。
package com.itheima.day10.teacher.d_other;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
public class DataInputStreamDemo {
/*
数据输出流
就是将各种数据 按照字节形式写出去
数据输入流
就是将数据输出流写出去各种数据 读取回来
注意 要看好顺序
底层依赖字节输入流
构造
DataInputStream(字节输入流)
*/
public static void main(String[] args) throws Exception{
DataInputStream dis = new DataInputStream(new FileInputStream("src\\data.txt"));
//读 整数
int i = dis.readInt();
System.out.println(i);
// 写小数
// dos.writeDouble(3.14);
double v = dis.readDouble();
System.out.println(v);
//写个 bollean
// dos.writeBoolean(true);
boolean b = dis.readBoolean();
System.out.println(b);
//写一个字符串---按照 UTF8的形式
// dos.writeUTF("醒醒吧!");
String s = dis.readUTF();
System.out.println(s);
dis.close();
}
}
8.IO流-序列化流
1.ObjectOutputStream:对象字节输出流
可以把Java对象进行序列化:把Java对象存入到文件中去。
package com.itheima.day10.teacher.f_object;
import java.io.Serializable;
/*
User类:
对象想序列化 需要先实现序列化接口 Serializable
代表当前对象可以 完成 写出去的操作
*/
public class User implements Serializable {
private String loginName;
private String username;
private transient String password;//加了这个关键字 就不在序列化出去了
private int age;
public User() {
}
public User(String loginName, String username, String password, int age) {
this.loginName = loginName;
this.username = username;
this.password = password;
this.age = age;
}
/**
* 获取
* @return loginName
*/
public String getLoginName() {
return loginName;
}
/**
* 设置
* @param loginName
*/
public void setLoginName(String loginName) {
this.loginName = loginName;
}
/**
* 获取
* @return username
*/
public String getUsername() {
return username;
}
/**
* 设置
* @param username
*/
public void setUsername(String username) {
this.username = username;
}
/**
* 获取
* @return password
*/
public String getPassword() {
return password;
}
/**
* 设置
* @param password
*/
public void setPassword(String password) {
this.password = password;
}
/**
* 获取
* @return age
*/
public int getAge() {
return age;
}
/**
* 设置
* @param age
*/
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User{loginName = " + loginName + ", username = " + username + ", password = " + password + ", age = " + age + "}";
}
}
-----------------------
package com.itheima.day10.teacher.f_object;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
public class ObjectOutputStreamDemo {
public static void main(String[] args) throws Exception {
/*
ObjectOutputStream 将对象写出去 序列化流
序列化 将java对象写出去
构造
底层依赖于 基本的流
ObjectOutputStream(字节输出流)
*/
//创建一个序列化流
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("src\\my.uu"));
//这个流也是输出流的子类
User user = new User("xiaoheizi","鸡太美","666666",19);
// 写对象 writeObject
oos.writeObject(user);
oos.close();
}
}
2.ObjectInputStream
可以把Java对象进行反序列化:把存储在文件中的Java对象读入到内存中来。
package com.itheima.day10.teacher.f_object;
import java.io.Serializable;
/*
对象想序列化 需要先实现序列化接口 Serializable
代表当前对象可以 完成 写出去的操作
*/
public class User implements Serializable {
private String loginName;
private String username;
private transient String password;//加了这个关键字 就不在序列化出去了
private int age;
public User() {
}
public User(String loginName, String username, String password, int age) {
this.loginName = loginName;
this.username = username;
this.password = password;
this.age = age;
}
/**
* 获取
* @return loginName
*/
public String getLoginName() {
return loginName;
}
/**
* 设置
* @param loginName
*/
public void setLoginName(String loginName) {
this.loginName = loginName;
}
/**
* 获取
* @return username
*/
public String getUsername() {
return username;
}
/**
* 设置
* @param username
*/
public void setUsername(String username) {
this.username = username;
}
/**
* 获取
* @return password
*/
public String getPassword() {
return password;
}
/**
* 设置
* @param password
*/
public void setPassword(String password) {
this.password = password;
}
/**
* 获取
* @return age
*/
public int getAge() {
return age;
}
/**
* 设置
* @param age
*/
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User{loginName = " + loginName + ", username = " + username + ", password = " + password + ", age = " + age + "}";
}
}
---------------------
package com.itheima.day10.teacher.f_object;
import java.io.FileInputStream;
import java.io.ObjectInputStream;
public class ObjectInputStreamDemo {
/*
反序列化
将 java对象从字节文件读取出来
*/
public static void main(String[] args) throws Exception{
//创建 反序列流对象
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("src\\my.uu"));
// 读取对象的方法 readObject()
User o = (User) ois.readObject();
System.out.println(o);
ois.close();
}
}
9.IO框架
什么是框架?
解决某类问题,编写的一套类、接口等,可以理解成一个半成品,大多框架都是第三方研发的。
好处:在框架的基础上开发,可以得到优秀的软件架构,并能提高开发效率
框架的形式:一般是把类、接口等编译成class形式,再压缩成一个.jar结尾的文件发行出去。
什么是IO框架?
IO框架封装了Java提供的对文件、数据进行操作的代码,对外提供了更简单的方式来对文件进行操作,对数据进行读写等。
5.Commons-IO
1.Commons-io是apache开源基金组织提供的一组有关IO操作的小框架,目的是提高IO流的开发效率。
2.使用步骤:5步
1.从官网下载commons-io的jar包:https://commons.apache.org/proper/commons-io/download_io.cgi
2.在项目中创建一个文件夹:lib
3.将第一步解压后的commons-io-2.11.0.jar文件复制到lib文件夹中
4.在jar文件上点右键,选择 Add as Library -> 点击OK
5.在类中导包使用
package com.itheima.day10.teacher.e_io;
import org.apache.commons.io.FileUtils;
import java.io.File;
public class FileTest {
public static void main(String[] args) throws Exception{
//使用工具包中的FileUtils 前提 先导包
//复制文件
// FileUtils.copyFile(new File("day10\\src\\咏鹅.txt"),new File("day10\\src\\咏鸡.txt"));
// //复制文件夹
// FileUtils.copyDirectory(new File("day09\\aaa"),new File("day09\\ccc"));
//删除文件夹
// FileUtils.deleteDirectory(new File("day09\\bbb"));
// 读取数据
String s = FileUtils.readFileToString(new File("day10\\src\\咏鹅.txt"), "UTF-8");
System.out.println(s);
// 写数据
FileUtils.writeStringToFile(new File("day10\\src\\咏鸡.txt"),"鸡鸡鸡 你太美","UTF-8",true);
}
}
10.总结真言必看(重点)
感觉太多记不住,记混乱,小编这里总结了几句真言
1.只有字节字符输入输出流和打印流的构造写文件路径,其它流路径指用实现流的类写路径放在辅助流的构造里
2.打印流只有输出流,一个字节输出流一个字符输出流
3.对象字节输入\输出流ObjectIn(Out)putStream也是 (Out)序列化,和(In)反序列化和数据输入输出流DataIn(Out)putStream只在字节流里有(都是字节流的子类不是字符流的)
4.数据输入和输出流是连数据类型都读取了,获取要一个个按类型获取
5.对象输出和输入流的读写方法多加了Object
6.只有字符缓冲流有readLine() 读一行和newLine()换行,字节缓冲流没有
7.转换流只有字符流有(只是字符流的子类不是字节流的子类),它可以让字节流按照指定的编码转成字符流(字节流变字符流)