File类
java.io.File类 文件和目录路径名的抽象表示形式 Java把电脑中的文件和文件夹(目录)封装为了一个File类,我们可以使用File类对文件和文件夹进行操作 我们可以使用File类的方法 创建一个文件/文件夹 删除文件/文件夹 获取文件/文件夹 判断文件/文件夹是否存在 对文件夹进行遍历 获取文件的大小 File类是一个与系统无关的类,任何的操作系统都可以使用这个类中的方法 重点:file:文件 directory:文件夹/目录 path:路径
File类的静态成员变量
static String pathSeparator 与系统有关的路径分隔符,为了方便,它被表示为一个字符串 static char pathSeparatorChar 与系统有关的路径分割符 static String separator 与系统有关的默认名称分隔符,为了方便,它被表示为一个字符串 static char separatorChar 与系统有关的默认名称分隔符 注意:操作路径,不能写死了,应该以=="+File.separator+"==代替正反斜杠 windows:C:\develop\a\a.txt linux:C:/develop/a/a.txt “C:”+File.separator+“develop”+File.separator+“a”+File.separator+“a.txt”
public class Demo01File {
public static void main(String[] args) {
String pathSeparator = File.pathSeparator;
System.out.println(pathSeparator);
String separator = File.separator;
System.out.println(separator);
}
绝对路径和相对路径
路径: 绝对路径:完整的路径 以盘符(C、D)开始的路径 E:\soft\IDEA 相对路径:简化的路径 相对指的是相对于当前项目的根目录 如果使用当前项目的根目录,可以简化书写 E:\soft\IDEA–>IDEA(可以省略项目的根目录) 注意:1、路径是不区分大小写的 2、路径中的文件名称分隔符windows使用反斜杠,反斜杠是转义字符,两个反斜杠代表一个普通的反斜杠
File类的构造方法
File(String pathname)通过将给定路径名字字符串转换为抽象路径名来创建一个新File实例 File(String parent,String child)根据parent路径名字符串和child路径名字符创建一个新的File实例 File(File parent,String child)根据parent抽象路径和child路径名字符串创建也给新的File实例
public class Demo02File {
public static void main(String[] args) {
show01();
show02("c:\\","a.txt");
show03();
}
private static void show01() {
File f1 = new File("D:\\java\\ceshi\\day01\\a.txt");
System.out.println(f1);
File f2 = new File("D:\\java\\ceshi\\day01\\xiaohaha");
System.out.println(f2);
File f3 = new File("b.txt");
System.out.println(f3);
}
private static void show02(String parent,String child) {
File file = new File(parent,child);
System.out.println(file);
}
private static void show03() {
File parent = new File("c:\\");
File file = new File(parent,"hello.java");
System.out.println(file);
}
}
File类获取功能的方法
public String getAbsolutePath():返回File的绝对路径名字符串 public String getPath():将此file转换为路径名字符串 public String getName():返回由此file表示的文件或目录的名称 public long length():返回由此file表示的文件长度
public class Demo03File {
public static void main(String[] args) {
show01();
show02();
show03();
show04();
}
private static void show01() {
File f1 = new File("D:\\java\\ceshi\\day01\\a.txt");
String absolutePath1 = f1.getAbsolutePath();
System.out.println(absolutePath1);
File f2 = new File("a.txt");
String absolutePath2 = f2.getAbsolutePath();
System.out.println(absolutePath2);
}
private static void show02() {
File f1 = new File("D:\\java\\ceshi\\day01\\a.txt");
File f2 = new File("a.txt");
String path1 = f1.getPath();
System.out.println(path1);
String path2 = f2.getPath();
System.out.println(path2);
System.out.println(f1);
System.out.println(f1.toString());
}
private static void show03() {
File f1 = new File("D:\\java\\ceshi\\day01\\a.txt");
String name1 = f1.getName();
System.out.println(name1);
File f2 = new File("D:\\java\\ceshi\\day01");
String name2 = f2.getName();
System.out.println(name2);
}
private static void show04() {
File f1 = new File("D:\\java\\ceshi\\day01\\a.txt");
long l1 = f1.length();
System.out.println(l1);
}
}
File类判断功能的方法
public boolean exists():此File表示的文件夹或目录是否实际存在 public boolean isDirectory():此File表示的是否为目录 public boolean isFile():此File表示的是否为文件
public class Demo04File {
public static void main(String[] args) {
show01();
show02();
}
private static void show01() {
File f1 = new File("D:\\java\\ceshi\\day01\\a.txt");
boolean e1 = f1.exists();
System.out.println(e1);
File f2 = new File("D:\\java\\ceshi\\day01\\b.txt");
boolean e2 = f2.exists();
System.out.println(e2);
File f3 = new File("a.txt");
System.out.println(f3.exists());
}
private static void show02() {
File f1 = new File("D:\\java\\ceshi\\day01\\a.txt");
System.out.println(f1.isDirectory());
System.out.println(f1.isFile());
}
}
File类创建删除功能的方法
public boolean createNewFiLe():当且仅当具有该名称的文件尚不存在时,创建一个新的空文件。 public boolean delete():删除由此FiLe表示的文件或目录。 public boolean mkdir() :创建由此FiLe表示的目录。 public boolean mkdirs():创建由此FiLe表示的目录,包括任何必需但不存在的父目录。
public class Demo05File {
public static void main(String[] args) throws IOException {
show01();
show02();
show03();
}
private static void show01() throws IOException {
File f1 = new File("D:\\java\\ceshi\\day01\\1.txt");
boolean b1 = f1.createNewFile();
System.out.println(b1);
File f2 = new File("2.txt");
System.out.println(f2.createNewFile());
}
private static void show02() {
File f1 = new File("D:\\java\\ceshi\\day01\\aaa");
boolean b1 = f1.mkdir();
System.out.println(b1);
File f2 = new File("D:\\java\\ceshi\\day01\\aaa\\bbb\\ccc");
boolean b2 = f2.mkdirs();
System.out.println(b2);
}
private static void show03() {
File f1 = new File("2.txt");
System.out.println(f1.delete());
File f2 = new File("D:\\java\\ceshi\\day01\\aaa\\bbb");
System.out.println(f2.delete());
File f3 = new File("D:\\java\\ceshi\\day01\\aaa\\ddd");
System.out.println(f3.delete());
}
}
FiLe类遍历(文件夹)目录功能
public String[ ] list():返回一个String数组,表示该FiLe目录中的所有子文件或目录。 public File[ ] listFiLes():返回一个FiLe数组,表示该FiLe目录中的所有的子文件或目录。 注意: List方法和ListFiles方法遍历的是构造方法中给出的目录 如果构造方法中给出的目录的路径不存在,会抛出空指针异常 如果构造方法中给出的路径不是一个目录,也会抛出空指针异常
public class Demo06File {
public static void main(String[] args) {
show01();
show02();
}
private static void show01() {
File f1 = new File("D:\\java\\ceshi\\day01");
String[] arr = f1.list();
for (String fileName:arr){
System.out.println(fileName);
}
}
private static void show02() {
File f1 = new File("D:\\java\\ceshi\\day01");
File[] arr = f1.listFiles();
for (File fileName:arr){
System.out.println(fileName);
}
}
}
递归
概念
方法自己调用自己就是递归
递归的分类
递归分为两种,直接递归和间接递归 直接递归称为方法自身调用自己 间接递归可以A方法调用B方法,B方法调用C方法,C方法调用A方法
注意事项
递归一定要有条件限制,保证递归能够停止下来,否则会发生栈内存溢出 在递归中虽然有限定条件,但是递归次数不能太多,否则也会发生栈内存溢出 构造方法:禁止递归 递归的使用前提: 当调用方法的时候,方法的主体不变,每次调用方法的参数不同,可以使用递归
public class Demo01Recurison {
public static void main(String[] args) {
a();
b(1);
}
private static void a() {
System.out.println("a方法");
a();
}
private static void b(int i) {
System.out.println(i);
if (i==1000){
return;
}
b(++i);
}
public Demo01Recurison(){
}
}

使用递归计算1-n之间的和
public class Demo02Recurison {
public static void main(String[] args) {
int s = sum(3);
System.out.println(s);
}
public static int sum(int n){
if(n==1){
return 1;
}
return n + sum(n-1);
}
}

递归求阶乘
public class Demo03Recurison {
public static void main(String[] args) {
int h = cJ(5);
System.out.println(h);
}
public static int cJ(int n){
if (n==1){
return 1;
}
return n * cJ(n-1);
}
}
打印多级目录
public class Demo04Recurison {
public static void main(String[] args) {
File file = new File("D:\\java\\ceshi\\day01");
getAllFile(file);
}
public static void getAllFile(File dir){
System.out.println(dir);
File[] files = dir.listFiles();
for (File f : files) {
if (f.isDirectory()){
getAllFile(f);
}else {
System.out.println(f);
}
}
}
}
文件搜索
public class Demo05Recurison {
public static void main(String[] args) {
File file = new File("D:\\java\\ceshi\\day01");
getAllFile(file);
}
public static void getAllFile(File dir){
File[] files = dir.listFiles();
for (File f : files) {
if (f.isDirectory()){
getAllFile(f);
}else {
String s = f.toString();
s = s.toLowerCase(Locale.ROOT);
boolean b = s.endsWith(".java");
if (b){
System.out.println(f);
}
}
}
}
}
过滤器
使用过滤器来是实现 在File类中有两个和ListFiles重载的方法,方法的参数传递的就是过滤器 File[] listFiles(FileFilter filter) java.io.FileFilter接口:用于抽象路径名(File对象)的过滤器 作用:用来过滤文件(File对象) 抽象方法:用来过滤文件的方法 boolean accept(File pathname)测试指定抽象路径名是否应该包含在某个路径名列表中 参数:File pathname:使用ListFiles方法遍历目录,得到的每一个文件对象 File[] listFiles(FilenameFilter filter) java.io.FilenameFiles接口:实现此接口的类实例可用于过滤器文件名 作用:用于过滤文件名称 抽象方法:用来过滤文件的方法 boolean accept(File dir,String name)测试指定文件是否应该包含在某一文件列表中 参数:File dir:构造方法中传递的被遍历的目录 String name:使用ListFiles方法遍历目录,获取的每一个文件/文件夹名称 注意:两个过滤器接口是没有实现类的,需要我们自己写实现类,重写过滤器的方法accept,在方法中自己定义过滤的规则
使用第一种过滤器
主方法
public class Demo01Filter {
public static void main(String[] args) {
File file = new File("D:\\java\\ceshi\\day01");
getAllFile(file);
}
public static void getAllFile(File dir){
File[] files = dir.listFiles(new FileFiterImpl());
for (File f : files) {
if (f.isDirectory()){
getAllFile(f);
}else {
System.out.println(f);
}
}
}
}
使用匿名内部类
public class Demo02Filter {
public static void main(String[] args) {
File file = new File("D:\\java\\ceshi\\day01");
getAllFile(file);
}
public static void getAllFile(File dir){
File[] files = dir.listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
return pathname.isDirectory() || pathname.getName().toLowerCase(Locale.ROOT).endsWith(".java");
}
});
for (File f : files) {
if (f.isDirectory()){
getAllFile(f);
}else {
System.out.println(f);
}
}
}
}
重写accept方法
public class FileFiterImpl implements FileFilter {
@Override
public boolean accept(File pathname) {
if (pathname.isDirectory()){
return true;
}
return pathname.getName().toLowerCase(Locale.ROOT).endsWith(".java");
}
}
为什么要重写accept方法的原理
在accept方法中判断传递的文件是否以.java结尾 
使用第二种过滤器
public class Demo02Filter {
public static void main(String[] args) {
File file = new File("D:\\java\\ceshi\\day01");
getAllFile(file);
}
public static void getAllFile(File dir){
File[] files = dir.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return new File(dir,name).isDirectory() || name.toLowerCase(Locale.ROOT).endsWith(".java");
}
});
for (File f : files) {
if (f.isDirectory()){
getAllFile(f);
}else {
System.out.println(f);
}
}
}
}
使用Lambda表达式优化匿名内部类
public class Demo02Filter {
public static void main(String[] args) {
File file = new File("D:\\java\\ceshi\\day01");
getAllFile(file);
}
public static void getAllFile(File dir){
File[] files = dir.listFiles((File d, String name)->{
return new File(d,name).isDirectory() || name.toLowerCase(Locale.ROOT).endsWith(".java");
});
for (File f : files) {
if (f.isDirectory()){
getAllFile(f);
}else {
System.out.println(f);
}
}
}
}
IO流

IO字节输出流
切文件数据(文本、图片、视频等)在存储时,都是以二进制数字的形式保存,都一个一个的字节,那么传输样如此。所以,字节流可以传输任意文件数据。在操作流的时候,我们要时刻明确,无论使用什么样的流对象底层传输的始终为二进制数据。
java.io.OutputStream:此抽象类是表示输出字节流的所有类的超类 定义了一些子类共性的成员方法: public void close():关闭此输出流并释放与此流相关联的任何系统资源。 public void flush():刷新此输出流并强制任何缓冲的输出字节被写出。 public void write(byte[] b):将b.length字节从指定的字节数组写入此输出流。 public void write(byte[] b, int off, int len):从指定的字节数组写入len字节,从偏移 public abstract void write(int b):将指定的字节输出流。 java.io.FileOutPutStream extends OutputStream FileOutPutStream:文件字节输出流 作用:把内存中的数据写到硬盘的文件中 构造方法: FileOutputStream(String name)创建一个向具有指定名称的文件中写入数据的输出文件流 FileOutputStream(File file)创建一个向指定File对象表示的文件中写入数据的文件输出流 参数:写入数据的目的地 String name:目的地是一个文件的路径 File file:目的地是一个文件 构造方法的作用: 1、创建一个FileOutputStream对象 2、会根据构造方法中传递的文件/文件路径,创建一个空的文件 3、会把FileOutputStream对象指向创建好的文件
写入数据的原理(内存–>硬盘)
java程序–>JVM(java虚拟机)–>OS(操作系统)–>OS调用写数据的方法–>把数据写入到文件中
字节输出流的使用步骤(重点)
1、创建一个FileOutputStream对象,构造方法中传递写入数据的目的地 2、调用FileOutputStream对象中的方法write,把数据写入到文件中 3、释放资源(流的使用会占用一定的内存,使用完毕要把内存清空,提高程序效率)
public class Demo01OutputStream {
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream("D:\\java\\ceshi\\day01\\a.txt");
fos.write(97);
fos.close();
}
}
文件存储原理

字节输出流写多个字节的方法
一次写多个字节的方法 public void write(byte[] b):将b.length字节从指定的字节数组写入此输出流。 public void write(byte[] b, int off, int len):从指定的字节数组写入len字节,从偏移量off开始输出到此输出流。
public class Demo02OutputStream {
public static void main(String[] args) throws Exception {
FileOutputStream fos = new FileOutputStream(new File("D:\\java\\ceshi\\day01\\b.txt"));
fos.write(49);
fos.write(48);
fos.write(48);
byte[] btes = {65,66,67,68,69};
fos.write(btes);
fos.write(btes,1,2);
byte[] bytes = "你好".getBytes();
System.out.println(Arrays.toString(bytes));
fos.write(bytes);
fos.close();
}
}
字节输出流的续写和换行
上面追加在b.txt中的内容都是重新写了之后把之前的b.txt覆盖掉了 追加写/续写:使用俩个参数的构造方法 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
public class Demo03OutputStream {
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream("D:\\java\\ceshi\\day01\\b.txt",true);
for (int i = 0; i < 10; i++) {
fos.write("你好".getBytes(StandardCharsets.UTF_8));
fos.write("\r\n".getBytes());
}
fos.close();
}
}
IO字节输入流
字节输入流读取字节数据
java.io.InputStream:字节输入流: 此抽象类是表示字节输入流的所有类的超类。 定义了所有子类共性的方法: int read()从出入流中读取数据的下一个字节 int read()从输入流中读取一定数量的字节,并将其存储在缓冲区数组b中 void close()关闭此输入流并释放与该流有关联的所有系统资源 Java.io.FileInputStream extends InputStream FileInputStream:文件字节输入流 作用:把硬盘文件中的数据,读取到内存中使用 构造方法:FileInputStream(String name) FileInputStream(File file) 参数:读取文件的数据源 String name:文件的路径 File file:文件 作用:1、创建一个FileInputStream对象 2、会把FileInputStream对象指定构造方法中要读取的文件 读取数据的原理(硬盘–>内存) java程序–>JVM–>OS–>OS读取数据的方法–>读取文件 字节输入流的使用步骤(重点) 1、创建FileInputStream对象,构造方法中绑定要读取的数据源 2、使用FileInputStream对象中的方法read,读取文件 3、释放资源
public class Dmeo01InputStream {
public static void main(String[] args) throws Exception {
FileInputStream fis = new FileInputStream("D:\\java\\ceshi\\day01\\a.txt");
int len = 0;
while((len = fis.read()) != -1){
System.out.print((char) len);
}
fis.close();
}
}
字节输入流一次读取一个字节/多个字节的原理

字节输入流一次读取多个字节
字节输入流一次读取多个字节的方法 int read(byte[] b)从输入流中读取一定数量的字节,并将其存储在缓冲区数组b中 明确两件事情: 1、方法的参数byte[]的作用 起到缓冲作用,存储每次读取到的多个字节 数组的长度定义为1024的整数倍 2、方法的返回值int是什么 每次读取的有效字节个数 String类的构造方法 String(byte[] bytes):把字节数组转为字符串 Strng(byte[],int offset,int length)把字节数组的一部分转换为字符串 offset:数组的开始索引 length:转换的字节个数 使用数组就是一个缓冲原理
public class Dmeo02InputStream {
public static void main(String[] args) throws Exception {
FileInputStream fis = new FileInputStream("D:\\java\\ceshi\\day01\\b.txt");
byte[] bytes = new byte[2];
int len = fis.read(bytes);
System.out.println(len);
System.out.println(new String(bytes));
len = fis.read(bytes);
System.out.println(len);
System.out.println(new String(bytes));
len = fis.read(bytes);
System.out.println(len);
System.out.println(new String(bytes));
fis.close();
}
}
代码优化
public class Dmeo02InputStream {
public static void main(String[] args) throws Exception {
FileInputStream fis = new FileInputStream("D:\\java\\ceshi\\day01\\b.txt");
byte[] bytes = new byte[1024];
int len = 0;
while((len = fis.read(bytes)) != -1){
System.out.println(new String(bytes,0,len));
}
fis.close();
}
}
文件复制案例
package cn.itcast.day15.demo04;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
public class Demo01CopyFile {
public static void main(String[] args) throws Exception {
long s = System.currentTimeMillis();
FileInputStream fis = new FileInputStream("D:\\java\\ceshi\\day01\\a.txt");
FileOutputStream fos = new FileOutputStream(new File("D:\\java\\ceshi\\day01\\aaa\\b.txt"));
byte[] bytes = new byte[1024];
int len = 0;
while((len = fis.read(bytes)) != -1){
fos.write(bytes,0,len);
System.out.println(new String(bytes,0,len));
}
fos.close();
fis.close();
long e = System.currentTimeMillis();
System.out.println("复制共耗时:"+ (e-s) +"毫秒");
}
}
使用字节流读取中文的问题
使用字节流读取中文文件,GBK占2个字节,UTF-8占用3个字节,不能读取1/3个字符,所以就需要引入字符流
IO字符输入流
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构造方法的作用: 1.创建一个FileReader对象 2.会把FileReader对象指向要读取的文件 字符输入流的使用步骤: 1、创建FileReader对象,构造方法中绑定要读取的数据源 2、使用FileReader对象中的方法read读取文件 3、释放资源
public class Demo01Reader {
public static void main(String[] args) throws Exception {
FileReader fr = new FileReader("D:\\java\\ceshi\\day01\\b.txt");
char[] cs = new char[1024];
int len = 0;
while ((len = fr.read(cs))!=-1){
System.out.println(new String(cs,0,len));
}
fr.close();
}
}
IO字符输出流
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对象。 参数:写入数据的目的地 String fileName:文件的路径 File file:是一个文件 构造方法的作用: 1.会创建一个FileWriter对象 2.会根据构造方法中传递的文件/文件的路径,创建文件 3.会把FiLeWriter对象指向创建好的文件 字符输出流的使用步骤(重点); 1.创建FileWriter对象,构造方法中绑定要写入数据的目的地 2.使用FiLeWriter中的方法write,把数据写入到内存缓冲区中(字符转换为字节的过程) 3.使用FileWriter中的方法flush,把内存缓冲区中的数据,刷新到文件中 4.释放资源(会先把内存缓冲区中的数据刷新到文件中)
public class Demo01Writer {
public static void main(String[] args) throws IOException {
FileWriter fw = new FileWriter("D:\\java\\ceshi\\day01\\1.txt");
fw.write(98);
fw.flush();
fw.close();
}
}
flush方法和close方法的区别
flush:刷新缓冲区,流对象还可以继续使用 close:先刷新缓冲区,然后同志系统释放资源,流对象就不能在被使用了
字符输出流写数据的其他方法
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写的字符个数。
public class Demo02Writer {
public static void main(String[] args) throws IOException {
FileWriter fw = new FileWriter("D:\\java\\ceshi\\day01\\1.txt");
char[] cs = {'a','b','c','d','e','f'};
fw.write(cs);
fw.write(cs,1,3);
fw.write("小甜甜爱蹦蹦蹦");
fw.write("吸烟有害健康",0,2);
fw.close();
}
}
字符输出流的续写和换行
续写和换行 续写和换行:使用两个参数的构造方法 FileWriter(String filename,boolean append) FileWriter(File file,boolean append) 参数:String fileName,File file:写入数据的目的地 boolean append:续写开关 true:不创建新的文件覆盖源文件,可以续写 false:创建新的文件覆盖源文件 换行:windows:\r\n linux:/n mac:/r
public class Demo03Writer {
public static void main(String[] args) throws IOException {
FileWriter fw = new FileWriter("D:\\java\\ceshi\\day01\\1.txt",true);
for (int i = 0; i < 10; i++) {
fw.write("HelloWorld" + i + "\r\n");
}
fw.close();
}
}
Properties集合
java.util.Properties集合 extends Hashtable<k,v> implements Map<k,v> Properties类表示了一个持久的属性集,Properties可保存在流中或者从流中加载 Properties集合是一个唯一和IO流相结合的集合 可以使用Properties集合中的方法store,把集合中的临时数据,持久化写入到硬盘中存储 可以使用Properties集合中的方法load,把硬盘中保存的文件(键值对),读取到集合中使用 Properties集合属性列表中每个键值及其对应值都是一个字符串 Properties集合是一个双列集合,key和value默认都是字符串
使用Properties集合存储数据,遍历
使用Properties集合存储数据,遍历取出Properties集合中的数据 Properties集合属性列表中每个键值及其对应值都是一个字符串 Properties集合有一些操作字符串的特有方法 Object setProperty(String key,String value)调用Hashtable的方法put String getProperty(String key)用指定的键在此属性列表中搜索属性,即通过key找到value 此方法相当于Map集合中的get(key)方法 Set stringPropertyNames()返回此属性列表中的键集,其中该键及其对应值是字符串,此方法相当于Map集合中的keySet
private static void show01() {
Properties prop = new Properties();
prop.setProperty("Alice","155");
prop.setProperty("Bob","157");
prop.setProperty("Mallory","185");
Set<String> set = prop.stringPropertyNames();
for (String key : set) {
String value = prop.getProperty(key);
System.out.println(key+"="+value);
}
Properties集合中的方法store
可以使用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 prop = new Properties();
prop.setProperty("Alice","155");
prop.setProperty("Bob","157");
prop.setProperty("Mallory","185");
FileWriter fw = new FileWriter("D:\\java\\ceshi\\day01\\c.txt");
prop.store(fw,"save data");
fw.close();
}
private static void show03() throws IOException {
Properties prop = new Properties();
prop.setProperty("Alice","155");
prop.setProperty("Bob","157");
prop.setProperty("Mallory","185");
prop.store(new FileOutputStream("D:\\java\\ceshi\\day01\\d.txt"),"save data");
}
Properties集合中的方法load
可以使用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 show04() throws IOException {
Properties prop = new Properties();
FileInputStream fis = new FileInputStream("D:\\java\\ceshi\\day01\\d.txt");
prop.load(fis);
Set<String> set = prop.stringPropertyNames();
for (String key : set) {
String value = prop.getProperty(key);
System.out.println(key+"="+value);
}
}
缓冲流
缓冲流的原理

BufferedOutputStream字节缓冲输出流
java.io.BufferedOutputStream extends OutputStream BufferedOutputStream:字节缓冲输出流 继承自父类的共性方法 public void close():关闭此输出流并释放与此流相关联的任何系统资源。 public void flush():刷新此输出流并强制任何缓冲的输出字节被写出。 public void write(byte[] b):将b.length字节从指定的字节数组写入此输出流。 public void write(byte[] b, int off, int len):从指定的字节数组写入len字节,从偏移量off开始输出到此输出流。 public abstract void write(int b):将指定的字节输出流。 构造方法: BufferedOutputStream(OutputStream out) 创建一个新的缓冲输出流,以将数据写入指定的底层输出流 BufferedOutputStream(OutputStream out,int size)创建一个新的缓冲输出流,以将具有指定缓冲区大小的数据写入指定的底层输出流 参数:OutputStream out:字节输出流 我们可以传递FileOutputStream,缓冲流会给FileOutputStream增加一个缓冲区,提高FileOutputStream的写入效率 int size:指定缓冲流内部缓冲区的大小,不指定默认 使用步骤:1、创建FileOutputStream对象,构造方法中绑定要输出的目的地 2、创建BufferedOutputStream对象,构造方法中传递FileOutputStream对象,提高FileOutputStream对象效率 3、使用BufferedOutputStream对象中的方法writer,把数据写入到内部缓冲区中 4、使用BufferedOutputStream对象中的方法flush,把内部缓冲区中的数据,刷新到文件中 5、释放资源(会先调用flush方法刷新数据,第4步可以省略)
public class Demo02BufferedOutputStream {
public static void main(String[] args) throws Exception {
FileOutputStream fos = new FileOutputStream("D:\\java\\ceshi\\day01\\e.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos);
bos.write("甜是真的甜".getBytes(StandardCharsets.UTF_8));
bos.flush();
bos.close();
}
}
BufferedInputStream字节缓冲输入流
java.io.BufferedInputStream extends InputStream BufferedInputStream:字节缓冲流 继承自父类的成员方法: int read()从出入流中读取数据的下一个字节 int read()从输入流中读取一数量的字节,并将其存储在缓冲区数组b中 void close()关闭此输入流并释放与该流有关联的所有系统资源 构造方法:BufferedInputStream(InputStream in)创建一个BufferedInputStream并保存其参数,即输入流in,以便将来使用 BufferedInputStream(InputStream in,int size)创建具有指定缓冲区大小的BufferedInputStream并保存其参数,即输入流in,以便将来使用 参数:InputStream in:字节输入流 我们可以传递FileInputStream,缓冲区会给FileInputStream增加一个缓冲区,提高FileInputStream的读取效率 int size:指定缓冲流内部缓冲区的大小,不指定默认 使用步骤:1、创建一个FileInputStream对象,构造方法中绑定要读取的数据源 2、创建BufferedInputStream对象,构造方法中传递FileInputStream对象,提高FileInputStream对象的读取效率 3、使用BufferedInputStream对象中的read,读取文件 4、释放资源 5、关闭资源
public class Demo02BufferedInputStream {
public static void main(String[] args) throws Exception {
FileInputStream fis = new FileInputStream("D:\\java\\ceshi\\day01\\a.txt");
BufferedInputStream bis = new BufferedInputStream(fis);
byte[] bytes = new byte[1024];
int len = 0;
while((len = bis.read(bytes))!=-1){
System.out.println(new String(bytes,0,len));
}
bis.close();
}
}
BufferedWriter字符缓冲输出流
java.io.BufferedWriter extends Writer BufferedWriter:字符缓冲输出流 继承自父类的共性成员方法: 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() 关闭此流,但要先刷新它。 构造方法: 1、BufferedWriter(Writer out) 创建一个使用默认大小缓冲区的缓冲字符输出流 2、BufferedWriter(Writer out,int sz) 创建一个使用给定大小输出缓冲区的新缓冲区字符输出流 参数:Writer out:字符输出流 可以传递FileWriter,缓冲流会给FileWriter增加一个缓冲区,提高FileWriter的写入效率 int sz:指定缓冲区的大小,不写默认大小 特有成员方法:void newLine()写一个行分隔符。会根据不同的操作系统获取不同的行分隔符 使用步骤:1、创建字符缓冲输出流对象,构造方法中传递字符输出流 2、调用字符缓冲输出流中的方法writer,把数据写入到内存缓冲区中 3、调用字符缓冲输出流中的方法flush,把内存缓冲区中的数据,刷新到文件中 4、释放资源
public class Demo03BufferedWriter {
public static void main(String[] args) throws IOException {
BufferedWriter bw = new BufferedWriter(new FileWriter("D:\\java\\ceshi\\day01\\f.txt"));
for (int i = 0; i < 10; i++) {
bw.write("吸烟有害健康!");
bw.newLine();
}
bw.flush();
bw.close();
}
}
BufferedReader字符缓冲输入流
java.io.BufferedReader extends Reader 继承自父类的共性成员方法: int read()读取单个字符并返回 int read(char[] cbuf)一次读取多个字符,将字符读入数组。 void close()关闭该流并释放与之关联的所有资源。 构造方法: BufferedReader(Reader in)创建一个使用默认大小输入缓冲区的缓冲字符输入流 BufferedReader(Reader in,int sz)创建一个使用指定大小输入缓冲区的缓冲字符输入流 参数:Reader in:字符输入流 可以传递FileReader,缓冲流会给FileReader增加一个缓冲区,提高FileReader的读取效率 特有的成员方法: String readLine()读取一个文本行,读取一行数据 行的终止符号:通过下列字符之一即可认为某行已将终止:(’\n’)、回车(’\r’)或回车后直接跟着换行(\r\n) 返回值:包含该行内容的字符串,不包含任何终止符,如果已经到达流末尾,则返回null 使用步骤:1、创建字符缓冲输入流对象,构造方法中传递字符输入流 2、使用字符缓冲输入流对象中的方法read/readline读取文本 3、释放资源
public class Demo03BufferedReader {
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new FileReader("D:\\java\\ceshi\\day01\\f.txt"));
char[] cs = new char[1024];
int len = 0;
while((len = br.read(cs)) != -1 ){
System.out.println(new String(cs,0,len));
}
br.read();
br.close();
}
}
转换流
字符编码和字符集
编码:字符->字节 解码:字节->字符
OutputStreamWriter
java.io.OutputStreamWriter extends Writer OutputStreamWriter:字符流通向字节流的桥梁,可使用指定的charset将要写入流中的字符编码成字节 继承父类的共性方法: 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() 关闭此流,但要先刷新它。 构造方法: OutputStreamWriter(OutputStream out)创建使用默认字符编码的OutputStreamWriter OutputStreamWriter(OutputStream out,String charsetName)创建使用指定字符集的OutputStreamWriter 参数:OutputStream out:字节输出流,可以用来写转换之后的字节到文件中 String charsetName:指定的编码表名称,不区分大小写,可以是UTF-8/utf-8,不指定默认使用utf-8 使用步骤: 1、创建OutputStreamWriter对象,构造方法中传递字节输出流和指定的编码表名称 2、使用OutputStreamWriter对象中的方法writer,把字符转换为字节存储缓冲区中(编码) 3、使用OutputStreamWriter对象中的方法flush,把内存缓冲区中的字节刷新到文件中(使用字节流写字节的过程) 4、释放资源
public class Demo02OutputStreamWriter {
public static void main(String[] args) throws Exception {
writer_gbk();
}
private static void writer_utf_8() throws Exception {
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("D:\\java\\ceshi\\day01\\a.txt"),"utf-8");
osw.write("你好");
osw.flush();
osw.close();
}
private static void writer_gbk() throws Exception {
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("D:\\java\\ceshi\\day01\\a.txt"),"gbk");
osw.write("你好a");
osw.flush();
}
}
InputStreamReader
java.io.InputStreamReader extends Reader InputStreamReader:是字节流通向字符流的桥梁,它使用指定的charset,读取字节并将其解码为字符 继承自父类的共性成员方法: int read()读取单个字符并返回 int read(char[] cbuf)一次读取多个字符,将字符读入数组。 void close()关闭该流并释放与之关联的所有资源。 构造方法: 1、InputStreamReader(InputStream in)创建一个使用默认字符集的InputStreamReader 2、InputStreamReader(InputStream in,String charsetName)创建使用指定字符集的InputStreamReader 参数:InputStream in:字节输入流用来读取文件中保存的字节 String charsetName:指定的编码表名称,不区分大小写 使用步骤: 1、创建InputStreamReader对象,构造方法中传递字节输入流和指定的编码表名称 2、使用InputStreamReader对象中的方法read读取文件 3、释放资源 注意事项:构造方法中指定的编码表名称要和文件的编码相同,否则会发生乱码
public class Demo03InputStreamReader {
public static void main(String[] args) throws Exception {
writer_utf_8();
}
private static void writer_utf_8() throws Exception {
InputStreamReader isr = new InputStreamReader(new FileInputStream("D:\\java\\ceshi\\day01\\a.txt"),"gbk");
int len = 0;
while((len = isr.read())!=-1){
System.out.println((char) len);
}
isr.close();
}
}
序列化流
序列化和反序列化

ObjectOutputStream:对象的序列化流
java.io.ObjectOutputStream extends OutputStream ObjectOutputStream:对象的序列化流 作用:把对象以流的方式写入到文件中保存 构造方法:ObjectOutputStream(OutputStream out)创建写入指定OutputStream的ObjectOutputStream 参数:OutputStream out:字节输出流 特有的成员方法: void writeObject(Object obj)将指定的对象写入ObjectOutputStream 使用步骤: 1、创建一个ObjectOutputStream对象,构造方法中传递字节输出流 2、使用ObjectOutputStream对象中的方法writeObject,把对象写入到文件中 3、释放资源 序列化和反序列化的时候,会抛出NotSerializableException没有序列化异常 类通过实现java.io.Serializable 接口启用其序列化功能,未实现此接口的类将无法使其任何状态序列化或反序列化 Serializable接口也叫标记型接口 要进行序列化和反序列化的类必须实现Serializable接口,就会给类添加一个标记 当我们进行序列化和反序列化的时候,就会检测类上是否有这个标记 有:就可以序列化和反序列化 没有:就会抛出NotSerializableException异常
public class Demo01ObjectOutputStream {
public static void main(String[] args) throws Exception {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D:\\java\\ceshi\\day01\\Person.txt"));
oos.writeObject(new Person("哈哈哈",18));
oos.close();
}
}
public class Person implements Serializable {
private String name;
private int age;
public Person() {
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
InputStream:对象的反序列化流
java.io.ObjectInputStream extends InputStream InputStream:对象的反序列化流 作用:把文件中保存的对象,以流的方式读取出来使用 构造方法:ObjectInputStream(InputStream in) 创建从指定InputStream读取的ObjectInputStream 参数:InputStream in:字节输入流 特有的成员方法:Object readObject() 从ObjectInputStream读取对象 使用步骤: 1、创建ObjectInputStream对象,构造方法中传递字节输入流 2、使用ObjectInputStream对象中的方法readObject()读取保存对象的文件 3、释放资源 4、使用读取出来的文件(打印) readObject()方法声明抛出了ClassNotFoundException异常(class文件找不到异常) 当不存在对象的class文件时抛出此异常 反序列化的前提: 1、类必须实现Serializable 2、必须存在类对应的class文件
public class Demo02ObjectInputStream {
public static void main(String[] args) throws Exception {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("D:\\java\\ceshi\\day01\\Person.txt"));
Object o = ois.readObject();
ois.close();
System.out.println(o);
Person p = (Person) o;
System.out.println(p.getName()+p.getAge());
}
}
transient关键字_瞬态关键字
static关键字:静态关键字 静态优先于非静态加载到内存中(静态优先于对象进入到内存中) 被static修饰的成员变量不能被序列化的,序列化的都是对象 transient关键字:瞬态关键字 被transient修饰成员变量,不能被序列化 如果需要不被序列化,而且非静态就可用transient
InvalidClassException异常
例如:在Person中我们将age的权限改为public ,直接进行反序列化。因为更改了以后其class文件已经被更改,所以就会抛出一个InvalidClassException异常,因为序列号发生了冲突  自动生成serialVersionUID Preferences -> Inspections -> Serialization issues -> Serialization class without ‘serialVersionUID’ 打上勾 然后在类的名称上Alt+Enter就会自动生成serialVersionUID
import java.io.Serial;
import java.io.Serializable;
public class Person implements Serializable {
@Serial
private static final long serialVersionUID = -7696353887086844926L;
private String name;
private int age;
public Person() {
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
序列化集合案例
import java.io.*;
import java.util.ArrayList;
public class Demo01Test {
public static void main(String[] args) throws Exception {
ArrayList<Person> list = new ArrayList<>();
list.add(new Person("小甜甜",18));
list.add(new Person("武哈哈",23));
list.add(new Person("杨蛋蛋",22));
list.add(new Person("赵鱼鱼",22));
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D:\\java\\ceshi\\day01\\2.txt"));
oos.writeObject(list);
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("D:\\java\\ceshi\\day01\\2.txt"));
Object o = ois.readObject();
ArrayList<Person> list1 = (ArrayList<Person>) o;
for (Person p : list1) {
System.out.println(p);
}
oos.close();
ois.close();
}
}
打印流
java.io.PrintStream:打印流 PrintStream 为其他输出流添加了功能,使它们能方便打印各种数据值表示形式 PrintStream特点: 1、只负责数据的输出,不负责数据的读取 2、与其他输出流不同,PrintStream永远不会抛出IoException 3、有特有的方法,print,println void print(任意类型的值) void println(任意类型的值并换行) 构造方法: PrintStream(File file):输出的目的地是一个文件 PrintStream(OutputStream out):输出的目的地是一个字符输出流 PrintStream(String fileName):输出的目的地是一个文件路径 PrintStream extends OutputStream 继承自父类的共性方法 public void close():关闭此输出流并释放与此流相关联的任何系统资源。 public void flush():刷新此输出流并强制任何缓冲的输出字节被写出。 public void write(byte[] b):将b.length字节从指定的字节数组写入此输出流。 public void write(byte[] b, int off, int len):从指定的字节数组写入len字节,从偏移量off开始输出到此输出流。 public abstract void write(int b):将指定的字节输出流。 注意事项:如果使用继承自父类的writer方法写数据,那么查看数据的时候会查询编码表97->a 如果使用自己特有的方法print,println方法写数据,写的数据原样输出97->97
public class Demo01PrintStream {
public static void main(String[] args) throws Exception {
PrintStream ps = new PrintStream("D:\\java\\ceshi\\day01\\3.txt");
ps.write(97);
ps.println(97);
ps.close();
}
}
打印输出语句的目的地
可以改变输出语句的目的地(打印流的流向) 输出语句,默认在控制台输出 使用System类中setOut方法改变输出语句的目的地为参数传递的打印流的目的地 static void setOut(PrintStream out)重新分配标准输出流
public class Demo02PrintStream {
public static void main(String[] args) throws Exception {
System.out.println("这是在控制台输出的!");
PrintStream ps = new PrintStream("D:\\java\\ceshi\\day01\\4.txt");
System.setOut(ps);
System.out.println("这是在打印流的目的地中输出!");
ps.close();
}
}
|