回顾
File对象的创建方式
new File("路径");
new File("父路径","子路径");
new File(new File("父路径"),"子路径");
File类常用方法
getName() 获取文件或文件夹名
getAbsolutePath() 获取绝对路径
length() 获取文件的大小(不能获取文件夹) 求文件夹的大小?
createNewFile() 创建文件
mkdirs() 创建多层文件夹
delete() 删除一个文件或空文件夹(不能删除有内容的文件夹) 删除文件夹?
isFile() 判断是否是一个文件
isDirectory() 判断是否是一个文件夹
exists() 判断是否存在
list() 获取文件夹中所有内容的名称
listFiles() 获取文件夹中所有内容的File对象形式
相对路径和绝对路径
绝对路径:从盘符开始写的路径
相对路径:不从盘符开始写的路径,相对的是当前项目
递归会内存溢出隐患的原因
递归会一直调用方法,如果无限递归就会导致内存溢出
IO流的分类和功能
字节输出流
FileOutputStream
write(int a) 输出一个字节
write(byte[] b) 输出一个字节数组
write(byte[] b,int off,int len) 输出字节数组的一部分
字节输入流
FileInputStream
read() 输入一个字节
read(byte[] b) 输入一个字节数组
字符输出流
FileWriter
write(int c) 输出一个字符
write(char[] chs) 输出一个字符数组
write(char[] chs,int off,int len)输出一个字符数组
write(String s) 输出字符串
flush() 刷新
字符输入流
FileReader
read() 输入一个字符
read(char[] chs) 输入一个字符数组
1.Properties类【重要】
1.概述
Properties叫属性集。是Hashtable的子类,属于双列集合,这个集合键值对都是字符串类型,不需要规定泛型。我们通常使用属性集和流相关的方法。
2.构造方法
方法 | 说明 |
---|---|
public Properties() | 创建一个空的属性列表。 |
3.常用方法
方法 | 说明 |
---|---|
Object setProperty(String key ,String value) | 添加键值对 |
String getProperty(String key) | 根据键获取值 |
stringPropertyNames() | 获取所有的键 |
load(输入流) | 把文件中的键值对数据读到集合中 |
store(输出流,String comments) | 把集合中的键值对保存到文件中 |
-
集合相关方法
package com.itheima_01; import java.util.Properties; import java.util.Set; public class Test01 { public static void main(String[] args) { //创建对象 Properties pro = new Properties(); //添加键值对 pro.setProperty("username","柳岩"); pro.setProperty("password","123456"); //通过键获取值 String s = pro.getProperty("username"); System.out.println(s); //柳岩 //获取所有的键 Set<String> set = pro.stringPropertyNames(); System.out.println(set); //[password, username] } }
-
IO相关方法
-
读数据
package com.itheima_01; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.util.Properties; public class Test02 { public static void main(String[] args) throws IOException { //创建对象 Properties pro = new Properties(); //输入 //会把文件中的键值对读取到集合中 FileReader fr = new FileReader("day11\\abc.properties"); pro.load(fr); //通过键获取值 String username = pro.getProperty("username"); String password = pro.getProperty("password"); String font = pro.getProperty("font"); System.out.println("用户名是" + username); System.out.println("密码是" + password); fr.close(); } }
-
写数据
package com.itheima_01; import java.io.FileWriter; import java.io.IOException; import java.util.Properties; public class Test03 { public static void main(String[] args) throws IOException { //创建对象 Properties pro = new Properties(); //添加 pro.setProperty("font","16"); pro.setProperty("color","white"); FileWriter fw = new FileWriter("day11\\abc.properties"); //store() :把集合中的键值对写出到文件中 //第一个参数输出流,第二个参数输出备注 pro.store(fw,"helloworld"); fw.close(); } }
-
2.ResourceBundle工具类【了解】
1.作用
可以在某些情况下替代Properties完成读取文件中的键值对。
前提:
文件必须以.properties作为后缀
文件必须放在src这个目录下
2.创建对象
// 使用指定的基本名称,默认语言环境和调用者的类加载器获取资源包。
static ResourceBundle getBundle(String baseName);
3.获取方法
String getString(String key) //根据键获取值
- 示例代码
package com.itheima_01;
import java.util.ResourceBundle;
public class Test04 {
public static void main(String[] args) {
//静态方法
ResourceBundle bundle = ResourceBundle.getBundle("abc");
//根据键获取值
String font = bundle.getString("font");
System.out.println(font);
String color = bundle.getString("color");
System.out.println(color);
}
}
3.缓冲流【重点】
1.介绍
普通流的使用效率比较低,java提供了四个缓冲流用来提高之前四个普通流的效率。
缓冲输出流都是会把数据先输出到缓冲区。
FileOutputStream --> BufferedOutputStream
FileInputStream --> BufferedInputStream
FileWriter --> BufferedWriter
FileReader --> BufferedReader
2.字节缓冲流
-
构造方法
public BufferedInputStream(InputStream in) : 创建一个新的缓冲输入流。 public BufferedOutputStream(OutputStream out) : 创建一个新的缓冲输出流。
-
缓冲效果展示
- 字节缓冲流作用就只是提高效率,没有什么特殊的功能。
package com.itheima_02; import java.io.*; public class Test01 { public static void main(String[] args) throws IOException { //public BufferedInputStream(InputStream in) : 创建一个新的缓冲输入流。 BufferedInputStream bis = new BufferedInputStream(new FileInputStream("day11\\123.txt")); //public BufferedOutputStream(OutputStream out) : 创建一个新的缓冲输出流。 BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("day11\\123.txt")); //方法 /* 输入流 读取一个字节 读取一个字节数组 */ /* 输出流 输出一个字节 输出一个字节数组 输出一个字节数组的一部分 */ bis.close(); bos.close(); } }
3.字符缓冲流
-
构造方法
public BufferedReader(Reader in) :创建一个新的缓冲输入流。 public BufferedWriter(Writer out) : 创建一个新的缓冲输出流。
-
方法演示
- 之前字符流有的方法缓冲流都有!!
package com.itheima_02; import java.io.*; public class Test02 { public static void main(String[] args) throws IOException { //public BufferedReader(Reader in) :创建一个新的缓冲输入流。 BufferedReader br = new BufferedReader(new FileReader("day11\\123.txt")); //public BufferedWriter(Writer out) : 创建一个新的缓冲输出流。 BufferedWriter bw = new BufferedWriter(new FileWriter("day11\\123.txt")); /* 方法 字符缓冲输入流 输入一个字符 输入一个字符数组 字符缓冲输出流 输出一个字符 输出一个字符数组 输出一个字符数组的一部分 输出一个字符串 */ br.close(); bw.close(); } }
-
字符缓冲流特有方法
-
方法
BufferedReader: public String readLine() : 读一行文字。 BufferedWriter: public void newLine() : 写换行,由系统属性定义符号
-
示例代码
- 读取一行
package com.itheima_02; import java.io.BufferedReader; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; public class Test03 { public static void main(String[] args) throws IOException { //字符缓冲流的特有方法 BufferedReader br = new BufferedReader(new FileReader("day11\\123.txt")); //readLine() 读取一整行 System.out.println(br.readLine()); //窗前明月光 System.out.println(br.readLine()); System.out.println(br.readLine()); //如果读到了末尾 文件会返回null br.close(); } }
- 换行
package com.itheima_02; import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; public class Test04 { public static void main(String[] args) throws IOException { BufferedWriter bw = new BufferedWriter(new FileWriter("day11\\123.txt")); //输出 bw.write("锄禾日当午"); //bw.write("\r\n"); // \r\n是windows系统的标准换行符号,别的系统是别的符号 //换行,兼容不同的系统 bw.newLine(); bw.write("汗滴。。。。"); //关流 bw.close(); } }
-
-
缓冲流的小结
字节缓冲流 没有特殊的方法,只是提高了效率 字符缓冲流 第一个功能就是提高效率 特殊功能: 读取一整行readLine() 写出换行符newLine()
-
练习题
- 需求:排序
- 排序前文件里面是乱序的,排序后,文件里面是123456789
3.侍中、侍郎郭攸之、费祎、董允等,此皆良实,志虑忠纯,是以先帝简拔以遗陛下。愚以为宫中之事,事无大小,悉 以咨之,然后施行,必得裨补阙漏,有所广益。 8.愿陛下托臣以讨贼兴复之效,不效,则治臣之罪,以告先帝之灵。若无兴德之言,则责攸之、祎、允等之慢,以彰其 咎;陛下亦宜自谋,以咨诹善道,察纳雅言,深追先帝遗诏,臣不胜受恩感激。 4.将军向宠,性行淑均,晓畅军事,试用之于昔日,先帝称之曰能,是以众议举宠为督。愚以为营中之事,悉以咨之, 必能使行阵和睦,优劣得所。 2.宫中府中,俱为一体,陟罚臧否,不宜异同。若有作奸犯科及为忠善者,宜付有司论其刑赏,以昭陛下平明之理,不 宜偏私,使内外异法也。 1.先帝创业未半而中道崩殂,今天下三分,益州疲弊,此诚危急存亡之秋也。然侍卫之臣不懈于内,忠志之士忘身于外 者,盖追先帝之殊遇,欲报之于陛下也。诚宜开张圣听,以光先帝遗德,恢弘志士之气,不宜妄自菲薄,引喻失义,以 塞忠谏之路也。 9.今当远离,临表涕零,不知所言。 6.臣本布衣,躬耕于南阳,苟全性命于乱世,不求闻达于诸侯。先帝不以臣卑鄙,猥自枉屈,三顾臣于草庐之中,咨臣 以当世之事,由是感激,遂许先帝以驱驰。后值倾覆,受任于败军之际,奉命于危难之间,尔来二十有一年矣。 7.先帝知臣谨慎,故临崩寄臣以大事也。受命以来,夙夜忧叹,恐付托不效,以伤先帝之明,故五月渡泸,深入不毛。 今南方已定,兵甲已足,当奖率三军,北定中原,庶竭驽钝,攘除奸凶,兴复汉室,还于旧都。此臣所以报先帝而忠陛 下之职分也。至于斟酌损益,进尽忠言,则攸之、祎、允之任也。 5.亲贤臣,远小人,此先汉所以兴隆也;亲小人,远贤臣,此后汉所以倾颓也。先帝在时,每与臣论此事,未尝不叹息 痛恨于桓、灵也。侍中、尚书、长史、参军,此悉贞良死节之臣,愿陛下亲之信之,则汉室之隆,可计日而待也。
-
代码编写
package com.itheima_02; import java.io.*; import java.util.ArrayList; import java.util.TreeSet; public class Test05 { public static void main(String[] args) throws IOException { //输入流 BufferedReader br = new BufferedReader(new FileReader("day11\\出师表.txt")); //集合用于存储字符串 TreeSet<String> set = new TreeSet<>(); //每次读取一行 String line; while((line =br.readLine()) != null){ //把字符串添加到集合中 set.add(line); } System.out.println(set); //把每个字符串输出到文件中 //输出流 BufferedWriter bw = new BufferedWriter(new FileWriter("day11\\出师表.txt")); //遍历集合 for (String s : set) { bw.write(s); //换行 bw.newLine(); } //关流 br.close(); bw.close(); } }
4.转换流【重要】
1.编码表
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9OMS077n-1598452343559)(img\码表问题.png)]
2.输入转换流InputStreamReader类
-
构造方法
InputStreamReader(InputStream in) : 创建一个使用默认字符集的字符流。 InputStreamReader(InputStream in, String charsetName) : 创建一个指定字符集的字符流
-
代码演示
package com.itheima_03; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStreamReader; public class Test01 { public static void main(String[] args) throws IOException { //输入转换流的构造方法 //idea的默认是UTF-8 //InputStreamReader(InputStream in) : 创建一个使用默认字符集的字符流。 //InputStreamReader isr = new InputStreamReader(new FileInputStream("C:\\Users\\jin\\Desktop\\1234.txt")); //InputStreamReader(InputStream in, String charsetName) // : 创建一个指定字符集的字符流 InputStreamReader isr = new InputStreamReader(new FileInputStream("C:\\Users\\jin\\Desktop\\1234.txt"),"GBK"); //可以调用普通字符流的方法 //读取一个字符 int read = isr.read(); System.out.println((char)read); int read2 = isr.read(); System.out.println((char)read2); //关流 isr.close(); } }
3.输出转换流OutputStreamWriter类
-
构造方法
OutputStreamWriter(OutputStream in) : 创建一个使用默认字符集的字符流。 OutputStreamWriter(OutputStream in, String charsetName) : 创建一个指定字符集的字符流
-
代码演示
package com.itheima_03; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; public class Test02 { public static void main(String[] args) throws IOException { //输出转换流OutputStreamWriter //OutputStreamWriter(OutputStream in) : 创建一个使用默认字符集的字符流。 //OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("day11\\123.txt")); //OutputStreamWriter(OutputStream in, String charsetName) // : 创建一个指定字符集的字符流 OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("day11\\123.txt"),"GBK"); //输出字符串 osw.write("中国"); osw.close(); } }
-
总结
转换流的本质也是字符流,所以可以调用字符流的方法 转换流用于指定编码表的情况 在idea上普通流不能指定码表,默认都是UTF-8
4.练习:把UTF-8文件转成GBK
把’'出师表.txt"UTF-8编码的文件 变成了 ‘’出师表2.txt‘’GBK编码的文件
package com.itheima_03;
import java.io.*;
public class Test03 {
public static void main(String[] args) throws IOException {
//输入流 (普通字符)
FileReader fr = new FileReader("day11\\出师表.txt");
//输出流(字符转换)
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("day11\\出师表2.txt"),"GBK");
//一次读取一个字符
int c;
while((c = fr.read()) != -1){
osw.write(c);
}
//关流
osw.close();
fr.close();
}
}
5.序列流【重点】
1.概述
序列流可以操作对象。
序列化:把对象从内存保存到文件中。
反序列化:把对象从文件读取到内存中。
2.ObjectOutputStream类
序列化流,对象输出流
-
构造方法
public ObjectOutputStream(OutputStream out) : 创建一个指定的ObjectOutputStream
-
写出对象方法
public final void writeObject (Object obj) : 将指定的对象写出。
-
常见的两个疑惑
- Serializable这个接口我们称为是标记型接口,这个接口中没有任何的方法。
- 输出的对象在电脑中显示是乱码,这是正常的。因为电脑根本就没有查看对象的方式。
-
代码演示
package com.itheima_04; import java.io.*; public class Test01 { public static void main(String[] args) throws IOException { //ObjectOutputStream序列化流,对象输出流 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("day11\\123.txt")); //创建对象 Student s = new Student("柳岩",38); //输出任意类型对象 oos.writeObject(s); //关流 oos.close(); } }
3.ObjectInputStream类
反序列化流, 对象输入流
-
构造方法
public ObjectInputStream(InputStream in) : 创建一个指定的ObjectInputStream
-
读取对象方法
public final Object readObject() : 读取一个对象。
-
代码演示
package com.itheima_04; import java.io.FileInputStream; import java.io.IOException; import java.io.ObjectInputStream; public class Test02 { public static void main(String[] args) throws IOException, ClassNotFoundException { //对象输入流 ObjectInputStream ois = new ObjectInputStream(new FileInputStream("day11\\123.txt")); //读取对象 Object obj = ois.readObject(); //向下转型 Student s = (Student)obj; System.out.println(s); //关流 ois.close(); } }
4.对象操作流的作用
对象操作流作用就是输出输入对象类型,别的流都是只能操作文本。
5.对象操作流的小知识点
-
transient关键字
-
transient表示瞬态,被瞬态修饰的成员变量不会被序列化。
private transient int age;
-
-
serialVersionUID问题
-
每个类都有一个UID编号,每次修改类编号都会随机改变,如果类在序列化和反序列化之间编号不同,反序列化会失败。如果中间要修改这个类,需要在序列化之前手动指定一个UID.
private static final long serialVersionUID = 2423534534634645L;
-
-
序列化多个对象
-
readObject()方法在读取到末尾的时候会直接抛出EOFException,不建议读取多次。
如果想要保存多个对象,建议把多个对象放在一起一次保存(用集合存储)。
package com.itheima_04; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; import java.util.ArrayList; public class Test03 { public static void main(String[] args) throws IOException { //ObjectOutputStream序列化流,对象输出流 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("day11\\123.txt")); //创建对象 Student s1 = new Student("柳岩",38); Student s2 = new Student("崔航",28); //放在集合中 ArrayList<Student> list = new ArrayList<>(); list.add(s1); list.add(s2); //输出任意类型对象 oos.writeObject(list); //关流 oos.close(); } } package com.itheima_04; import java.io.FileInputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.util.ArrayList; @SuppressWarnings("all") public class Test04 { public static void main(String[] args) throws IOException, ClassNotFoundException { //对象输入流 ObjectInputStream ois = new ObjectInputStream(new FileInputStream("day11\\123.txt")); //读取对象 Object obj = ois.readObject(); //向下转型 ArrayList<Student> list = (ArrayList<Student>)obj; //打印 System.out.println(list); //关流 ois.close(); } }
-
6.打印流【了解】
1.概述
打印流帮助程序把数据用打印的方式来输出。
2.构造方法
public PrintStream(String fileName) : 使用指定的文件名创建一个新的打印流。
3.代码演示
package com.itheima_05;
import java.io.FileNotFoundException;
import java.io.PrintStream;
public class Test01 {
//打印流
public static void main(String[] args) throws FileNotFoundException {
//创建对象
PrintStream ps = new PrintStream("day11\\123.txt");
//输出
//以打印的方式来输出,你写啥就是啥
ps.print(97);
ps.print(98);
ps.print(1);
ps.print(3.14);
ps.print("哈哈哈");
ps.println('a');
ps.println('b');
ps.println('c');
//在控制台输出数据
System.out.println();
//输出语句使用ps这个对象作为打印流
System.setOut(ps);
System.out.println("柳岩");
//关流
ps.close();
}
}
7.装饰设计模式
1.概述
如果想要对类进行增强,且不想使用继承的情况下。就可以使用装饰设计模式。
前提:
被装饰类必须实现接口。
2.装饰设计模式写法
-
用装饰类实现和被装饰类同样的接口。
-
在装饰类中定义被装饰类的对象,使用构造方法传入对象。
-
需要增强的方法自己去编写。
-
不需要增强的方法调用被装饰类原来的方法。
3.代码演示
package com.itheima_05;
public interface Star {
//唱跳
void singAndDance();
//rap
void rap();
}
//被装饰类
public class CaiXuKun implements Star{
//功能
public void singAndDance(){
System.out.println("唱跳");
}
public void rap(){
System.out.println("鸡你太美~");
}
}
//装饰类 增强类
public class BufferedCaiXuKun implements Star {
//定义成员变量
CaiXuKun cxk;
//构造方法
public BufferedCaiXuKun(CaiXuKun cxk) {
this.cxk = cxk;
}
@Override
//增强的方法
public void singAndDance() {
System.out.println("唱青藏高原");
System.out.println("跳广场舞");
}
@Override
public void rap() {
cxk.rap();
}
}
public class Test02{
public static void main(String[] args) {
//创建增强类对象
BufferedCaiXuKun bc = new BufferedCaiXuKun(new CaiXuKun());
//调用方法
bc.rap();
bc.singAndDance();
}
}
4.开发的原则
开发的原则:
高内聚,低耦合
内聚:自己独立完成功能的能力。
耦合:代码和代码之间的依赖。
继承有一个缺点就是会提高类的耦合。
8.commons-io包
1.概述
commons-io是一个第三方jar包。
commons-io是Apache基金组织开发的开源工具,这个工具不在JDK里,使用的时候需要单独导入jar包。
2.使用方式
- 下载commons-io相关jar包;http://commons.apache.org/proper/commons-io/
- 把commons-io-2.6.jar包复制到指定的Module的lib目录中
- 将commons-io-2.6.jar加入到classpath【右键–add as Library–选择到模块中】
3.方法
-
IOUtils类中
- public static int copy(InputStream in, OutputStream out) 文件复制(适合文件大小为2GB以下)
- public static long copyLarge(InputStream in, OutputStream out) 文件复制(适合文件大小为2GB以上)
-
FileUtils类中
- public static void copyFileToDirectory(final File srcFile, final File destFile) //复制文件到另外一个目录下
- public static void copyDirectoryToDirectory( file1 , file2 );//复制file1目录到file2位置
package com.itheima_06; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import java.io.*; public class Test01 { public static void main(String[] args) throws IOException { //IOUtils //public static int copy(InputStream in, OutputStream out) 文件复制(适合文件大小为2GB以下) //IOUtils.copy(new FileInputStream("day11\\出师表.txt"),new FileOutputStream("C:\\Users\\jin\\Desktop\\出师表.txt")); //public static long copyLarge(InputStream in, OutputStream out) 文件复制(适合文件大小为2GB以上) //IOUtils.copyLarge(new FileInputStream("day11\\出师表.txt"),new FileOutputStream("C:\\Users\\jin\\Desktop\\出师表.txt")); //FileUtils //public static void copyFileToDirectory(final File srcFile, final File destFile) //复制文件到另外一个目录下 //FileUtils.copyFileToDirectory(new File("C:\\Users\\jin\\Desktop\\1234.txt"),new File("C:\\Users\\jin\\Desktop\\day11")); //public static void copyDirectoryToDirectory( file1 , file2 );//复制file1目录到file2位置 FileUtils.copyDirectoryToDirectory(new File("C:\\Users\\jin\\Desktop\\repositorys"),new File("C:\\Users\\jin\\Desktop\\day11")); } }
其实我们现在所能想到的功能,都已经有人实现了。
现阶段学习的很多知识点都是原理并不是应用。
9.IO流的异常处理
-
JDK7之前
package com.itheima_06; import java.io.*; public class Test02 { public static void main(String[] args){ OutputStreamWriter osw = null; try { //创建转换流对象 osw = new OutputStreamWriter(new FileOutputStream("day11"), "GBK"); //输出汉字 osw.write("中国"); }catch (IOException e){ }finally { //一定会执行的代码 try { //关流 if(osw != null) { osw.close(); } }catch (IOException e){ } } } }
-
JDK7之后
try(创建流对象;创建流对象){ 其他代码 }catch(异常类型 异常对象){ } 不需要调用关流方法,这个写法代码会自动帮我们关流
package com.itheima_06; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; public class Test03 { public static void main(String[] args) throws IOException { //JDK7之后trycatch可以帮我们关流 try(OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("day11\\123.txt"),"GBK")){ osw.write("中国"); }catch (IOException e){ //异常处理 } } }
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-v62Jwfse-1598452343561)(img\流的总结.png)]