目录
Lambda
一、使用Lambda必须具有接口 且要求接口中有且仅有一个抽象方法
二、有且仅有一个抽象方法的接口称为函数式接口
三、Lambda表达式的标准格式: 一些参数、一个箭头、一段代码
四、格式:(参数列表)->{一些重写方法的代码};
解释说明格式:
()
:接口中抽象方法的参数列表 没有参数 就空着 有参数就写出参数 多个参数使用逗号分隔
->
:传递的意思 把参数传递给方法体{}
{}
:重写接口的抽象方法的方法体
五、Lambda表达式是可以推导 可以省略的 凡是根据上下文推导出来的内容 都可以省略书写
可以省略的内容:
- (参数列表):括号中参数列表的数据类型 可以省略不写
- (参数列表):括号中的参数如果只有一个 那么类型和
()
都可以省略- (一些代码):如果
{}
中的代码只有一行 无论是否有返回值 都可以省略{}
return
分号
。【注】:要省略{} return 分号必须一起省略
六、题目:给定一个厨子cook
接口 内含唯一的抽象方法makefood
且无参数 无返回值 使用Lambda
的标准格式调用invokeCook
方法 打印输出“吃饭啦!
”
public class LambdaClass {
public static void main(String[] args) {
//使用Lambda表达式 简化匿名内部类的书写
invokeCook(()->{
System.out.println("吃饭了!");
});
}
//定义一个方法 参数传递Cook接口 方法内部调用Cook接口中的方法makeFood
public static void invokeCook(Cook cook) {
cook.makeFood();
}
}
public interface Cook {
//定义无参数无返回值的方法makeFood
public abstract void makeFood();
}
Lambda表达式有参数有返回值的练习
需求:使用数组存储多个Person对象 对数组中的Person对象使用Arrays的sort方法通过年龄进行升序排序
import java.util.Arrays;
import java.util.Comparator;
public class LambdaArrays {
public static void main(String[] args) {
//使用数组存储多个Person对象
Person[] arr = {
new Person("柳岩",38),new Person("迪丽热巴",18),new Person("古力娜扎",19),
};
//对数组中的Person对象使用Arrays的sort方法通过年龄进行升序排序
// Arrays.sort(arr,new Comparator<Person>() {
// @Override
// public int compare(Person o1, Person o2) {
// return o1.getAge() - o2.getAge();
// }
// });
//使用Lambda表达式 简化匿名内部类
Arrays.sort(arr,(Person o1, Person o2)->{
return o1.getAge() - o2.getAge();
});
//遍历数组
for (Person person : arr) {
System.out.println(person);
}
System.out.println("有参数有返回值的类型:===================================================");
//调用invokeCalc方法 方法的参数是一个接口 可以使用匿名内部类
// invokeCalc(10, 20, new Calculator() {
// @Override
// public int calc(int a, int b) {
// return a + b;
// }
// });
//使用Lambda表达式简化匿名内部类的书写
invokeCalc(120, 130, (int a,int b)->{
return a + b;
});
}
//定义一个方法 参数传递两个int类型的整数 参数传递calculator接口 方法内部调用calculator中的方法calc计算两个整数的和
public static void invokeCalc(int a,int b,Calculator c) {
int sum = c.calc(a, b);
System.out.println(sum);
}
}
public class Person {
private String nameString;
private int age;
@Override
public String toString() {return "Person [nameString=" + nameString + ", age=" + age + "]";}
public Person(String nameString, int age) {
super();
this.nameString = nameString;
this.age = age;
}
public Person() {super();}
public String getNameString() {return nameString;}
public void setNameString(String nameString) {this.nameString = nameString;}
public int getAge() {return age;}
public void setAge(int age) {this.age = age;}
}
/*
* 给定一个计算器Calculator接口 内含抽象方法calc可以将两个int数字相加得到和 使用Lambda的标准格式调用invokeCalc方法 完成120和130的相加计算
*/
public interface Calculator {
public abstract int calc(int a,int b);
}
递归
一、递归:指在当前方法内调用自己
二、递归分为两类:直接递归(方法自身调用自己)间接递归(A方法调用B方法 B方法调用C方法 C方法调用A方法)
【注】:
- 递归一定要有条件限定 保证递归能够停止下来 否则会发生栈内存溢出
- 在递归中虽然有限定条件 但是递归次数不能太多 否则也会发生栈内存溢出
- 构造方法禁止递归
三、递归的使用前提:当调用方法时 方法的主体不变 每次调用方法的参数不同 可以使用递归
public class DiGui {
public static void main(String[] args) {
//a();
b(1);
}
/*
* 在递归中虽然有限定条件 但是递归次数不能太多 否则也会发生栈内存溢出
* Exception in thread "main" java.lang.StackOverflowError
*
*/
private static void b(int i) {
System.out.println(i);
if (i == 20000) {
return;//结束方法
}
b(++i);
}
/*
* 递归一定要有条件限制 保证递归能够停下来 否则会发生栈内存溢出
* Exception in thread "main" java.lang.StackOverflowError
* a方法会在栈内存中一直调用a方法 就会导致栈内存中有无数多个a方法 方法太多了 超出栈内存的大小 就会导致内存溢出的错误
* 【注】:当一个方法调用其他方法的时候 被调用的方法没有执行完毕 当前方法会一直等待调用的方法执行完毕 才会继续执行
*/
private static void a() {
System.out.println("a方法!");
a();
}
/*
* 构造方法禁止递归
* 编译报错:构造方法是创建对象使用的 一直递归会导致内存中有无数多个对象 所以直接编译就报错了
*/
public void Recurison() {
//Recurison();
}
}
java.io.File
一、java.io.File
类:文件和目录路径名的抽象表示形式
二、java把电脑中的文件和文件夹(目录)封装为了一个file
类 我们可以使用file
类对文件和文件夹进行操作
三、我们可以使用file
类的方法:创建一个文件/文件夹 删除文件/文件夹 获取文件/文件夹 判断文件/文件夹是否存在 对文件夹进行遍历 获取文件的大小
四、file
类是一个与系统无关的类 任何的操作系统都可以使用这个类中的方法
五、重点:记住以下单词:file
文件 directory
文件夹(目录) path
路径
- 路径:
(1)绝对路径:是一个完整的路径 以盘符(c:
,d:
)开始的路径。如:c:\\a.txt d:\\demo\\b.txt
、c:\\users\itcast\\ideaProjects\\shungyuan\\123.txt
(2)相对路径:是一个简化的路径。相对指的是相对于当前项目的根目录(c:\\users\itcast\\ideaProjects\\shungyuan
)。如果使用当前项目的根目录 路径可以简化书写:c:\\users\itcast\\ideaProjects\\shungyuan\\123.txt
简化为123.txt
(可以省略项目的根目录)
【注】:
- 路径是不区分大小写
- 路径中的文件名称分隔符Windows使用反斜杠
/
反斜杠是转义字符 两个反斜杠代表一个普通的反斜杠
import java.io.File;
public class FileClass {
public static void main(String[] args) {
/*
* static String pathSeparator:与系统有关的路径分隔符 为了方便 他被表示为一个字符串
* static char pathSeparator:与系统有关的路径分隔符
* static String separator:与系统有关的默认名称分隔符 为了方便 他被表示为一个字符串
* static char separatorChar:与系统有关的默认名称分隔符
*/
String pathSeparatorString = File.pathSeparator;
System.out.println(pathSeparatorString);//;路径分隔符 windows:分号; linux:冒号:
String separetorString = File.separator;
System.out.println(separetorString);//文件名称分隔符\ Windows:反斜杠\ Linux:正斜杠\
/*
* 使用File.separator时 不能因为Windows:反斜杠\ Linux:正斜杠\ 在操作路径时 就直接写:
* 在Windows系统:c:\develop\a\a.txt或者:
* 在Linux系统:c:/develop/a/a.txt
* 因为如果这样写的话 在Windows中可以操作 但是如果项目拿到Linux中 就不能操作了
* 所以 要这样写:
* "c:"+File.separator+"develop"+File.separator+"a"+File.separator+"a.txt"
*/
show01();
//show02("c:\\","a.txt");//c:\a.txt
show02("d:\\","a.txt");//d:\a.txt
show03();
}
/*
* file类的构造方法:
* File(String parent,String child):根据parent路径名字符串和child路径名字符串创建一个新file实例
* 参数:把路径分成了两个部分
* String parent:父路径
* String child:子路径
* 好处:
* 1.父路径和子路径可以单独书写 使用起来非常灵活 父路径和子路径都可以变化
* 2.父路径是file类型 可以使用file的方法对路径进行一些操作 再使用路径创建对象
*/
private static void show03() {
File parentFile = new File("c:\\");
File file = new File(parentFile,"hello.java");
System.out.println(file);
}
/*
* file类的构造方法:
* File(String parent,String child):根据parent路径名字符串和child路径名字符串创建一个新file实例
* 参数:把路径分成了两个部分
* String parent:父路径
* String child:子路径
* 好处:父路径和子路径可以单独书写 使用起来非常灵活 父路径和子路径都可以变化
*/
private static void show02(String parentString,String childString) {
File file = new File(parentString,childString);
System.out.println(file);
}
/*
* file类的构造方法:
* file(String pathname):通过将给定路径名字符串转换为抽象路径名来创建一个新file实例
* 参数:
* String pathname:字符串的路径名称
* 路径可以以文件、文件夹结尾
* 路径可以是相对路径 绝对路径
* 路径可以是存在 也可以是不存在
* 创建file对象 只是把字符串路径封装为file对象 不考虑路径的真假情况
*/
private static void show01() {
File f1 = new File("D:\\JAVA\\source.a.txt");//不存在的文件
System.out.println(f1);//D:\JAVA\source.a.txt
File f2 = new File("D:\\JAVA\\source");//存在的文件夹
System.out.println(f2);//D:\JAVA\source
File f3 = new File("Day01");
System.out.println(f3);//Day01
}
}
删除
file类创建删除功能的方法:
public boolean createNewFile()
:当且仅当具有该名称的文件尚不存在时 创建一个新的空文件public boolean delete()
:删除由此file表示的文件或目录public boolean mkdir()
:创建由此file表示的目录public boolean mkdirs()
:创建由此file表示的目录 包括任何必须但不存在的父目录
import java.io.File;
import java.io.IOException;
public class FileDelete {
public static void main(String[] args) throws IOException {
show01();
show02();
show03();
}
/*
* public boolean delete():删除由此file表示的文件或目录
* 此方法可以删除构造方法路径中给出的文件/文件夹
* 返回值:布尔值
* true:文件/文件夹删除成功 返回true
* false:文件夹中有内容 不会删除返回false 构造方法中路径不存在false
* 【注】:delete方法是直接在硬盘删除文件/文件夹 不走回收站 删除要谨慎
*/
private static void show03() {
File f1 = new File("E:\\正片\\aaa");
boolean b1 = f1.delete();
System.out.println(b1);
File f2 = new File("E:\\正片\\111\\222\\333");
boolean b2 = f2.delete();
System.out.println(b2);
}
/*
* public boolean mkdir():创建单级空文件夹
* public boolean mkdirs():创建单级空文件夹 多级空文件夹
* 创建文件夹的路径和名称在方法中给出(构造方法的参数)
* 返回值:布尔值
* true:文件夹不存在 创建文件夹 返回true
* false:文件夹存在 不会创建 返回false
* 【注】:此方法只能创建文件夹 不能创建文件
*/
private static void show02() {
File f1 = new File("E:\\正片\\aaa");
boolean b2 = f1.mkdir();
System.out.println("b2:" + b2);
File f2 = new File("E:\\正片\\111\\222\\333");
boolean b3 = f2.mkdirs();
System.out.println("b3:" + b3);//不能创建 因为只能创建单级文件夹
}
/*
* public boolean createNewFile():当且仅当具有该名称的文件尚不存在时 创建一个新的空文件
* 创建文件的路径和名称在方法中给出(构造方法的参数)
* 返回值:布尔值
* true:文件不存在 创建文件 返回true
* false:文件存在 不会创建 返回false
* 【注】:
* 1.此方法只能创建文件 不能创建文件夹
* 2.创建文件的路径必须存在 否则会抛出异常
*
* public boolean createNewFile() throws IOException
* createNewFile声明抛出了IOException 我们调用这个方法 就必须得处理这个异常 要么throws 要么try...catch
*/
private static void show01() throws IOException {
File f1 = new File("E:\\正片\\1.txt");
boolean b1 = f1.createNewFile();
System.out.println("b1:" + b1);
}
}
获取
file类获取功能的方法:
public String getAbsolutePath()
:返回此file的绝对路径名字符串public String getPath()
:将此file转换为路径名字符串public String getName()
:返回由此file表示的文件或目录的名称public long Length()
:返回由此file表示的文件的长度
import java.io.File;
public class FileGet {
public static void main(String[] args) {
show01();
show02();
show03();
show04();
}
/*
* public long Length():返回由此file表示的文件的长度
* 获取的是构造方法指定的文件的大小 以字节为单位
* 【注】:文件夹是没有大小概念的不能获取文件夹的大小
* 如果构造方法中给出的路径不存在 那么Length方法返回0
*/
private static void show04() {
File f1 = new File("E:\\正片");
long l1 = f1.length();
System.out.println(l1);//4096
}
/*
* public String getName():返回由此file表示的文件或目录的名称
* 获取的就是构造方法传递路径的结尾部分(文件/文件夹)
*
*/
private static void show03() {
File f1 = new File("c:\\users\\itcast\\ideaProjects\\shungyuan\\123.txt");
String nameString = f1.getName();
System.out.println(nameString);//123.txt
File f2 = new File("c:\\users\\itcast\\ideaProjects\\shungyuan");
String nameString2 = f2.getName();
System.out.println(nameString2);//shungyuan
}
/*
* public String getPath():将此file转换为路径名字符串
* 获取的构造方法中传递的路径
*/
private static void show02() {
File f1 = new File("c:\\users\\itcast\\ideaProjects\\shungyuan\\123.txt");
File f2 = new File("a.txt");
String path1 = f1.getPath();
System.out.println(path1);//c:\ users\itcast\ideaProjects\shungyuan\123.txt
String path2 = f2.getPath();
System.out.println(path2);//a.txt
System.out.println(f1);//c:\ users\itcast\ideaProjects\shungyuan\123.txt
System.out.println(f1.toString());//c:\ users\itcast\ideaProjects\shungyuan\123.txt
}
/*
* public String getAbsolutePath():返回此file的绝对路径名字符串
* 获取的构造方法中传递的路径
* 无论路径是绝对的还是相对的 getAbsolutePath方法返回的都是绝对路径
*/
private static void show01() {
File f1 = new File("c:\\users\\itcast\\ideaProjects\\shungyuan\\123.txt");
String absolutePath = f1.getAbsolutePath();
System.out.println(absolutePath);/*c:\ users\itcast\ideaProjects\shungyuan\123.txt*/
File f2 = new File("a.txt");
String absolutePath2 = f2.getAbsolutePath();
System.out.println(absolutePath2);//D:\JAVA\source\Day19\a.txt
}
}
遍历
file类遍历(文件夹)目录功能:
public String[] list()
:返回一个String数组 表示该file目录中的所有子文件或目录public File[] listFile()
:返回一个file数组 表示该file目录中的所有子文件或目录
【注】:
- list方法和listFile方法遍历的是构造方法中给出的目录
- 如果构造方法中给出的目录的路径不存在 会抛出空指针异常
- 如果构造方法中给出的目录的路径不是一个目录 会抛出空指针异常
import java.io.File;
public class FileFor {
public static void main(String[] args) {
show01();
show02();
}
/*
* public File[] listFile():返回一个file数组 表示该file目录中的所有子文件或目录
* 遍历构造方法中给出的目录 会获取目录中所有文件/文件夹 把文件/文件夹封装为file对象 多个file对象存储到file数组中
*/
private static void show02() {
File file = new File("D:\\JAVA\\source");
File[] files = file.listFiles();
for (File f : files) {
System.out.println(f);//连隐藏文件夹都会打印输出
}
}
/*
* public String[] list():返回一个String数组 表示该file目录中的所有子文件或目录
* 遍历构造方法中给出的目录 会获取目录中所有文件/文件夹的名字 把获取到的多个名称存储到一个String类型的数组中
*/
private static void show01() {
File file = new File("D:\\JAVA\\source");
String[] arr = file.list();
for (String fileName : arr) {
System.out.println(fileName);//连隐藏文件夹都会打印输出
}
}
}
判断
file判断功能的方法:
public boolean exists()
:此file表示的文件或目录是否实际存在public boolean isDirectory()
:此file表示的是否为目录public boolean isFile()
:此file表示的是否为文件
import java.io.File;
public class FileIs {
public static void main(String[] args) {
show01();
System.out.println("判断是否为文件/文件夹:============================");
show02();
}
/*
* public boolean isDirectory():此file表示的是否为目录
* 用于判断构造方法中给定的路径是否以文件夹结尾
* 是:true 否:false
* public boolean isFile():此file表示的是否为文件
* 用于判断构造方法中给定的路径是否以文件结尾
* 是:true 否:false
* 【注】:电脑的硬盘中只有文件和文件夹 所以两个方法是互斥的
* 这两个方法的使用前提:路径必须是存在的 否则都返回false
*/
private static void show02() {
File f1 = new File("c:\\users\\itcast\\ideaProjects\\shungyuan\\123.txt");
//System.out.println(f1.isDirectory());//false
//System.out.println(f1.isFile());//false
//因为这个文件不存在 所以都返回false 所以我们在用这两个方法时 可以先判断这个文件到底存不存在
if (f1.exists()) {//不存在就没必要获取
System.out.println(f1.isDirectory());//false
System.out.println(f1.isFile());//false
}
File f2 = new File("E:\\正片");
if (f2.exists()) {//不存在就没必要获取
System.out.println(f2.isDirectory());//true
System.out.println(f2.isFile());//false
}
}
/*
* public boolean exists():此file表示的文件或目录是否实际存在
* 用于判断构造方法中的路径是否存在 存在:true 不存在:false
*/
private static void show01() {
File f1 = new File("E:\\正片");
System.out.println(f1.exists());//true
File f2 = new File("c:\\users\\itcast\\ideaProjects\\shungyuan\\123.txt");
System.out.println(f2.exists());//false
}
}
练习
遍历打印多级目录
import java.io.File;
public class Test3 {
public static void main(String[] args) {
File file = new File("C:\\Users\\dc16102111\\Documents\\Tencent Files\\809476070\\FileRecv");
getAllFile(file);
}
/*
* 定义一个方法 参数传递file类型的目录
* 方法中对目录进行遍历
*/
public static void getAllFile(File dir) {
System.out.println(dir);
File[] files = dir.listFiles();
for (File f : files) {
if(f.isDirectory()){//对遍历得到的file文件f进行判断 判断是否是文件夹
getAllFile(f);//f是一个文件夹 则继续遍历这个文件夹 我们发现 getAllFile方法就是传递文件夹 遍历文件夹的方法 所以直接调用getAllFile方法即可:递归 自己调用自己
} else{
System.out.println(f);//f是一个文件 直接打印即可
}
}
}
}
搜索文件并打印
搜索C:\Users\dc16102111\Documents\Tencent Files\809476070\FileRecv
文件中.md
结尾的文件 并打印输出
import java.io.File;
public class Test4 {
public static void main(String[] args) {
File file = new File("C:\\Users\\dc16102111\\Documents\\Tencent Files\\809476070\\FileRecv");
getAllFile(file);
}
/*
* 定义一个方法 参数传递file类型的目录
* 方法中对目录进行遍历
*/
public static void getAllFile(File dir) {
File[] files = dir.listFiles();
for (File f : files) {
if(f.isDirectory()){//对遍历得到的file文件f进行判断 判断是否是文件夹
getAllFile(f);//f是一个文件夹 则继续遍历这个文件夹 我们发现 getAllFile方法就是传递文件夹 遍历文件夹的方法 所以直接调用getAllFile方法即可:递归 自己调用自己
} else{
//f是一个文件 直接打印即可
//把file对象f转换为字符串对象
//String nameString = f.getName();
//String pathString = f.getPath();
String string = f.toString();
//把字符串转换为小写 更加方便判断 比如 假设有.MD结尾的文件 也可以打印输出
string = string.toLowerCase();
//调用String类中的方法endsWith判断字符串是否是以.java结尾
boolean b = string.endsWith(".md");
//如果是 则打印输出
if (b) {
System.out.println(f);//f是一个文件 直接打印即可
}
/*以上代码可以简化为链式编程:
if (f.getName().toLowerCase().endsWith(".md")) {
System.out.println(f);//f是一个文件 直接打印即可
}
*/
}
}
}
}
过滤器实现
一、搜索C:\Users\dc16102111\Documents\Tencent Files\809476070\FileRecv
文件中.md
结尾的文件 并打印输出,可以使用过滤器来实现。
二、在file
类中有两个和ListFiles
重载的方法 方法的参数传递的就是过滤器
File[] listFiles(FileFilter filter)
(1)java.io.FileFilter
接口:用于抽象路径名(File
对象)的过滤器
(2)作用:用来过滤文件 (File
对象)
(3)抽象方法:用来过滤文件的方法
(4)boolean accept(File pathname)
:测试指定抽象路径名是否应该包含在某个路径名列表中
参数:
File pathname
:使用ListFiles
方法遍历目录 得到的每一个文件对象
File[] listFiles(FilenameFilter filter)
(1)java.io.FilenameFilter
接口:实现此接口的类实例可用于过滤器文件名
(2)作用:用于过滤文件的方法
(3)boolean accept(File dir,String name)
:测试指定文件是否应该包含在某一文件列表中
参数:
File dir
:构造方法中传递的被遍历的目录String name
:使用ListFiles
方法遍历目录 获取的每一个文件/文件夹的名称
【注】:两个过滤器接口是没有实现类的 需要我们自己写实现类 重写过滤的方法accept
在方法中自己定义过滤的规则
import java.io.File;
public class Test5 {
public static void main(String[] args) {
File file = new File("C:\\Users\\dc16102111\\Documents\\Tencent Files\\809476070\\FileRecv");
getAllFile(file);
}
/*
* 定义一个方法 参数传递file类型的目录
* 方法中对目录进行遍历
*/
public static void getAllFile(File dir) {
File[] files = dir.listFiles(new FileFilterImpl());//传递过滤器对象
for (File f : files) {
if(f.isDirectory()){//对遍历得到的file文件f进行判断 判断是否是文件夹
getAllFile(f);//f是一个文件夹 则继续遍历这个文件夹 我们发现 getAllFile方法就是传递文件夹 遍历文件夹的方法 所以直接调用getAllFile方法即可:递归 自己调用自己
} else{
System.out.println(f);//f是一个文件 直接打印即可
}
}
}
}
三、过滤器:创建过滤器FileFilterImpl
的实现类 重写过滤方法accept
定义过滤规则
import java.io.File;
import java.io.FileFilter;
public class FileFilterImpl implements FileFilter{
@Override
public boolean accept(File pathname) {
if (pathname.isDirectory()) {
return true;
}
return pathname.getName().toLowerCase().endsWith(".md");
}
}
四、必须明确两件事:
- 过滤器中的
accept
方法是谁调用的 accept
方法的参数pathname
是什么
五、listFiles
方法一共做了三件事:
listFiles
方法会对构造方法中传递的目录进行遍历 获取目录中的每一个文件/文件夹 把获取的每一个文件/文件夹封装为File
对象listFiles
方法会调用参数传递的过滤器中的方法accept
listFiles
方法会把遍历得到的每一个File
对象 传递给accept
方法的参数pathname
优化
import java.io.File;
import java.io.FileFilter;
import java.io.FilenameFilter;
import java.util.jar.Attributes.Name;
public class Test6 {
public static void main(String[] args) {
File file = new File("C:\\Users\\dc16102111\\Documents\\Tencent Files\\809476070\\FileRecv");
getAllFile(file);
}
/*
* 定义一个方法 参数传递file类型的目录
* 方法中对目录进行遍历
*/
public static void getAllFile(File dir) {
File[] files = dir.listFiles((File d,String name) -> {
//过滤规则 pathname是文件夹或是.java结尾的文件返回true
return new File(dir,name).isDirectory() || name.toLowerCase().endsWith(".md");
});
for (File f : files) {
if(f.isDirectory()){//对遍历得到的file文件f进行判断 判断是否是文件夹
getAllFile(f);//f是一个文件夹 则继续遍历这个文件夹 我们发现 getAllFile方法就是传递文件夹 遍历文件夹的方法 所以直接调用getAllFile方法即可:递归 自己调用自己
} else{
System.out.println(f);//f是一个文件 直接打印即可
}
}
}
}
IO流
一、内存:临时存储
二、磁盘:永久存储
- i:input输入(读取)把磁盘中的数据读取到内存中使用
- o:output输出(写入)输出:把内存中的数据写入到磁盘中保存
- 流:数据(字符 字节) 1个字符=2个字节 1个字节=8个二进制位
三、IO流最顶层的父类:
输入流 | 输出流 | |
---|---|---|
字节流 | 字节输入流InputStream | 字节输出流OutputStream |
字符流 | 字符输入流Beader | 字符输出流Writer |
四、java.io.OutputStream
:字节输出流 此抽象类是表示输出字节流的所有类的超类,
- 其中定义了一些子类共性的成员方法:
(1)public void close()
:关闭此输出流并释放与此流相关联的任何系统资源
(2)public void flush()
:刷新此输出流并强制任何缓冲的输出字节被写出
(3)public void write(byte[] b)
:将b.length
字节从指定的字节数组写入此输出流
(4)public void write(byte[] b,int off,int len)
:从指定的字节数组写入len
字节 从偏移量off
开始输出到此输出流
(5)public abstract void write(int b)
:将指定的字节输出流 java.io.FileOutputStream extends OutputStream
(1)FileOutputStream
:文件字节输出流
(2)作用:把内存中的数据写入到硬盘的文件中
(3)构造方法:
FileOutputStream(String name)
:创建一个向具有指定名称的文件中写入数据的输出文件流
FileOutputStream(File file)
:创建一个向指定file对象表示的文件中写入数据的文件输出流
参数:写入数据的目的
String name
:目的地是一个文件的路径File file
:目的地是一个文件
(4)构造方法的作用:
- 创建一个
FileOutputStream
对象 - 会根据构造方法中传递的文件/文件路径 创建一个空的文件
- 会把
FileOutputStream
对象指向创建好的文件
五、数据由内存写入硬盘的原理:java程序-》JVM(java虚拟机)-》os(操作系统)-》os调用写数据的方法-》把数据写入到文件中
六、字节输出流的使用步骤:
- 创建一个
FileOutputStream
对象 构造方法中传递写入数据的目的地 - 调用
FileOutputStream
对象中的方法write 把数据写入到文件中 - 释放资源(流的使用会占用一定的内存 使用完毕要把内存清空 提高程序的效率)
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class IOStream {
public static void main(String[] args) throws IOException {
//1.创建一个FileOutputStream对象 构造方法中传递写入数据的目的地
FileOutputStream fos = new FileOutputStream("D:\\JAVA\\source\\Day20\\src\\a.txt");
//2.调用FileOutputStream对象中的方法write 把数据写入到文件中
//public abstract void write(int b):将指定的字节输出流
fos.write(97);
//3.释放资源(流的使用会占用一定的内存 使用完毕要把内存清空 提高程序的效率)
fos.close();
}
}
字节输入流
一、java.io.InputStream
:字节输入流。此抽象类是表示字节输入流的所有类的超类二、定义了所有子类共性的方法:
int read()
:从输入流中读取数据的下一个字节int read(byte[] b)
:从输入流中读取一定数量的字节 并将其存储在缓冲区数组b中void close()
:关闭此输入流并释放与该流关联的所有系统资源
三、java.io.FileInputStream extends InputStream
FileInputStream
:文件字节输入流- 作用:把硬盘文件中的数据读取到内存中使用
四、构造方法:
FileInputStream(String name)
FileInputStream(File file)
参数:读取文件的数据源
- String name:文件的路径
- File file:文件
五、构造方法的作用:
- 会创建一个
FileInputStream
对象 - 会把
FileInputStream
对象指定构造方法中要读取的文件
六、读取数据的原理:java程序-》JVM-》os-》os读取数据的方法-》读取文件
七、字节输入流的使用步骤:
- 创建
FileInputStream
对象 构造方法中绑定要读取的数据源 - 使用
FileInputStream
对象中的方法read
读取文件 - 释放资源
import java.io.FileInputStream;
import java.io.IOException;
public class InputStream {
public static void main(String[] args) throws IOException {
// * 1.创建FileInputStream对象 构造方法中绑定要读取的数据源
FileInputStream fis = new FileInputStream("D:\\JAVA\\source\\Day20\\src\\b.txt");
// * 2.使用FileInputStream对象中的方法read 读取文件
// * int read():读取文件中的一个字节并返回 读取到文件的末尾返回-1
// int len = fis.read();//97
// System.out.println(len);
// len = fis.read();
// System.out.println(len);//每读取一次指针向后移一位 所以每写一次代码就是往后读一位 读完了返回-1
// len = fis.read();
// System.out.println(len);
// len = fis.read();
// System.out.println(len);
// len = fis.read();
// System.out.println(len);
// len = fis.read();
// System.out.println(len);
// len = fis.read();
// System.out.println(len);
// len = fis.read();
// System.out.println(len);
// len = fis.read();
// System.out.println(len);
// len = fis.read();
// System.out.println(len);
// len = fis.read();
// System.out.println(len);
// len = fis.read();
// System.out.println(len);
// len = fis.read();
// System.out.println(len);
// len = fis.read();
// System.out.println(len);
// len = fis.read();
// System.out.println(len);//-1
//
/*
* 发现以上读取文件是一个重复的过程 所以可以使用循环优化
* 不知道文件中有多少字节 使用while循环 while循环结束条件:读取到-1时结束
* 布尔表达式(len = fis.read()) != -1的含义:
* 1.fis.read():读取一个字节
* 2.len = fis.read():把读取到的字节赋值给变量len
* 3.(len = fis.read()) != -1:判断变量len是否不等于-1
*/
int len = 0;//记录读取到的字节
while ((len = fis.read()) != -1) {
System.out.println(len);
}
fis.close();
}
}
字节输入流一次读取多个字节的方法
一、int read(byte[] b)
:从输出流中读取一定数量的字节 并将其存储在缓冲区数组b
中
二、明确两件事:
- 方法的参数
byte[]
的作用:缓冲作用 存储每次读取到的多个字节的个数 提高了读取效率 数组的长度一般定义为1024(1kb)
或1024
的整数倍 - 方法的返回值
int
是什么:每次读取的有效字节个数
三、当使用字节流读取中文字符时 可能不会显示完整的字符 因为一个中文字符可能占用多个字节存储
四、一个中文 在gbk
编码下占用两个字节 在utf-8
编码下占用三个字节
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Arrays;
public class InputStreamRead {
public static void main(String[] args) throws IOException {
// * 1.创建FileInputStream对象 构造方法中绑定要读取的数据源
FileInputStream fis = new FileInputStream("D:\\JAVA\\source\\Day20\\src\\b.txt");
//2.使用FileInputStream对象中的方法read 读取文件
// * int read(byte[] b):从输出流中读取一定数量的字节 并将其存储在缓冲区数组b中
// byte[] bytes = new byte[2];
// int len = fis.read(bytes);
// System.out.println(len);//2 每次读取的字节数的个数
// /*
// * String类的构造方法:
// * String(byte[] bytes):把字节数组转换为字符串
// * String(byte[] bytes,int offset,int length):把字节数组的一部分转化为字符串 offset:数组的开始索引 length:转换的字节个数
// */
// //System.out.println(Arrays.toString(bytes));//[49, 48]
// System.out.println(new String(bytes));//10
//
// len = fis.read(bytes);
// System.out.println(len);//2 每次读取的字节数的个数
// System.out.println(new String(bytes));//0A
//
// len = fis.read(bytes);
// System.out.println(len);//2 每次读取的字节数的个数
// System.out.println(new String(bytes));//BC
//
// len = fis.read(bytes);
// System.out.println(len);//2 每次读取的字节数的个数
// System.out.println(new String(bytes));//DE
//
// len = fis.read(bytes);
// System.out.println(len);//2 每次读取的字节数的个数
// System.out.println(new String(bytes));//BC
//
// len = fis.read(bytes);
// System.out.println(len);//2 每次读取的字节数的个数
// System.out.println(new String(bytes));//你
//
// len = fis.read(bytes);
// System.out.println(len);//2 每次读取的字节数的个数
// System.out.println(new String(bytes));//好
//
// len = fis.read(bytes);
// System.out.println(len);//-1
// System.out.println(new String(bytes));//好
/*
* 发现以上读取是一个重复的过程 可以使用循环优化
* 不知道文件中有多少字节 所以使用while循环 while循环结束的条件:读取到-1结束
*/
byte[] bytes = new byte[1024];//存储读取到的多个字节
int len = 0;//记录每次读取的有效字节个数
while ((len = fis.read(bytes)) != -1) {
//System.out.println(new String(bytes));//因为D:\\JAVA\\source\\Day20\\src\\b.txt文件中的内容没有1024个字节
//这么多 所以输出打印的内容会有很多空格 为了改进 我们可以使用String(byte[] bytes,int offset,int length):把字节数组的一部分转化为字符串
System.out.println(new String(bytes,0,len));
}
fis.close();//释放资源
}
}
一次写多个字节的方法
一、public void write(byte[] b)
:将b.length
字节从指定的字节数组写入此输出流
二、public void write(byte[] b,int off,int len)
:从指定的字节数组写入len
字节 从偏移量off
开始输出到此输出流
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Arrays;
public class OutputStream {
public static void main(String[] args) throws IOException {
//1.创建一个FileOutputStream对象 构造方法中传递写入数据的目的地
FileOutputStream fos = new FileOutputStream(new File("D:\\JAVA\\source\\Day20\\src\\b.txt"));
//2.调用FileOutputStream对象中的方法write 把数据写入到文件中
//假设要求在文件中显示100
fos.write(49);
fos.write(48);
fos.write(48);
/*
* public void write(byte[] b,int off,int len):从指定的字节数组写入len字节 从偏移量off开始输出到此输出流
* 一次写多个字节
* 如果写的第一个字节是整数(0-127) 那么显示的时候会查询ASCII表
* 如果写的第一个字节是负数 那第一个字节会和第二个字节 第三个字节和第四个字节……每两个字节组成一个中文显示 查询系统默认码表GBK 如果有一个单的 就查询ASCII表显示
*/
byte[] bytes = {65,66,67,68,69};//100ABCDE
//byte[] bytes = {-65,-66,-67,68,69};//100烤紻E
fos.write(bytes);
/*
* public void write(byte[] b,int off,int len):从指定的字节数组写入len字节 从偏移量off开始输出到此输出流
* int off:数组的开始索引
* int len:写几个字节
*/
fos.write(bytes,1,2);//100ABCDEBC
/*
* 写入字符的方法:可以使用String类中的方法把字符串转换为字节数组
* byte[] getBytes():把字符串转换为字节数组
*/
byte[] bytes2 = "你好".getBytes();
System.out.println(Arrays.toString(bytes2));//[-60, -29, -70, -61]
fos.write(bytes2);//100ABCDEBC你好
//3.释放资源(流的使用会占用一定的内存 使用完毕要把内存清空 提高程序的效率)
fos.close();
}
}
追加写/续写字节
一、追加写/续写:使用两个参数的构造方法:
FileOutputStream(String name,boolean append)
:创建一个向具有指定name
的文件中写入数据的输出文件流FileOutputStream(File file,boolean append)
:创建一个向指向file
对象表示的文件中写入数据的文件输出流
参数:
String name
,File file
:写入数据的目的地boolean append
:追加写开关
true
:创建对象不会覆盖源文件 继续在文件的末尾追加写数据
false
:创建一个新文件 覆盖源文件
二、如何换行:写换行符号
Windows:\r\n
linux:/n
mac:/r
import java.io.FileOutputStream;
import java.io.IOException;
public class OutputStreamWrite {
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream("D:\\JAVA\\source\\Day20\\src\\c.txt",true);
fos.write("你好".getBytes());//每点击一次运行 D:\\JAVA\\source\\Day20\\src\\c.txt文件就会写一次你好
fos.write("\r\n".getBytes());//每点击一次运行 D:\\JAVA\\source\\Day20\\src\\c.txt文件就会换行写一次你好
fos.close();
}
}
字符输入流
一、java.io.Reader:字符输入流 是字符输入流的最顶层的父类 定义了一些共性的成员方法 是一个抽象类
二、共性的成员方法:
int read()
:读取单个字符并返回int read(char[] cbuf)
:一次读取多个字符 将字符读入数组void close()
:关闭该流并释放与之关联的所有资源
三、java.io.FileReader extends InputStreamReader extends Reader
FileReader
:文件字符输入流- 作用:把硬盘文件中的数据以字符的方式读取到内存中
四、构造方法:
FileReader(String fileName)
FileReader(File file)
参数:读取文件的数据源
String fileName
:文件的路径File file
:一个文件
五、FileReader
构造方法的作用:
- 创建一个
FileReader
对象 - 会把
FileReader
对象指向要读取的文件
六、字符输入流的使用步骤:
- 创建
FileReader
对象 构造方法中绑定要读取的数据源 - 使用
FileReader
对象中的方法read
读取文件 - 释放资源
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
public class Reader {
public static void main(String[] args) throws IOException {
// * 1.创建FileReader对象 构造方法中绑定要读取的数据源
FileReader fr = new FileReader("D:\\JAVA\\source\\Day20\\src\\b.txt");
// * 2.使用FileReader对象中的方法read读取文件
// * int read():读取单个字符并返回
// int len = 0;
// while ((len = fr.read()) != -1) {
// System.out.println((char)len);
// }
//为演示第二种方法 将上述代码注释
// * int read(char[] cbuf):一次读取多个字符 将字符读入数组
char[] cs = new char[1024];//存储读取到的多个字符
int len = 0;//记录的是每次读取的有效字符个数
while ((len = fr.read(cs)) != -1) {
/*
* String类的构造方法:
* String(char[] value):把字符数组转换为字符串
* String(char[] value,int offset,int count):把字符数组的一部分转换为字符串 offset数组的开始索引 count转换的个数
*/
System.out.println(new String(cs,0,len));
}
// * 3.释放资源
fr.close();
}
}
字符输出流
一、java.io.Writer
:字符输出流 是所有字符输出流的最顶层的父类 是一个抽象类
二、共性的成员方法:
void write(int c)
:写入单个字符void write(char[] cbuf)
:写入字符数组abstract void write(char[] cbuf,int off,int len)
:写入字符数组的某一部分off
数组的开始索引len
写的字符个数void write(String str)
:写入字符串void write(String str,int off,int len)
:写入字符串的某一部分off
字符串的开始索引len
写的字符个数void flush()
:刷新该流的缓冲void close()
:关闭此流 但要先刷新他
三、java.io.FileWriter extends OutputStreamWriter extends Writer
FileWriter
:文件字符输出流- 作用:把内存中字符数据写入到文件中
四、构造方法:
FileWriter(File file)
:根据给定的File对象构造一个FileWriter
对象FileWriter(String fileName)
:根据给定的文件名构造一个FileWriter
对象
参数:写入数据的目的地
- File file:是一个文件
- String fileName:文件的路径
五、构造方法的作用:
- 会创建一个
FileWriter
对象 - 会根据构造方法中传递的文件的路径 创建文件
- 会把
FileWriter
对象指向创建好的文件
六、字符输出流的使用步骤:
- 创建一个
FileWriter
对象 构造方法中绑定要写入数据的目的地 - 使用
FileWriter
中的方法write
把数据写入到内存缓冲区中(字符转换为字节的过程) - 使用
FileWriter
中的方法flush
把内存缓冲区中的数据刷新到文件中 - 释放资源(会先把内存缓冲区中的数据刷新到文件中)
七、flush
方法和close
方法的区别:
flush
:刷新缓冲区 流对象可以继续使用close
:先刷新缓冲区 然后通知系统释放资源 流对象不可以再被使用了
import java.io.FileWriter;
import java.io.IOException;
public class Writer {
public static void main(String[] args) throws IOException {
// * 1.创建一个FileWriter对象 构造方法中绑定要写入数据的目的地
FileWriter fw = new FileWriter("D:\\JAVA\\source\\Day20\\src\\c.txt");
// * 2.使用FileWriter中的方法write 把数据写入到内存缓冲区中(字符转换为字节的过程)
// * void write(int c):写入单个字符
fw.write(97);
// * 3.使用FileWriter中的方法flush 把内存缓冲区中的数据刷新到文件中
// * void flush():刷新该流的缓冲
//fw.flush();//可以不写这条语句 写fw.close();也会先把内存缓冲区中的数据刷新到文件中
// * void write(char[] cbuf):写入字符数组
char[] cs = {'a','b','c','d','e'};
fw.write(cs);
// * abstract void write(char[] cbuf,int off,int len):写入字符数组的某一部分 off数组的开始索引 len写的字符个数
fw.write(cs,1,3);
// * void write(String str):写入字符串
fw.write("传智播客");
// * void write(String str,int off,int len):写入字符串的某一部分 off字符串的开始索引 len写的字符个数
fw.write("黑马程序员",2,3);
// * 4.释放资源(会先把内存缓冲区中的数据刷新到文件中)
fw.close();
}
}
追加续写字符
一、续写:追加写:使用两个参数的构造方法
FileWriter(String fileName,boolean append)
FileWriter(File file,boolean append)
参数:
String fileName,boolean append
:写入数据的目的地的File file,boolean append
:续写开关
true
:不会创建新的文件覆盖源文件 可以续写
false
:创建新的文件覆盖源文件
二、换行:使用换行符号
Windows:\r\n
linux:/n
mac:/r
import java.io.FileWriter;
import java.io.IOException;
public class XuXieAndHuanHang {
public static void main(String[] args) throws IOException {
FileWriter fw =new FileWriter("D:\\JAVA\\source\\Day20\\src\\c.txt",true);
for (int i = 0; i < 10; i++) {
fw.write("HelloWorld" + i + "\r\n");
}
fw.close();
}
}
文件复制练习:一读一写
一、明确:
- 数据源:
E:\正片\DSC_0087.jpg
- 数据的目的地:
D:\JAVA\source\Day20\src
二、文件复制步骤:
- 创建一个字节输入流对象 构造方法中绑定要读取的数据源
- 创建一个字节输出流对象 构造方法中绑定要写入的目的地
- 使用字节输入流对象中的方法
read
读取文件 - 使用字节输出流中的方法
write
把读取到的字节写入到目的地的文件中 - 释放资源
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class CopyFile {
public static void main(String[] args) throws IOException {
// * 1.创建一个字节输入流对象 构造方法中绑定要读取的数据源
FileInputStream fis = new FileInputStream("E:\\正片\\DSC_0087.jpg");
// * 2.创建一个字节输出流对象 构造方法中绑定要写入的目的地
FileOutputStream fos = new FileOutputStream("C:\\");
//一次读取一个字节 写入一个字节的方式
// * 3.使用字节输入流对象中的方法read读取文件
// int len = 0;
// while ((len = fis.read()) != -1) {
// // * 4.使用字节输出流中的方法write 把读取到的字节写入到目的地的文件中
// fos.write(len);
// }
//方法二:使用数组缓冲读取多个字节 写入多个字节
byte[] bytes = new byte[1024];
// * 3.使用字节输入流对象中的方法read读取文件
int len = 0;//每次读取的有效字节个数
while ((len = fis.read(bytes)) != -1) {
// * 4.使用字节输出流中的方法write 把读取到的字节写入到目的地的文件中
fos.write(bytes,0,len);
}
// * 5.释放资源(先关闭写的流 在关闭读的流 因为写完了肯定读完了 读完了不一定写完了)
fos.close();
fis.close();
}
}
异常处理
一、在JDK1.7之前使用try
catch
finally
处理流中的异常
二、格式:
try{
可是会产生异常的代码
}catch(异常类变量 变量名){
异常的处理逻辑
}finally{
一定会执行的代码
资源释放
}
import java.io.FileWriter;
import java.io.IOException;
public class TryCatch {
public static void main(String[] args) {
//提高变量fw的作用域 让finally可以使用
//变量在定义时 可以没有值 但是使用的时候必须有值
//fw =new FileWriter("D:\\JAVA\\source\\Day20\\src\\c.txt",true);如果执行失败 fw没有值 fw.close会报错
FileWriter fw = null;
try {
//可能会产生异常的代码
fw =new FileWriter("D:\\JAVA\\source\\Day20\\src\\c.txt",true);
for (int i = 0; i < 10; i++) {
fw.write("HelloWorld" + i + "\r\n");
}
} catch (Exception e) {
//异常的处理逻辑
System.out.println(e);
}finally {
//一定会执行的代码
//如果创建对象失败了 fw的默认值是Null null是不能调用方法的 会抛出空指针异常 需要增加一个判断 不是null再把资源释放
if (fw != null) {
try {
fw.close();//fw.close方法声明抛出了IOException异常对象 所以我们就得处理这个异常对象 要么try catch 要么throws
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
jdk7新特性
一、在try
的后边可以增加一个()
,在括号中可以定义流对象,那么这个流对象的作用域就在try
中有效
二、try
中的代码执行完毕 会自动把流对象释放 不用写finally
三、格式:
try(定义流对象;定义流对象...){
可能会产生异常的代码
}catch(异常类变量 变量名){
异常的处理逻辑
}
import java.io.FileWriter;
public class JDK7 {
public static void main(String[] args) {
try(FileWriter fw =new FileWriter("D:\\JAVA\\source\\Day20\\src\\d.txt",true);)
{
//可能会产生异常的代码
for (int i = 0; i < 10; i++) {
fw.write("HelloWorld" + i + "\r\n");
}
} catch (Exception e) {
//异常的处理逻辑
System.out.println(e);
}
}
}
JDK9新特性
一、try
的前面可以定义流对象 try
后面的()
中可以直接引入流对象的名称(变量名)
二、在try
代码执行完毕之后 流对象也可以释放掉 不用写finally
三、格式:
A a = new A();
B b = new B();
try(a,b){
可能会出现异常的代码
}catch(异常类变量 变量名){
异常的处理逻辑
}
import java.io.FileWriter;
public class JDK9 {
public static void main(String[] args) {
FileWriter fw =new FileWriter("D:\\JAVA\\source\\Day20\\src\\d.txt",true);
try(try)//我这是JDK8 不支持这个特性
{
//可能会产生异常的代码
for (int i = 0; i < 10; i++) {
fw.write("HelloWorld" + i + "\r\n");
}
} catch (Exception e) {
//异常的处理逻辑
System.out.println(e);
}
}
}
java.util.Properties
一、java.util.Properties
集合 extends Hashtable<k,v> implements Map<k,v>
二、Properties
类表示了一个持久的属性集 Properties
可保存在流中或从流中加载
三、Properties
集合是一个唯一和IO
流相结合的集合
四、可以使用Properties
集合中的方法store
把集合中的临时数据持久化写入到硬盘中存储
五、可以使用Properties
集合中的方法load
把硬盘中保存的文件(键值对) 读取到集合中使用
六、属性列表中每个键及其对应值都是一个字符串
七、Properties
集合是一个双列集合 key
和value
默认都是字符串
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Properties;
import java.util.Set;
public class ProperttiesClass {
public static void main(String[] args) throws IOException {
show01();
show02();
show03();
}
/*
* 可以使用Properties集合中的方法load 把硬盘中保存的文件(键值对) 读取到集合中使用
* void load(InputStream inStream)
* void load(Reader reader)
* 参数:
* InputStream inStream:字节输入流 不能读取含有中文的键值对
* Reader reader:字符输入流 能读取含有中文的键值对
* 使用步骤:
* 1.创建Properties集合对象
* 2.使用Properties集合对象中的方法load读取保存键值对的文件
* 3.遍历Properties集合
* 【注】:
* 1.存储键值对的文件中 键与值默认的连接符号可以使用= 空格 和其他符号
* 2.存储键值对的文件中 可以使用#进行注释 被注释的键值对不会再被读取
* 3.存储键值对的文件中 键与值默认都是字符串 不用再加引号
*/
private static void show03() throws IOException {
// * 1.创建Properties集合对象
Properties properties = new Properties();
// * 2.使用Properties集合对象中的方法load读取保存键值对的文件
properties.load(new FileReader("D:\\JAVA\\source\\Day20\\src\\pro.txt"));
// * 3.遍历Properties集合
Set<String> set = properties.stringPropertyNames();
for (String key : set) {
String valueString = properties.getProperty(key);
System.out.println(key + "=" + valueString);//在文档中 在迪丽热巴前面加上了# 读取文件的时候 就不会输出打印迪丽热巴 我不知道为啥还是会显示
}
}
/*
* 可以使用Properties集合中的方法store 把集合中的临时数据 持久化写入到硬盘中存储
* void store(OutputStream out,String comments)
* void store(Writer writer,String comments)
* 参数:
* OutputStream out:字节输出流 不能写入中文
* Writer writer:字符输出流 可以写中文
* String comments:注释 用来解释说明保存的文件是做什么用的 不能使用中文 会产生乱码 默认是Unicode编码 一般使用" "空字符串
* 使用步骤:
* 1.创建Properties集合对象 添加数据
* 2.创建字节输出流/字符输出流对象 构造方法中绑定要输出的目的地
* 3.使用Properties集合中的方法store 把集合中的临时数据 持久化写入到硬盘中存储
* 4.释放资源
*/
private static void show02() throws IOException {
//创建Properties集合对象 添加数据
Properties properties = new Properties();
properties.setProperty("赵丽颖","168");
properties.setProperty("迪丽热巴","165");
properties.setProperty("古力娜扎","160");
// * 2.创建字节输出流/字符输出流对象 构造方法中绑定要输出的目的地
FileWriter fw = new FileWriter("D:\\JAVA\\source\\Day20\\src\\pro.txt");
// * 3.使用Properties集合中的方法store 把集合中的临时数据 持久化写入到硬盘中存储
properties.store(fw, "save data");
//释放资源
fw.close();
}
/*
* 使用Properties集合存储数据 遍历取出Properties集合中的数据
* Properties集合是一个双列集合 key和value默认都是字符串
* Properties集合有一些操作字符串的特有方法
* Object setProperty(String key,String value):调用Hashtable的方法put
* String getProperty(String key):通过key找到value值 此方法相当于Map集合中的get(key)方法
* Set<String> stringPropertyNames():返回此属性列表中的键值 其中该键及其对应值是字符串 此方法相当于Map集合中的keySet方法
*/
private static void show01() {
//创建Properties集合对象
Properties properties = new Properties();
//使用setProperties往集合中添加数据
properties.setProperty("赵丽颖","168");
properties.setProperty("迪丽热巴","165");
properties.setProperty("古力娜扎","160");
//使用stringPropertyNames把Properties集合中的键取出 存储到一个Set集合中
Set<String> set = properties.stringPropertyNames();
//遍历Set集合 取出Properties集合的每一个键
for (String key : set) {
//使用getProperty方法通过key获取value
String valueString = properties.getProperty(key);
System.out.println(key + "=" +valueString);
}
}
}