前言

b站java课程学习笔记整理。

b站视频: 黑马程序员全套Java教程_Java基础入门视频教程,零基础小白自学Java必备教程

309. 复制单级文件夹

需求:把一个文件夹下的所有文件复制到指定的位置。

package 文件夹的复制;

import java.io.*;

public class Demo {
    public static void main(String[] args) throws IOException {
        // 创建数据源目录对象
        File srcFolder = new File("E:\\Javacode\\JavaSE Code\\rookie");
        //获取数据源目录的名称
        String folderName = srcFolder.getName();

        // 创建目的地目录
        File destFolder = new File("idea_test",folderName);

        // 如果目的地目录不存在,就新建一个目录
        if(!destFolder.exists()){
            destFolder.mkdir();
        }

        // 创建一个文件数组,读取数据源目录下所有文件
        File[] listFiles = srcFolder.listFiles();

        // 写文件
        for(File srcFile:listFiles){
            String srcFileName = srcFile.getName();
            File destFile = new File(destFolder,srcFileName);
            copyFile(srcFile,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())!=-1){
            bos.write(bys,0,len);
        }

        bis.close();
        bos.close();
    }
}

310. 复制多级文件夹

用递归。

package 文件夹的复制;

import java.io.*;

public class DuoJiDemo {
    public static void main(String[] args) throws IOException {
        // 创建数据源目录对象
        File srcFile = new File("E:\\Javacode\\JavaSE Code\\theshy");
        // 创建目的地对象
        File destFile = new File("idea_test");
        // 使用copyFolder方法
        copyFolder(srcFile,destFile);


    }
    private static void copyFolder(File srcFile, File destFile) throws IOException {
        //如果是文件夹
        if(srcFile.isDirectory()){
            // 在目的地下查找同名目录,如果没有就创建个新的
            String srcFilename = srcFile.getName(); // “一个文件夹”
            File newFolder = new File(destFile,srcFilename); // “idea_test\\一个文件夹”
            if(!newFolder.exists()){
                newFolder.mkdir();
            }
            File[] fileList =  srcFile.listFiles();
            for(File file:fileList){
                copyFolder(file,newFolder); //递归,新的文件夹地址取代了destFile。
            }
        }else{
            File newFile = new File(destFile,srcFile.getName());
            copyFile(srcFile,newFile);
        }
    }
    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())!=-1){
            bos.write(bys,0,len);
        }

        bis.close();
        bos.close();
    }
}

有点难,注意理解。

311. 复制文件夹的异常处理

保准的使用try...catch...finally处理。 JDK7的改进方案:

try(定义流对象){
    可能有问题的代码;
}catch(异常类名 变量名){
    异常的处理代码
}
自动释放资源

JDK9的改进方案:

定义输入流对象
定义输出流对象
try(输入流对象;输出流对象e){
    可能有问题的代码;
}catch(异常类名 变量名){
    异常的处理代码
}
自动释放资源
   

四种完整的方法:

package 复制文件的异常处理;

import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class demo {
    public static void main(String[] args) {

    }

    // 方法一: 直接抛出
    private static void method1() throws IOException {
        FileWriter fw = new FileWriter("java.txt");
        FileReader fr = new FileReader("idea_test\\java.txt");
        char[] chars = new char[1024];
        int len;
        while ((len = fr.read()) != -1) {
            fw.write(chars, 0, len);
        }
    }

    // 方法二: 标准化处理
    private static void method2() {
        FileWriter fw = null;
        FileReader fr = null;
        try {
            fw = new FileWriter("java.txt");
            fr = new FileReader("idea_test\\java.txt");
            char[] chars = new char[1024];
            int len;
            while ((len = fr.read()) != -1) {
                fw.write(chars, 0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fw == null){
                try {
                    fw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(fr== null){
                try {
                    fr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    // 方法三: JDK7
    private static void method3() {
        try (FileWriter fw = new FileWriter("java.txt");
             FileReader fr = new FileReader("idea_test\\java.txt")){
            char[] chars = new char[1024];
            int len;
            while ((len = fr.read()) != -1) {
                fw.write(chars, 0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 方案四: JDK9
    private static void method4() throws IOException {
        FileWriter fw = new FileWriter("java.txt");
        FileReader fr = new FileReader("idea_test\\java.txt");
        try (fw;fr){
            char[] chars = new char[1024];
            int len;
            while ((len = fr.read()) != -1) {
                fw.write(chars, 0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

312. 标准输入流

System类中有两个静态的成员变量:

  • public static final InputStream in 标准输入流。
  • public static final PrintStream out 标准输出流。

自己实现键盘录入数据:

  • BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

原理就是把系统的标准输入流(字节输入流)转换为字符输入流,再包装成缓冲输入流,之后就可以使用readLine方法了。

这就是Scanner的底层原理。

313. 标准输出流

System.out的本质就是一个字节输出流。

sout 就是System.out.Println() 就是字节输出流的一种使用。

314. 字节打印流

打印流分类:

  • 字节打印流: PrintStream
  • 字符打印流:PrintWriter

打印流的特点:

  • 只负责输出数据,不负责读取数据
  • 有自己的特有方法

字节打印流

  • PrintStream(String fileName): 使用指定的文件名创建新的打印流。
package 字节打印流;

import java.io.IOException;
import java.io.PrintStream;

public class Demo {
    public static void main(String[] args) throws IOException {
        PrintStream ps = new PrintStream("idea_test\\rookie\\java.txt");

        ps.write(97);

        ps.print(97);
        ps.println(98);
        ps.println(false);

        ps.close();
    }
}

特有方法printprintln,使用这两种方法,到txt文档没有转码,写多少就是多少。

315. 字符打印流

方法名 说明
PrintWriter(String fileName) 使用指定的文件名创建一个新的PrintWriter,而不需要自动执行刷新
PrintWriter(Writer out, boolean autoFlush) 创建一个新的PrintWriter
out:字符输出流
autoFlush:一个布尔值,如果为真,则printlnprintf,或者format方法将刷新输出缓冲区

示例代码:

package 字符打印流;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;

public class Demo {
    public static void main(String[] args) throws IOException {
        PrintWriter pw = new PrintWriter("idea_test\\java.txt");
        pw.println("hello");
        pw.flush();
        pw.println("world");
        pw.flush();
        pw.close();


        PrintWriter pw2 = new PrintWriter(new FileWriter("idea_test\\java.txt"),true);
        pw2.println("ni");
        pw2.println("hao");
        pw2.close();
    }
}

316. 复制java文件打印流改进版

package 复制java文件打印流改进版;

import java.io.*;

public class Demo {
    public static void main(String[] args) throws IOException {
        String source = "E:\\Javacode\\JavaSE Code\\rookie\\rookie.java";
        String destination = "E:\\Javacode\\JavaSE Code\\theshy\\theshy.java";

        BufferedReader br = new BufferedReader(new FileReader(source));
        PrintWriter pw = new PrintWriter(new FileWriter(destination),true);
        
        String line;
        while((line=br.readLine())!=null){
            pw.println(line);
        }
        
        br.close();
        pw.close();
        
        

    }
}

总结:用这个,这个简单。

317. 对象序列化流

就是把一个对象写入一个文件中。

对象序列化流:ObjectOutputStream

  • 将Java对象的原始数据类型和图形写入OutputStream。可以使用ObjectInputStream读取(重构)对象。可以通过使用流的文件来实现对象的持久存储。如果流是网络套接字流,则可以在另一个主机上或另一个进程中重构对象。

构造方法:

  • ObjectOutputStream(OutputStream out): 创建一个写入指定的OutputStreamObjectOutputStream

序列化对象的方法:

  • void writeObject(Object obj): 将指定的对象写入ObjectOutputStream

注意:

需要写入的类必须实现序列化接口Serializable。这个接口不需要重写方法。

package 对象序列化流;

import java.io.Serializable;

public class Student implements Serializable {

    private int age;

    private String name;

    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;
    }

    public Student(String name, int age) {
        System.out.println("使用带参方法定义");
        this.name = name;
        this.age = age;
    }

    public Student() {
        System.out.println("使用无参方法定义");
    }

    public void getInfo() {
        System.out.println("学生名为" + name);
        System.out.println("学生年龄为" + age);
    }
}

package 对象序列化流;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

public class Demo {
    public static void main(String[] args) throws IOException {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("java.txt"));
        Student s = new Student("林青霞",30 );
        oos.writeObject(s);

        oos.close();
    }
}

318. 对象的反序列化流

构造方法:

  • ObjectInputStream(InputStream in): 创建从指定的InputStream读取的ObjectInputStream

反序列化对象的方法:

  • Object readObject(): 从ObjectInputStream读取一个对象。
package 对象反序列化流;

import 对象序列化流.Student;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;

public class Demo {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("java.txt"));
        Object obj = ois.readObject();

        Student s = (Student) obj;

        s.getInfo();

        ois.close();
    }

}

注意: 反序列化流里的Student类要和序列化流的类一致,不然就会报错ClassNotFoundException

319. serialVersionUID&transient

在序列化写入对象时,类会获取一个ID,在修改类后,类会获取一个新ID。这会导致类版本不匹配的报错问题。

解决方案:让这个类提前声明一个ID,并用private进行修饰。

示例代码:

private static final long serialVersionUID = 42L;

如果一个变量不想被序列化,那就用transient修饰。

示例代码:

pritave transient String name;

320. Properties作为Map集合的使用

Properties是一个Map体系的集合类,可以保存在流中,或者被流加载。

Properties虽然是Map体系的,但是没有泛型

package PropertiesDemo;

import java.util.Properties;
import java.util.Set;

public class Demo {
    public static void main(String[] args) {
        Properties prop = new Properties();

        prop.put("1","孙健耕");
        prop.put("2","王晓松");
        prop.put("3","林青霞");

        Set<Object> keyset = prop.keySet();
        for (Object key: keyset){
            Object value = prop.get(key);
            System.out.println(key +","+ value);
        }
    }
}

321. Properties作为集合的特有方法

方法名 说明
Object setProperty(String key, String value) 设置集合的键和值,都是String类型,底层调用Hashtable方法put
String getProperty(String key) 使用此属性列表中指定的键搜索属性
Set<String> stringPropertyNames() 从该属性列表中返回一个不可修改的键集,其中键及其对应的值是字符串
package PropertiesDemo;

import java.util.Properties;
import java.util.Set;

public class Demo2 {
    public static void main(String[] args) {
        Properties prop = new Properties();
        prop.setProperty("123","孙健耕");
        prop.setProperty("1234","孙健");

        System.out.println(prop.getProperty("123"));
        System.out.println(prop.getProperty("12343"));

        Set<String> names = prop.stringPropertyNames();
        for(String key: names){
            System.out.println(key+","+prop.getProperty(key));
        }
    }
}

map那里的键值对原理是一样的。

322. 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(Reader)方法的格式写入输出字符流。
package PropertiesDemo;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Properties;

public class Demo3 {
    public static void main(String[] args) throws IOException {
        myStore();
        myload();
    }

    private static void myload() throws IOException {
        Properties prop = new Properties();
        FileReader fr = new FileReader("java.txt");
        prop.load(fr);
        fr.close();
        System.out.println(prop);
    }


    private static void myStore() throws IOException {
        Properties prop = new Properties();

        prop.setProperty("123","孙健耕");
        prop.setProperty("1234","孙健");

        FileWriter fw = new FileWriter("java.txt");
        prop.store(fw,null);
        fw.close();
    }
}

把文件中的属性加载到集合。

323. 游戏次数

需求:用程序实现猜数字小游戏只能试玩三次,如果还想玩,提示想玩请充值。

思路:

  1. 写一个游戏类,里面有一个猜数字的小游戏。
  2. 写一个测试类。
#Sun Nov 21 22:29:49 CST 2021
count=3
package 游戏次数;

import java.util.Random;
import java.util.Scanner;

public class Game {
    private Game(){};
    public static void start(){
        Random r = new Random();
        int number = r.nextInt(100)+1;

        while(true){
            Scanner sc = new Scanner(System.in);
            System.out.println("请输入你要猜的数字");
            int guessNumber = sc.nextInt();

            if(guessNumber > number){
                System.out.println("你猜的数字"+guessNumber+"大了");
            }else if(guessNumber<number){
                System.out.println("你猜的数字"+guessNumber+"小了");
            }else{
                System.out.println("恭喜你猜中了");
                break;
            }
        }
    }
}

package 游戏次数;

import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Properties;

public class Demo {
    public static void main(String[] args) throws IOException {

        Properties prop = new Properties();

        FileReader fr = new FileReader("idea_test\\java.txt");
        prop.load(fr);
        fr.close();

        String count = prop.getProperty("count");
        int number = Integer.parseInt(count);

        if(number>=3){
            System.out.println("请充值");
        }else{
            Game.start();
            number++;
            prop.setProperty("count",String.valueOf(number));
            FileWriter fw = new FileWriter("idea_test\\java.txt");
            prop.store(fw,null);
            fw.close();

        }

    }
    private static void myStore() throws IOException {
        Properties prop = new Properties();
        prop.setProperty("count","0");
        FileWriter fw = new FileWriter("idea_test\\java.txt");
        prop.store(fw,null);
        fw.close();
    }
}