目录
一.FileInputStream,FileOutputStream:操作本地文件的字节输入输出流
五.案例:使用read一次读取一个字节数组的数据,每次读取尽量把数组装满
八.AutoCloseable:JDK7出现:特定情况下自动释放资源
十.FileReader与FileWriter:操作本地文件的字符输入输出流
一.FileInputStream,FileOutputStream:操作本地文件的字节输入输出流
1.IO流能够读写什么? 读写文件、网络中的数据 2.IO流主如何分类? 分为输入流(读),输出流(写) 又能分为字节流(所有文件)与字符流(文本) 3.主要哪一些抽象类? InputStream,OutputStream操作字节,Reader,Writer操作字符 4.创建字节输出流时,如果路径不对会怎样? 5.如果文件已存在会怎样? 6.使用write方法写入文件的时候写入的数字代表的是什么? 7.除了写入单个字节,如何写入多个字节? 8.使用完字节输出流之后,最后一步是什么?
public class Demo281 {
public static void main(String[] args) throws IOException {
String str = "JAVA基础\\src\\Day28\\MyText\\a.txt";
System.out.println("4.如果路径不正确会报错");
System.out.println("5.如果文件已经存在,会清空文件");
FileOutputStream fos = new FileOutputStream(str);
System.out.println("6.写的是97,实际写到本地文件的是ascii码表上的字符");
for (int i = 'a'; i <= 'z'; i++) fos.write(i);
System.out.println("7.定义数组写入文件,后面的参数代表截取的位置,在后面定义写入内存的时候会用到");
byte[] arr = new byte[26];
for (int i = 0; i < arr.length; i++) arr[i] = (byte) ('A' + i);
fos.write(arr, 0, 26);
System.out.println("8.最后一步释放资源");
fos.close();
}
}
二.使用输出流续写,输出字符串,换行
1.如何续写? 2.如何输入字符串? 3.在使用字节输出流输出成文件时,如何换行?
public class Demo282 {
public static void main(String[] args) throws IOException {
String str = "JAVA基础\\src\\Day28\\MyText\\a.txt";
System.out.println("1.续写只要在定义字节输出流的时候把第二个参数设置true即可");
FileOutputStream fos = new FileOutputStream(str,true);
System.out.println("2.把字符串变成字节数组换行操作");
System.out.println("3.使用\\r\\n都可以换行(三个操作系统的换行符都不一样,java帮忙处理了)");
fos.write("\nHello IO!".getBytes());
fos.write("\r666".getBytes());
fos.close();
}
}
三.读取整个文件:一个一个字节读取
1.使用read方法读取数据时,返回的参数代表什么? 2.如何使用while循环读取整个文件?
public class Demo283 {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("JAVA基础\\src\\Day28\\MyText\\a.txt");
int i;
System.out.println("1.使用read方法读取资源,返回值为int类型的读到的字节,到最后返回-1");
System.out.println("2.在while循环里面使用赋值语句,注意在这里赋值的语句优先级较低,需要加括号");
while ((i=fis.read()) != -1) System.out.print((char) i);
fis.close();
}
}
四.拷贝文件
1.如何拷贝文件? 2.一次只读写一个字节有什么缺点? 3.对于输入流与输出流的关闭顺序有什么规范吗?
public class Demo284 {
public static void main(String[] args) throws IOException {
String str = "JAVA基础\\src\\Day28\\MyText\\";
System.out.println("1.同时使用fis与fos可以拷贝文件");
FileInputStream fis = new FileInputStream(str+"a.txt");
FileOutputStream fos = new FileOutputStream(str+"aCopy.txt");
System.out.println("2.一次只读写一个字节,速度非常慢");
int b;
while ((b = fis.read())!=-1){
System.out.print(b+" ");
fos.write(b);
}
System.out.println();
System.out.println("3.先开的资源后关闭");
fos.close();
fis.close();
}
}
五.案例:使用read一次读取一个字节数组的数据,每次读取尽量把数组装满
1.使用read读取数组时,返回值是什么? 2.在读完数据之后,再次读取数据会替代之前的老数据,老数据会被全部清空吗? 3.全部读取完之后会返回什么? 4.如何解决掉多余的老数据呢?
public class Demo285 {
public static void main(String[] args) throws IOException {
String str = "JAVA基础\\src\\Day28\\MyText\\a.txt";
FileInputStream fis = new FileInputStream(str);
byte[] bytes = new byte[50];
System.out.println("1.使用read读取数组的返回值代表本次读取的数据个数");
int len = fis.read(bytes);
String MyStr = new String(bytes);
System.out.println("本次读取到的数据:"+MyStr);
System.out.println("本次读取的数据量:"+len);
System.out.println("2.读完的数据会覆盖之前的数据:但是不会全部清除");
len = fis.read(bytes);
MyStr = new String(bytes);
System.out.println(MyStr);
System.out.println("本次读取了数据量:"+len);
System.out.println("3.全部读取完之后再读取会返回-1,数据依旧是老数据");
len = fis.read(bytes);
MyStr = new String(bytes);
System.out.println(MyStr);
System.out.println("本次读取了数据量:"+len);
System.out.println("解决办法:使用len进行参数传递,如new String(bytes,0,len)");
fis.close();
}
}
六.文件拷贝改进:快速拷贝大文件
public class Demo286 {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("C:\\Users\\33428\\Videos\\haniwa\\いつだって戦ってる.mp4");
FileOutputStream fos = new FileOutputStream("C:\\Users\\33428\\Desktop\\Haniwa.mp4");
byte[] bytes = new byte[1024 * 1024*10];
int len;
while ((len = fis.read(bytes)) != -1) fos.write(bytes, 0, len);
fos.close();
fis.close();
}
}
七.finally:捕获异常完整形态
1.finally后面的代码块的执行特点? 2.如何在try-catch之后使用finally关闭流?
public class Demo287 {
public static void main(String[] args) {
System.out.println("1.finally一定会执行:除非虚拟机停止");
String str = "JAVA基础\\src\\Day28\\MyText\\a.txt";
System.out.println("2.在try-catch代码块外设置io流为null");
FileInputStream fis = null;
try {
fis = new FileInputStream(str);
fis.read();
} catch (IOException e) {
e.printStackTrace();
} finally {
System.out.println("在finally中,只有建立了传输通道(IO流不为null)才关闭");
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
八.AutoCloseable:JDK7出现:特定情况下自动释放资源
实现这个接口的类可以在try-catch后自动释放资源 在try-catch中具体应该如何实现自动释放资源?
public class Demo288 {
public static void main(String[] args) {
String str1 = "JAVA基础\\src\\Day28\\MyText\\a.txt";
String str2 = "JAVA基础\\src\\Day28\\MyText\\aCopy.txt";
System.out.println("在try后加入括号(),在括号中写入需要定义的对象,对象用分号隔开");
System.out.println("JDK9之后就可以在外面创建对象,括号里面只写变量名");
try (FileInputStream fis = new FileInputStream(str1);
FileOutputStream fos = new FileOutputStream(str2)) {
fis.read();
} catch (IOException e) {
e.printStackTrace();
}
}
}
九.使用使用String与byte数组进行编码解码
1.字符集详解 Windows中文系统使用的编码方式是什么?系统显示为什么? windows中文系统使用的就是GBK(国家标准扩展,是一种编码方式),系统显示为ANSI 2.在GBK编码中,汉字用多少个字节存储?一般以0开头还是1开头? 在GBK中一个汉字用两个字节存储,英文二进制0开头,中文1开头 3.UniCode字符集:包含世界大多数文字 4.UTF-数字,后面的数字代表什么意思,在UTF-8中,中日韩文一般用多少个字节存储? UTF-16:(UniCode Transfer Format)最常用的就是转成16比特位(两字节) UTF-32:统一32字节保存 UTF-8:用1-4字节保存,使用的最多,英文一个字节,中日韩三个字节 5.在UTF-8中,1-4位字节的数据的每个字节的开头有什么特点? 一个字节的第一位是0(留下7位自由选择) 两个字节的前两位是110,后面字节的全是10开头(留下11位自由选择) 三个字节前两位是1110,后面字节全是10开头(留下16位自由选择) 上面这样做是为了区别一个字符开始的字节在何处 6.UTF-8如何对汉字进行编码? 汉字要先查询Unicode,再转换成UTF-8编码 7.乱码的原因大多数是因为什么? 乱码原因,很大原因是编码解码方式不一样:如GBK一次读汉字读两个字节,而UTF-8一次读三个字节 8.如何避免乱码? 避免乱码:不要用字节流读取文本文件,编码解码使用同一字符集与同一编码方式 使用使用String与byte数组进行编码解码 1.如何把字符串编码变成字节数组? 2.如何把字节数组解码变成字符串? 3.上述两个操作如何指定编码与解码方式?
public class Demo289 {
public static void main(String[] args) throws UnsupportedEncodingException {
String str = "元神,启动!";
System.out.println("1.使用String的getBytes方法,把要存储的数据进行编码:以默认方式(UTF-8)编码");
byte[] bytes = str.getBytes();
System.out.println(Arrays.toString(bytes));
System.out.println("2.在字符串中的构造方法中传入字节数组解码:把字节数据变成想要查看的内容,默认UTF-8");
System.out.println(new String(bytes,"UTF-8"));
System.out.println("3.getBytes方法中传入参数代表编码方式");
bytes = str.getBytes("GBK");
System.out.println(Arrays.toString(bytes));
System.out.println("4.传入第二个参数代表解码方式");
System.out.println(new String(bytes,"GBK"));
}
}
十.FileReader与FileWriter:操作本地文件的字符输入输出流
字符流 1.字符流的底层是? 底层就是字节流,添加了字符集的概念,适合操作纯文本文件 2.字符输入流与输出流每一次读取或写出多少数据? 输入流:按照规则读取,如果是英文就读一个字节,如果是中文就读三字节(根据不同编码方式) 输出流:按指定编码格式进行编码并且写到文件当中 3.一般使用什么类进行字符输入与输出? 使用Reader,Writer的实现类:FileReader与FileWriter来读写文件 读写缓存区 在字符流输入流底层,在-内存区-创建了一个8KB的缓冲区来存储数据,在第一次读数据的时候尽量装满,每次读取都从缓冲区中读取 每次读取都会判断缓冲区是否有数据可以读,没有数据读了就在文件中继续找数据放进去,新的数据替代老的数据(多出来的老数据不会清空) 在字符输出流底层,也会在-内存区-创建8KB的byte数组缓存数据 4.在读写缓存区中,数据什么时候会进行传输?有哪三种情况? 只有当: 数组满了 || flush() || close() 才会把数据放进去 5.读写缓存区的位置在哪里? 区别读缓存区与写缓存区:读是一次性先拿,写是一次性后给,都是在内存中创建的空间! FileReader与FileWriter:操作本地文件的字符输入输出流 使用reader与writer的操作与fis与fos情况相似,不同点: 1.字符输入与输出读取与写入的是字符还是字节? 2.字符输出流可以除了写入字符以及字符数组,还能写入什么? 3.在使用输入流的无参read方法时,返回的整数代表什么?
public class Demo2810 {
public static void main(String[] args) throws IOException {
FileReader fileReader = new FileReader("JAVA基础\\src\\Day28\\MyText\\b.txt");
FileWriter fileWriter = new FileWriter("JAVA基础\\src\\Day28\\MyText\\bCopy.txt");
System.out.println("1.使用字符数组读取与写入");
char[] chars = new char[1024];
int len;
System.out.println("2.除了传递char[],还能传递string去写入");
while ((len = fileReader.read(chars)) != -1) {
fileWriter.write(chars, 0, len);
}
fileWriter.close();
fileReader.close();
fileReader = new FileReader("JAVA基础\\src\\Day28\\MyText\\b.txt");
int i;
System.out.println("3.返回的整数表示字符集上的数据,强转即可变成字符");
while ((i = fileReader.read()) != -1) {
System.out.print((char) i);
}
fileReader.close();
}
}
十一.案例:拷贝文件夹,包括其子文件夹
public class Demo2811 {
public static void main(String[] args) throws IOException {
File file1 = new File("D:\\Java基础\\Java基础-资料");
File file2 = new File("D:\\实验文件夹");
copy(file1, file2);
}
public static void copy(File file1, File file2) throws IOException {
//创建新的文件名字,看情况创建文件或者文件夹,这里使用getName获取文件名或者是文件夹名,不需要使用split方法
File file1Copy = new File(file2, file1.getName());
if (file1.isFile()) {
//是文件,所以要拷贝,这里不需要创建文件:输出流自动创建!
FileInputStream fis = new FileInputStream(file1);
FileOutputStream fos = new FileOutputStream(file1Copy);
byte[] bytes = new byte[1024 * 1024];
int len;
if ((len = fis.read(bytes)) != -1)fos.write(bytes,0,len);
fos.close();
fis.close();
}else {
//不是文件:所以要创建文件夹
file1Copy.mkdirs();
//遍历file1
for (File file : file1.listFiles()) {
copy(file,file1Copy);
}
}
}
}
十二.案例:文件加密与解密
a^b^b之后依然是a:如100^10 1100100 a 0001010 b ————————— 1101110 密文 0001010 b ————————— 1100100 a 这里我们只看一位: 1^0^0:在这里1一直不变 1^1^1:在这里1取反变0再取反变1 0也是这样的结果。 奇妙比喻:1碰到0:不变即可,1碰到1:总得有一方变0 结论:计算机中的数据经过两次相同的异或运算之后,数据不变
public class Demo2812 {
public static void main(String[] args) throws IOException {
encryptAndDecrypt("a.jpg", "b.jpg");
encryptAndDecrypt("b.jpg", "c.jpg");
}
public static void encryptAndDecrypt(String str1, String str2) throws IOException {
String str = "Java基础\\src\\Day28\\MyPic\\";
FileInputStream fis = new FileInputStream(str + str1);
FileOutputStream fos = new FileOutputStream(str + str2);
byte[] bytes = new byte[1024];
int len;
while ((len = fis.read(bytes)) != -1) {
for (int i = 0; i < bytes.length; i++) bytes[i] ^= 66;
fos.write(bytes, 0, len);
}
fos.close();
fis.close();
}
}
十三.案例:修改文件中的数据,再排序数据
public class Demo2813 {
public static void main(String[] args) throws IOException {
FileReader reader = new FileReader("D:\\IDEACode\\demo1\\JAVA基础\\src\\Day28\\MyText\\c.txt");
StringBuilder sb= new StringBuilder();
int i;
//如果是用数组的方式读取,一定要记得要限制范围
while((i=reader.read())!=-1) sb.append((char)i);
reader.close();
//可以先把read的操作全部做完再创建writer
FileWriter writer = new FileWriter("D:\\IDEACode\\demo1\\JAVA基础\\src\\Day28\\MyText\\cSort.txt");
String str= Arrays.toString(Arrays.stream(sb.toString().split("-"))
.map(Integer::parseInt).sorted().toArray(Integer[]::new))
//这里对于数据只用改动部分(只需要替换字符与去除第一个与最后一个字符),无需StringBuilder再遍历了,尽量简化你的操作
.replace(", ","-");
writer.write(str.substring(1,str.length()-1));
writer.close();
}
}