学习笔记三、IO流
1、_File类
在java.io包下面
extends Object
implements Serializable Comparable
File:文件和目录路径名的抽象表示。
文件和目录是可以通过File封装成对象的。
对于File而言,其封装的并不是一个真正存在的文件,仅仅是一个路径名字而已,他是可以存在的,也可以不存在,将来时要通过具体的操作把这个路径通过具体操作把这个路径的内容转换为具体存在的。
构造方法:
File(String pathname):通过将给定的路径名字符串转化为抽象路径名,来创建新的File实例
File(String parent,String Child):从父路径名字符串和子路径字符串创建新的File实例。
File(File parent,String child):从父抽象,路径名和子路径名字符串创建新的File实例。
public static void main(String[] args) {//不是真正的文件,如果要指定文件的时候,就用下面的构造方法 File f1 = new File("D:\\java\\java.txt"); System.out.println(f1);//D:\java\java.txt,说明重写了tostring方法 File f2 = new File("D:\\java","java.txt"); System.out.println(f2); File f3 = new File("D:\\java"); File f4 = new File(f3,"java.txt"); System.out.println(f4); }
1.1File类的创建功能
boolean createNewFile():当具有该名称的文件不存在时,创建一个由改抽象路径名明明的新的空文件。
boolean mkdir():创建由此抽象路径名明明的目录
boolean mkdirs():创建由此抽象路径名命名的目录,包括任何必须但不存在的父目录
public static void main(String[] args) throws IOException { File f1 = new File("D:\\java\\java.txt"); System.out.println(f1.createNewFile());//如果文件不存在,就创建文件。如果文件存在就不创建文件,并返回false。 File f2 = new File("D:\\java\\zynew"); System.out.println(f2.mkdir());//如果目录不存在就创建目录,如果目录存在,就不创建目录,并返回false File f3 = new File("D:\\java\\zynew2\\zy"); System.out.println(f3.mkdirs());//自己补齐 }
1.2 File类判断和获取功能
boolean isDirectory():测试此抽象路径名表示的File是否为目录。
boolean isFile():测试此抽象路径名表示的File是否为文件
boolean exists():测试File是否存在
String getAbsolutePath():返回此抽象路径名的绝对路径名字符串
String getPath ():将此抽象路径名转换为路径名字字符串
String getName():返回此抽象名表示的目录中的文件和目录的名称
String[] list():返回此抽象路径名表示的目录中的文件和目录的名称字符串数组。
File[] listFiles():返回此抽象路径名表示的目录中的文件和目录的File对象数组。
public static void main(String[] args) throws IOException { File f1 = new File("idea_test\\src\\java.txt"); System.out.println(f1.isDirectory()); System.out.println(f1.isFile()); System.out.println(f1.exists()); System.out.println(f1.getAbsolutePath());//D:\java\a1\idea_test\src\java.txt System.out.println(f1.getPath());//idea_test\src\java.txt System.out.println(f1.getName());//java.txt System.out.println("----------"); File f2 = new File("D:\\java"); String[] str = f2.list(); for (String s : str){ System.out.println(s); } File[] filearry = f2.listFiles(); for (File f : filearry){ System.out.println(f); if (f.isDirectory()){ System.out.println(f.getName()); } }
false false false D:\java\a1\idea_test\src\java.txt idea_test\src\java.txt java.txt ---------- a1 ij jdk17 project D:\java\a1 a1 D:\java\ij ij D:\java\jdk17 jdk17 D:\java\project project Process finished with exit code 0
1.3 File类删除功能
public Boolean delete():删除此抽象路径名表示的文件或目录。
psvm{ File f1 = new File("E:\\java\\java.txt") sout(f1createNewFile()) }
绝对路径,相对路径
如果要删除的目录下有内容,不能直接删除。所以要先删除目录下的文件,再删除目录。
1.4 递归
概述:方法定义中调用方法本身的现象。
public static void main(String[] args) { System.out.println(f(6)); } public static int f(int n){ if(n==1||n==2){ return 1; }else { return f(n - 1) + f(n - 2); } }
要找到两个内容:
要找到递归出口
要与原问题较小的规模
递归求阶乘
递归出口:1!=1
递归规则:n!=n*(n-1)!
public static void main(String[] args) { System.out.println(f(6)); } public static int f(int n){ if(n==1){ return 1; }else { return n*f(n - 1); } }
遍历目录
public static void main(String[] args) { File f1 = new File("D:\\java\\project"); getallfilepath(f1); } public static void getallfilepath(File srcFile){ File[] filearr = srcFile.listFiles(); if(filearr!=null){ for (File f : filearr){ if(f.isDirectory()){ getallfilepath(f); }else{ System.out.println(f.getAbsolutePath()); } } } } }
2、字节流
2.1 IO流概述和分类
IO:输入/输出
流:对数据传输的总成,也就是说数据在设备键的传输叫做流,流的本质时数据传输。
IO流就是用来处理设备间数据传输问题的。
常见的应用:文件赋值;文件上传;文件下载
输入流:读数据
输出流:写数据
按照数据类型分:
字节流:不知道用啥流,就用字节流
字符流:如果用记事本打开,就用字符流,否则用字节流
2.2 字节流写数据
InputStream:这个抽象类是表示字节输入流的所有类的超类
OutputStream:资格抽象类是表示字节输出流的所有类的超类
子类名特点:用父类名作为后缀
构造方法:
FileOutputStream f1write = new FileOutputStream("D:\java\a1\idea_test\src\java1.txt");
FileOutputStream f1write = new FileOutputStream(File f);
public static void main(String[] args) throws IOException { FileOutputStream f1write = new FileOutputStream("D:\\java\\a1\\idea_test\\src\\java1.txt"); //做了1、调用系统功能创建文件,创建字节输出流对象,让字节输出流对象指向创建的文件。 f1write.write(97);//a f1write.write(57);//9 f1write.close();//关闭此文件输出流并释放与此流相关联的任何系统资源 }
字节流写数据的三种方式
1、write(int b):将指定的字节写入此文件输出流
2、write(byte[] b):将b.length字节从指定的字节数组写入此文件输出流
3、write(byte[] b,int pff ,int len):将len字节从指定的字节数组开始,从偏移量off开始写入此文件输出流
FileOutputStream f = new FileOutputStream("D:\\java\\a1\\idea_test\\src\\java1.txt"); // byte[] bys = {97,98,99,100,101}; byte[] bys = "123456789".getBytes(); // f.write(bys); f.write(bys,7,1);//8
字节流写数据如何实现换行呢?
\n或者\r
public static void main(String[] args) throws IOException { FileOutputStream f = new FileOutputStream("D:\\java\\a1\\idea_test\\src\\java1.txt"); for (int i= 0 ;i<6;i++){ byte[] bys = "hello".getBytes(); f.write(bys); f.write("\n".getBytes()); } f.close();
字节流如何追加写数据
第二个参数是true,就可以在末尾接着写了。
FileOutputStream f = new FileOutputStream("D:\\java\\a1\\idea_test\\src\\java1.txt",true);
2.3 字节流写数据加异常处理
FileOutputStream f = null; try { f = new FileOutputStream("D:\\java\\a1\\idea_test\\src\\java1.txt", true); for (int i = 0; i < 6; i++) { byte[] bys = "hello".getBytes(); f.write(bys); f.write("\n".getBytes()); } }catch (IOException e){ e.printStackTrace(); }finally{ if(f!=null){ try{ f.close(); }catch(IOException e){ e.printStackTrace(); } } }
finally :在一场处理时提供finally块来执行所有清楚操作,比如IO流中的释放资源
特点:被finally控制的语句一定会执行,除非JVM退出。
2.4 字节流一次读取一个字节的数据
需求:把文件f.txt中的内容读取出来再控制台输出。
FileInputStream:从文件系统中的文件获取输入字节
public static void main(String[] args) throws IOException { FileInputStream f = new FileInputStream("idea_test\\src\\java1.txt"); //读取数据 // int by = f.read(); // System.out.println(by); // System.out.println((char)by); // //第二次读取数据 // by = f.read(); // System.out.println(by); // System.out.println((char)by); //用循环改进 // while(by != -1){ System.out.println(by); // System.out.println((char)by); // by = f.read(); // } //优化 int by; while ((by=f.read())!=-1){ System.out.print((char)by); } //释放资源 f.close(); }
hello hello hello hello hello hello
2.5 复制文本文件
把文件中的内容读取出来,然后写入到另一个文件
public static void main(String[] args) throws IOException { FileInputStream fi = new FileInputStream("idea_test\\src\\java1.txt"); FileOutputStream fo = new FileOutputStream("idea_test\\src\\java.txt"); int by; while((by = fi.read())!=-1){ fo.write(by); } fi.close(); fo.close(); }
2.6 字节流一次读取一个字节数组数据
hello zy
public static void main(String[] args) throws IOException { FileInputStream fi = new FileInputStream("idea_test\\src\\java1.txt"); byte[] by = new byte[7]; int len = fi.read(by); // System.out.println(len); System.out.println(new String(by)+"====="); len = fi.read(by); System.out.println(len); System.out.println(new String(by,0,len)); fi.close(); }
hello z===== 2 y
因为输出为:hello后面还有\n算一个。
byte[] by = new byte[1024]; int len; while((len=fi.read(by))!=-1){ System.out.println(len); System.out.println(new String(by,0,len)); }
9 hello zy
2.7 复制图片
public static void main(String[] args) throws IOException { FileInputStream fi = new FileInputStream("1.png"); FileOutputStream fo =new FileOutputStream("idea_test\\src\\2.png"); byte[] by =new byte[1024]; int len; while((len=fi.read(by))!=-1){ fo.write(by,0,len); } fi.close(); fo.close(); }
3、字节缓冲流
BufferedOutputStreeam:通过设置这样的呼出流,应用程序可以向底层输出流写入字节,而不必为写入的每一个字节导致底层系统的调用。
BufferedOutputStreeam(OutputStreeam out)
BufferedItputStreeam:缓冲输入支持mark和reset方法的功能。创建BufferedInputStream将创建一个内部缓冲区数组。当从流中读取或者跳过字节的时候,内部缓冲区将根据需要从所包含的输入流中重新填充,一次很多字节。mark操作会记住输入流中的一个点,并且reset操作会导致从最近的mark操作读取的所有字节再从包含的输入流中取出新字节之前重新读取。
BufferedInputStreeam(InputStreeam in)
public static void main(String[] args) throws IOException { FileOutputStream fo = new FileOutputStream("idea_test\\src\\java.txt"); BufferedOutputStream bfo = new BufferedOutputStream(fo); bfo.write("hello\n".getBytes()); bfo.write("nihaome\n".getBytes()); bfo.close(); BufferedInputStream bfi = new BufferedInputStream(new FileInputStream("idea_test\\src\\java.txt")); // int by; // while((by= bfi.read())!=-1){ // System.out.print((char)by); // } //一次读取一个字节数组 byte[] bys = new byte[1024]; int len; while((len= bfi.read(bys))!=-1){ System.out.println(new String(bys,0,len)); } }
案例:复制视频
public static void main(String[] args) throws IOException { //记录开始时间 long startTime = System.currentTimeMillis(); //复制视频 method1(); //记录结束时间 long endTime = System.currentTimeMillis(); System.out.println("总耗时:"+(endTime-startTime)+"毫秒"); } //基本字节流一次 public static void method1() throws IOException {//总耗时:1936毫秒 FileInputStream fi = new FileInputStream("idea_test\\1.mp4"); FileOutputStream fo = new FileOutputStream("2.mp4"); int by; while((by= fi.read())!=-1){ fo.write(by); } fi.close(); fo.close(); } //基本字节流一次读写一个字节数组 public static void method2() throws IOException{//总耗时:4毫秒 FileInputStream fi = new FileInputStream("idea_test\\1.mp4"); FileOutputStream fo = new FileOutputStream("2.mp4"); byte[] bys = new byte[1024]; int len; while((len= fi.read(bys))!=-1){ fo.write(bys,0,len); } fi.close(); fo.close(); } } //字节缓冲流一次读写一个字节,总耗时:8毫秒 public static void method3() throws IOException{ BufferedInputStream bfi = new BufferedInputStream(new FileInputStream("idea_test\\1.mp4")); BufferedOutputStream bfo = new BufferedOutputStream(new FileOutputStream("2.mp4")); int by; while((by= bfi.read())!=-1){ bfo.write(by); } bfi.close(); bfo.close(); } //字节缓冲流一次读写一个字节数组总耗时:2毫秒 public static void method4() throws IOException{ BufferedInputStream bfi = new BufferedInputStream(new FileInputStream("idea_test\\1.mp4")); BufferedOutputStream bfo = new BufferedOutputStream(new FileOutputStream("2.mp4")); byte[] bys = new byte[1024]; int len; while((len= bfi.read(bys))!=-1){ bfo.write(bys,0,len); } bfi.close(); bfo.close(); } }
4、字符流
4.1为什么会出现字符流
一个汉字存储:
如果用GBK编码,占用2个字节
如果用UTF-8编码,占用3个字节
由于字节流操作中文不是特别方便,所以提供了字符流
字符流=字节流+编码表
用字节流复制文本文件的时候,文本文件也会有中文,但是没有问题,原因时最终底层操作会自动进行字节拼接中文,如何识别中文的呢?
汉字再存储的时候,无论使用哪种编码,第一个字节都是负数。
4.2编码表
计算机存储的信息都是二进制表示的。这个老早就学过了。不用多讲。
A-65
ASCll字符集,美国信息交换标准代码。
GB2312:简体中文码表
GBK:最常用的中文码表。完全兼容GB2312
GB18030:最新的中文码表
Unicode字符集:为表达任意语言的任意字符二设计,时业界的标准,也成为同意吗,标准玩过吗。
UTF-8:可以用来表示UNicode标准中任意字符,他是电子邮件、网页及其他存储火传送文字的应用中,有限采用的编码。互联网工程工作小组要求所有狐狸篮网协议都必须支持UTF-8编码,它使用1-4个字节为每个字符编码。
采用何种规则编码,就要采用何种规则解码,不然就会乱码。
4.3 字符串中的编码解码问题
编码:
byte[] getByte():使用平台默认字符集,将String编码为一系列字节,将结果存储到新的字节数组中
byte[] getByte(String charserName):使用指定字符集,将该String编码为一系列字节,将结果存储到新的字符数组中
解码:
String(byte[] bytes):字节数组---String,使用平台默认字符集
String(byte[] bytes,String charsetName):字符数组---构造新的String,使用指定字符集
4.4 字符流中的编码解码问题
字符流抽象基类:
Reader:字符输入流的抽象类
Writer:字符输出流的抽象类
InputStreamReader:是字节流到字符流的桥梁,它读取字节,并使用指定的编码将其解码为字符。它使用的字符集可以由名称指定,也可以被明确指定,或者可以接受平台的默认字符集。
OutputStreamWriter:是从字符流到字节流的桥梁,使用指定的编码写入的字符编码为字节。它使用的字符集可以由名称指定,也可以被明确指定,或者可以接受平台的默认字符集
构造方法:
OutputStreamWriter(OutputStream out):使用默认字符编码的
OutputStreamWriter(OutputStream out,String charsetName):使用命名字符集的
4.5 字符流写数据的5种方式
write(int c):写一个字符
write(char[] cbuf):写入一个数组
write (char[] cbuf,int off,int len):写入字符数组的一部分
write(String str):写一个字符串
write(String str,int off,int len):写入一个字符串的一部分
public static void main(String[] args) throws IOException { OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("idea_test\\src\\java.txt")); // osw.write(97);//写不进去还在缓冲区里面 // osw.flush();//刷新一下,数据就进去了 // char[] chs = {'a','b','c','d','e'}; // osw.write(chs); // osw.write(chs,1,3);//bcd // osw.write("abcdgt");//abcdgt osw.write("abcdefghizy",2,5);//cdefg osw.close();//coloce自带一个刷新 }
flush():刷新流,还可以继续写数据。
close():关闭流,释放数据,但是再关闭之前会先刷新流。一旦关闭,就不能再写数据了。
4.6 字符流读数据的两种方式
read():一次读一个字符数据
read(char[] cbuf):一次都一个字符数组
public class demo1 { public static void main(String[] args) throws IOException { InputStreamReader isr = new InputStreamReader(new FileInputStream("D:\\java\\a1\\idea_test\\src\\com\\zy8\\demo1.java")); char[] cha = new char[1024]; int len; while((len= isr.read(cha))!=-1){ System.out.print(new String(cha,0,len));//abcdefghizy } isr.close(); } }
4.7 字符流复制java文件
public static void main(String[] args) throws IOException { InputStreamReader isr = new InputStreamReader(new FileInputStream("D:\\java\\a1\\idea_test\\src\\com\\zy7\\demo1.java")); OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("copy7.java")); char[] cha = new char[1024]; int len; while((len= isr.read(cha))!=-1){ osw.write(cha,0,len); } // int ch; // while((ch= isr.read())!=-1){ // osw.write(ch); // } isr.close(); osw.close(); }
改进版:
数据源:读数据,用InputStreamReader的子类FileReader
目的地:写数据,OutputStreamWriter的子类FileWriter
public static void main(String[] args) throws IOException { FileReader fr = new FileReader("D:\\java\\a1\\idea_test\\src\\com\\zy8\\demo1.java"); FileWriter fw = new FileWriter("copy.java"); char[] cha = new char[1024]; int len; while((len= fr.read(cha))!=-1){ fw.write(cha,0,len); } fr.close(); fw.close(); }
5、字符缓冲流
BufferedWrite:将文本写入字符输出流,缓冲字符,以提供单个字符,数组和字符串的高效写入,可以指定缓冲区的大小,或者可以接受默认大小。默认值足够大,可用于大多数用途。
BufferedWrite(Writer out)
BufferedReader:从字符输入流读取文本,缓冲字符,以提供字符,数组和行的搞笑读取,可以指定缓冲区大小,或者可以使用默认大小,默认值足够大,可用于大多数用途。
BufferedReader(Reader in)
public static void main(String[] args) throws IOException { // FileWriter fw = new FileWriter("idea_test\\bw.txt"); // BufferedWriter bw = new BufferedWriter(fw); // bw.write("shbhjsbjsbjhbhdbcjhbd\n"); // bw.write("jdjlllll"); // bw.close(); BufferedReader br = new BufferedReader(new FileReader("idea_test\\bw.txt")); // int ch; // while((ch=br.read())!=-1){ // System.out.print((char)ch); // } char[] cha = new char[1024]; int len; while((len= br.read(cha))!=-1){ System.out.println(new String(cha,0,len)); } }
案例:用字符缓冲流复制java文件
public static void main(String[] args) throws IOException { FileWriter fw = new FileWriter("idea_test\\copy.java"); BufferedWriter bw = new BufferedWriter(fw); BufferedReader br = new BufferedReader(new FileReader("D:\\java\\a1\\idea_test\\src\\com\\zy8\\demo1.java")); char[] cha = new char[1024]; int len; while((len= br.read(cha))!=-1){ bw.write(cha,0,len); } bw.close(); br.close(); }
5.1 字符缓冲流特有功能
BufferedWriter:
void newLine():写一行行分隔符,行分隔符字符串由系统属性定义
BufferedReader:
public String readLine():读一行文字,结果包含行的内容的字符串,不包括任何行终止字符,如果流的结尾已经到达,则为null。
案例:字符缓冲流特有功能,复制Java文件
public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new FileReader("D:\\java\\a1\\idea_test\\src\\com\\zy8\\demo1.java")); BufferedWriter bw = new BufferedWriter(new FileWriter("copyd.java")); String line; while((line=br.readLine())!=null){ bw.write(line); bw.newLine(); bw.flush(); } br.close(); bw.close(); }
6、IO流小节
7、案例
7.1 集合到文件
需求:把arraylist集合中的字符串数据写道文本文件中,要求:每一个字符串元素作为文件中的一行数据
public static void main(String[] args) throws IOException { ArrayList<String> arr = new ArrayList<String>(); arr.add("hello"); arr.add("world"); arr.add("zhang"); BufferedWriter bw = new BufferedWriter(new FileWriter("idea_test\\src\\arr.txt")); for(String s:arr){ bw.write(s); bw.newLine(); bw.flush(); } bw.close(); }
7.2文件到集合
需求:把文本文件中的数据读取到集合中,并遍历集合。要求:文件中的每一行数据是一个集合元素。
public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new FileReader("idea_test\\src\\arr.txt")); ArrayList<String> arr = new ArrayList<String>(); String s; while((s = br.readLine())!=null){ arr.add(s); } br.close(); for(String a:arr){ System.out.println(a); } }
7.3 点名器
需求:我有一个文件里面存储了班级同学的姓名,每一个名字占一行,要求通过程序实现随机点名器。
public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new FileReader("idea_test\\src\\arr.txt")); ArrayList<String> arr = new ArrayList<String>(); String s; while((s = br.readLine())!=null){ arr.add(s); } br.close(); Random r = new Random(); int i = r.nextInt(arr.size()); System.out.println(arr.get(i)+","+i); }
7.4 集合到文件的改进版
需求:把arraylist集合中的学生数据写道文本文件中,要求:每一个学生元素作为文件中的一行数据
public static void main(String[] args) throws IOException { ArrayList<Student> arr = new ArrayList<Student>(); Student s1 = new Student("001","aa",12,"北京"); Student s2 = new Student("002","bb",2,"西安"); Student s3 = new Student("003","ccc",44,"河北"); arr.add(s1); arr.add(s2); arr.add(s3); BufferedWriter bw = new BufferedWriter(new FileWriter("stu,txt")); for (Student s :arr){ StringBuilder sb = new StringBuilder(); sb.append(s.getId() + "," + s.getName() + "," + s.getAge() + "," + s.getAddress()); bw.write(sb.toString()); bw.newLine(); bw.flush(); } bw.close(); }
7.5 文件到集合改进版
public static void main(String[] args) throws IOException { ArrayList<Student> arr = new ArrayList<Student>(); BufferedReader br = new BufferedReader(new FileReader("D:\\java\\a1\\stu,txt")); String s; while((s= br.readLine())!=null){ String[] strarr = s.split(","); Student stu = new Student(); stu.setId(strarr[0]); stu.setName(strarr[1]); stu.setAge(Integer.parseInt(strarr[2])); stu.setAddress(strarr[3]); arr.add(stu); } br.close(); for(Student ww:arr){ System.out.println(ww.getId() + "," + ww.getName() + "," + ww.getAge() + "," + ww.getAddress()); } }
8、案例
8.1 案例:集合到文件,键盘录入学生5个学生信息,要求成绩总分从高到底写入文本文件
格式,姓名,语文成绩,数学成绩,英语成绩
public class demo1 { public static void main(String[] args) throws IOException { TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() { @Override public int compare(Student o1, Student o2) { int num = o2.getAll() - o1.getAll(); int num2 = num == 0 ? o1.getChinese() - o2.getChinese() : num; int num3 = num2 == 0 ? o1.getMath() - o2.getMath() : num2; int num4 = num3 == 0 ? o1.getEnglish() - o2.getEnglish() : num3; return num4; } }); for (int i = 0; i < 2; i++) { Scanner sc = new Scanner(System.in); System.out.println("请录入学生信息" + i); System.out.println("姓名:"); String name = sc.nextLine(); System.out.println("语文:"); int chinese = sc.nextInt(); System.out.println("数学:"); int math = sc.nextInt(); System.out.println("英语:"); int english = sc.nextInt(); Student s1 = new Student(name, chinese, math, english); ts.add(s1); } BufferedWriter bw = new BufferedWriter(new FileWriter("D:\\java\\a1\\idea_test\\src\\java.txt")); for (Student a : ts) { StringBuilder sb = new StringBuilder(); sb.append(a.getName() + "," + a.getChinese() + "," + a.getMath() + "," + a.getEnglish() + "," + a.getAll()); String l = sb.toString(); bw.write(l); bw.newLine(); bw.flush(); } bw.close(); } }
public class Student { private String name; private int chinese; private int math; private int english; public Student() { } public Student(String name, int chinese, int math, int english) { this.name = name; this.chinese = chinese; this.math = math; this.english = english; } public int getAll(){ return this.chinese+this.math+this.english; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getChinese() { return chinese; } public void setChinese(int chinese) { this.chinese = chinese; } public int getMath() { return math; } public void setMath(int math) { this.math = math; } public int getEnglish() { return english; } public void setEnglish(int english) { this.english = english; } }
8.2 复制单极文件夹
需求:将一个文件夹,复制到模块目录下
public static void main(String[] args) throws IOException { File srcFoder = new File("yuan"); //获取yuan这个名字 String srcFolderName = srcFoder.getName(); System.out.println(srcFolderName); File destFolder = new File("D:\\java\\a1\\idea_test\\src\\com\\zy9",srcFolderName); if(!destFolder.exists()){ destFolder.mkdir(); } File[] list = srcFoder.listFiles(); for (File f : list){ String name = f.getName(); File destFile = new File(destFolder,name); copyFile(f,destFile); } } private static void copyFile(File srcFile, File destFile) throws IOException { BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcFile)); BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destFile)); byte[] bys = new byte[1024]; int len; while((len=bis.read(bys))!=-1){ bos.write(bys,0,len); } bos.close(); bis.close(); }
8.3 复制多级文件夹
public class copyduo { public static void main(String[] args) throws IOException { File srcFile = new File("D:\\yuan"); File destFile = new File("D:\\java"); copyFolder(srcFile,destFile); } private static void copyFolder(File srcFile, File destFile) throws IOException { if(srcFile.isDirectory()){ String name = srcFile.getName();//yuan File newFolder = new File(destFile,name);//zy\\yuan if(!newFolder.exists()){ newFolder.mkdir(); } File[] srclist = srcFile.listFiles(); for (File f : srclist){ copyFolder(f,newFolder); } }else{ File fa = new File(destFile,srcFile.getName()); copyFile(srcFile,fa); } } private static void copyFile(File srcFile, File destFile) throws IOException { BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcFile)); BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destFile)); byte[] bys = new byte[1024]; int len; while((len=bis.read(bys))!=-1){ bos.write(bys,0,len); } bos.close(); bis.close(); } }
8.4 复制文件的异常处理
用try-(可能出现异常的代码)-----catch(异常的处理代码)-----finally(执行所有清楚操作)
public static void main(String[] args) { FileReader fr = null; FileWriter fw = null; try { fr = new FileReader("D:\\java\\a1\\idea_test\\src\\com\\zy8\\demo1.java"); fw = new FileWriter("copy55.java"); char[] cha = new char[1024]; int len; while ((len = fr.read(cha)) != -1) { fw.write(cha, 0, len); } }catch (IOException e){ e.printStackTrace(); }finally{ if(fr!=null) { try { fr.close(); }catch (IOException e){ e.printStackTrace(); } } if (fw!=null) { try { fw.close(); }catch (IOException e){ e.printStackTrace(); } } } }
改进方法:JDK7之后的改进方案
try(定义流对象){
可能出现异常的代码;
}catch(异常类名 变量名){
异常的处理代码;
}
自动释放资源,所以不需要finally
public static void main(String[] args) { try (FileReader fr = new FileReader("D:\\java\\a1\\idea_test\\src\\com\\zy8\\demo1.java"); FileWriter fw = new FileWriter("copy55.java");) { char[] cha = new char[1024]; int len; while ((len = fr.read(cha)) != -1) { fw.write(cha, 0, len); } } catch (IOException e) { e.printStackTrace(); } }
JDK9之后的改进方案:
定义输入流对象;
定义输出流对象
try(输入流对象,输出流对象){
可能出现异常的代码;
}catch(异常类名 变量名){
异常的处理代码;
}
自动释放资源
public static void main(String[] args) throws IOException { FileReader fr = new FileReader("D:\\java\\a1\\idea_test\\src\\com\\zy8\\demo1.java"); FileWriter fw = new FileWriter("copy55.java"); try (fr;fw) { char[] cha = new char[1024]; int len; while ((len = fr.read(cha)) != -1) { fw.write(cha, 0, len); } } catch (IOException e) { e.printStackTrace(); } }
最后视频说JDK7好像不错,因为不用抛出IOE啥的异常
9、 特殊操作流
9.1 标准输入流
public static final InputStream in :该留已经打开,准备提供输入数据。标准输入流,通常该留对应于键盘输入火由主机环境火用户指定的另一个输入源。
public static final PrintStream out:标准输出流。通常该流对应于显示输出或者由主机环境或用户指定的另一个输出目标
public static void main(String[] args) throws IOException { // InputStream is = System.in; int by; while((by = is.read())!=-1){ System.out.print((char)by); } // //将字节流变成字符流,用转换流 // InputStreamReader isr = new InputStreamReader(is); //使用字符流能不能一次读取一行数据呢? //可以,但是一次读取一行数据的方法是字符缓冲流输入流的特有方法 BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); System.out.println("请输入一个字符串"); String s = br.readLine(); System.out.println(s); System.out.println("请输入一个整数"); int i = Integer.parseInt((br.readLine()));//得到的是字符串,要想获得int类型,必须转换 System.out.println(i); //自己实现键盘录入数据太麻烦了,所以java自己提供了一个类,所以java就提供了一个类。供我们使用 Scanner sc = new Scanner(System.in); }
9.2 标准输出流
public static final PrintStream out:标准输出流。通常该流对应于显示输出或者由主机环境或用户指定的另一个输出目标
public static void main(String[] args) { PrintStream ps = System.out; ps.print("hello"); ps.print(5); ps.println("jdfhdsj"); ps.println(568); System.out.println("hello"); //System.out相当于ps,System.out的本质是一个字节输出流 print必须有参数 println可以不带参数
9.3 打印流
字节打印流:printStream
字符打印流:printWriter
字节打印流:
打印流的特点:
只负责输出数据,不负责苏区数据
有自己的特有方法
printStream(String fileName):使用指定的文件名创建新的打印流
使用继承父类的方法写数据,查看的时候会转码;使用自己的特有方法写数据,查看得到数据原样输出。
public static void main(String[] args) throws FileNotFoundException { PrintStream ps = new PrintStream("D:\\java\\a1\\idea_test\\src\\java.txt"); //写数据 // ps.write(56);//8 //使用特有方法写数据 // ps.print(56);//写多少是多少 ps.close(); }
字符打印流:
PrintWriter(String fileName):使用指定的文件名创建一个新的PrintWriter,而并不需要自动执行刷新
PrintWriter(Writer out,Boolean outFlush):创建一个新的PrintWriter,如果为真,则prinln,prinf,format方法将刷新缓冲区
public static void main(String[] args) throws IOException { // PrintWriter pw = new PrintWriter(("D:\\java\\a1\\idea_test\\src\\java.txt")); // pw.write("hello\n"); // pw.flush(); // pw.write("dfhfghj\n"); // pw.flush(); // pw.println("jgjhshfjshfjdhfhd---"); // pw.flush(); //去除flush PrintWriter pw2 = new PrintWriter(new FileWriter("D:\\java\\a1\\idea_test\\src\\java.txt"),true); pw2.println("aaaaaaaaaaaaaa");//但print号线不会自动刷新,println会有自动刷新的 pw2.print(56);//没有进去,则prinln,prinf,format方法将刷新缓冲区 pw2.close();//close自带一个flush }
9.4 复制java文件(打印流改进版)
public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new FileReader("D:\\java\\a1\\idea_test\\src\\com\\zy9\\copyduo.java")); // BufferedWriter bw = new BufferedWriter(new FileWriter("copy.java")); PrintWriter pw = new PrintWriter(new FileWriter("copy.java"),true); String line; while((line = br.readLine())!=null){ // bw.write(line); // bw.newLine(); // bw.flush(); //三步可以用打印流改进 pw.println(line); } pw.close(); br.close(); }
9.5 对象序列化流
对象序列化:就是将对象保存到磁盘中,或者再网络中传输对象
这种机制就是使用一个字节序列表示一个对象,该字节序列包含:对象的类型、对象的数据和对象中存储的属性等信息。
字节序列写道文件之后,相当于文件中持久保存了一个对象的信息
反之,该字节序列还可以从文件中读取回来,重构对象,对他进行反序列化
对象序列化流
ObjectOytputStream:将java对象的原始数据类型和图形写入OutputStream。可以使用ObjectInputStream读取对象。可以通过使用流的文件来实现对象的持久存储,如果流是网络套接字流,则可以再另一个主机或者另一个进程中重构对象,
构造方法:
ObjectOutputStream(OutputStream out):创建一个写入指定的OutputSteam的ObjectOutputStream
序列化对象的方法:
void writeObject(object obj):将指定的对象写入ObjectOutputStream
注意!:一个对象要想被实例化,该对象所属的类必须实现Serializable接口
Serializable是一个标记接口,实现该接口,不需要重写任何方法
public class Student implements Serializable {//实现该接口,该对象就可以被实例化
//NotSerializableException:抛出一个实例需要一个 //类的对象的序列化,由实现Serializable的接口 public class duixiang { public static void main(String[] args) throws IOException { ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D:\\java\\a1\\idea_test\\src\\java.txt")); Student s = new Student("zx",5,6,8); oos.writeObject(s); oos.close();//使用流就要释放资源 } }
9.6 对象反序列化流
ObjectInputStream:反序列化先前使用ObjectOutputStream编写的原始数据和对象
构造方法:ObjectInputStream(InputStream in)
void readObject():读取一个对象
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D:\\java\\a1\\idea_test\\src\\java.txt")); ObjectInputStream ois = new ObjectInputStream(new FileInputStream("D:\\java\\a1\\idea_test\\src\\java.txt")); Object obj = ois.readObject(); Student s =(Student)obj; System.out.println(s.getName()+","+s.getChinese()+","+s.getEnglish()); ois.close();
问题?
用对象序列化流序列化一个对象后,加入我们修改了对象所属的类别,读取数据会不会出问题?
会出问题。
如果再student重写了一个toString方法。是类的串行版本与从流中读取的类描述符的类型不匹配
问题:InvalidClassException。
当序列化运行时检测到类中的一下问题之一时抛出。
1、类的串行版本与从流中读取的类描述符的类型不匹配
2、该类包含未知的数据参数。
3、该类没有可访问的无参构造函数。
当修改了类后,他的序列化ID会改。
static、final、long
强烈建议所有可序列化的类显示生命SerialVersionUID
如果出问题了,如何解决?
给对象所属的类加一个值。
public class Student implements Serializable { private static final long serialVersionUID = 42L; private String name; private int chinese;
如果一个对象中的某一个成员变量不想被序列化,又改如何实现?
被transient修饰的成员变量,就不会被序列化,这个位置的默认值就是0。
private transient int chinese;
10、properties
是一个Map体系的集合类
Properties可以保存到流中或从流中加载
练习,properties作为map集合使用
public static void main(String[] args) { // Properties<String,String> prop = new Properties<String,String>();//写法是不对的 Properties prop = new Properties(); prop.put("itudgf1","djfbj"); prop.put("itudgf2","djfbj"); prop.put("itudgf3","djfbj"); Set<Object> keyset = prop.keySet(); for (Object key : keyset){ Object value = prop.get(key); System.out.println(key+","+value); } }
作为集合的特有方法:
Object setProperty(String key,String value):设置集合的键和值,都是String类型,底层调用Hashtable方法put。
String getProperty(String key):使用此属性列表中指定的键搜索属性。
Set<String> stringPropertyNames():从该属性列表中返回一个不可修改的键集。其中键及其对应的键是字符串。
public static void main(String[] args) { // Properties<String,String> prop = new Properties<String,String>();//写法是不对的 Properties prop = new Properties(); prop.setProperty("001","fhfhhhb"); prop.setProperty("002","sssssssssss"); prop.setProperty("003","faaaaaaaaaa"); System.out.println(prop);//{001=fhfhhhb, 002=sssssssssss, 003=faaaaaaaaaa} System.out.println(prop.getProperty("002"));//sssssssssss System.out.println(prop.getProperty("052"));//null Set<String> names = prop.stringPropertyNames();//names拿到的是键的集合 for (String key:names){ String value = prop.getProperty(key); System.out.println(key+","+value); // 001,fhfhhhb // 002,sssssssssss // 003,faaaaaaaaaa } }
properties和IO流结合的方式:
void load(InputStream inStream):从输入字节流读取属性列表(键和元素对)
void load(Reader reader):从输入字符流读取属性列表(键和元素对)
void store(OutputStream out,String comments):将此属性列表写入此properties表中,以适合于使用load(InputStream)方法的格式写入输入字节流。
void store(Writer writer,String comments):将此属性列表写入此properties表中,以适合于使用load(InputStream)方法的格式写入输入字符流
private static void mystore() throws IOException {//集合到文件 Properties prop = new Properties(); prop.setProperty("001","lin"); prop.setProperty("002","bn"); prop.setProperty("003","ii"); FileWriter fw = new FileWriter("D:\\java\\a1\\idea_test\\src\\java.txt"); prop.store(fw,null); fw.close(); }
#Wed Mar 30 21:40:08 CST 2022 001=lin 002=bn 003=ii
文件到集合:
private static void myload() throws IOException { Properties prop = new Properties(); FileReader fr = new FileReader("D:\\java\\a1\\idea_test\\src\\java.txt"); prop.load(fr); fr.close(); System.out.println(prop); }
{001=lin, 002=bn, 003=ii}
10.1 游戏次数
需求:请写程序实现猜数字小游戏只能试玩3次,如果还想玩。提示:游戏试玩已经结束,想玩请充值(
public class playgame { private playgame(){ } public static void start(){ Random r = new Random(); int num = r.nextInt(100)+1; while(true){ Scanner sc = new Scanner(System.in); System.out.println("请输入你要才的数字:"); int n = sc.nextInt(); if(n>num){ System.out.println("大了"); }else if(n<num){ System.out.println("小了"); }else{ System.out.println("猜中了"); break; } } } }
public class demotest { public static void main(String[] args) throws IOException { //文件到集合 Properties prop = new Properties(); FileReader fr = new FileReader("D:\\java\\a1\\idea_test\\src\\java.txt"); prop.load(fr); fr.close(); String count = prop.getProperty("count"); int number = Integer.parseInt(count); if(number>=3){ System.out.println("试玩结束"); }else{ playgame.start(); number++; prop.setProperty("count",String.valueOf(number)); FileWriter fw = new FileWriter("D:\\java\\a1\\idea_test\\src\\java.txt"); prop.store(fw,null); fw.close(); } } }