Java基础笔记

本文详细介绍了Java中的多线程概念,包括生产者消费者模型的实现,线程的生命周期,以及File类的使用,如构造器、创建删除文件、判断文件属性、目录遍历等。同时,文章还涵盖了IO流的基本知识,如字节流和字符流的分类、方法以及文件复制的应用。
摘要由CSDN通过智能技术生成
笔记
  • 生产者消费者代码案
  • 线程的生命周期
  • File类

多线程&IO

  • 今日内容
    • 生产者与消费者案例
    • 线程通信方法
    • 生产者消费者案例优化
    • 线程生命周期
    • File类构造器
    • File类常用方法
    • File类目录遍历

第一章 生产者与消费者

1.1 案例介绍

生产者与消费者案例:角色一个生产者(线程),一个消费者(线程),针对于同样的一个资源数据,进行不同方向的操作。最终要达到的目的:生产一个消费一个,不能一次生产多个,也不能一次消费多个。实现的效果:生产1个,消费1个,生产2个,消费2个…

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GQBxtCsw-1682346063120)(imgs\05131.png)]

1.2 案例实现

  • 生产和消费共用一个对象
/**
 * 资源对象,定义产品的计数器
 */
public class Resource {
    int count;//定义产品的计数器 default = 0
}
/**
 * 生产者线程,负责对资源对象中计数器++操作
 */
public class Produce implements Runnable{
    //创建资源对象
    private Resource r ;

    public Produce(Resource r) {
        this.r = r;
    }

    @Override
    public void run() {
        while (true){
            r.count++;
            System.out.println("生产第"+r.count+"个");
        }
    }
}
/**
 * 消费者线程,负责将资源对象中的计数器输出打印
 */
public class Customer implements Runnable{
    //创建资源对象
    private Resource r ;

    public Customer(Resource r) {
        this.r = r;
    }

    @Override
    public void run() {
        while (true){
            //输出资源对象中的计数器
            System.out.println("消费第"+r.count+"个");
        }
    }
}
    public static void main(String[] args) {
        //创建资源对象
        Resource r = new Resource();
        //开启生产者线程和消费者线程
        Runnable product = new Produce(r);
        Runnable customer = new Customer(r);
        new Thread(product).start();//开启生产者线程
        new Thread(customer).start();//开启消费者线程
    }
  • 数据安全加入同步锁,保证同步对象锁唯一的
/**
 * 生产者线程,负责对资源对象中计数器++操作
 */
public class Produce implements Runnable{
    //创建资源对象
    private Resource r ;
    public Produce(Resource r) {
        this.r = r;
    }
    @Override
    public void run() {
        while (true){
            synchronized (r) {
                r.count++;
                System.out.println("生产第" + r.count + "个");
            }
        }
    }
}
/**
 * 消费者线程,负责将资源对象中的计数器输出打印
 */
public class Customer implements Runnable{
    //创建资源对象
    private Resource r ;

    public Customer(Resource r) {
        this.r = r;
    }
    @Override
    public void run() {
        while (true){
            synchronized (r) {
                //输出资源对象中的计数器
                System.out.println("消费第" + r.count + "个");
            }
        }
    }
}

1.3 线程通信的方法

线程通信的方法:线程的等待和唤醒,定义在Object类中:

  • void wait() 线程无限等待
  • void notify() 唤醒等待的单个线程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-l6FBrSGx-1682346063125)(imgs\05132.png)]

  • 线程等待与唤醒中的异常问题

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QD55AVEw-1682346063126)(D:/Atguigu/day22源码笔记/笔记/images/3.png)]

IllegalMonitorStateException:无效的监视器状态异常
程序中出现这个异常:线程wait() 和 notify() 造成的异常:监视器就是对象锁
wait(),notify() 必须要出现在同步中,方法的调用者必须是锁对象!!
/**
 * 资源对象,定义产品的计数器
 */
public class Resource {
    int count;//定义产品的计数器 default = 0
    /**
     *  定义标志位 default false
     *  flag = false,可以生产,不能消费
     *  flag = true ,可以消费,不能生产
     */
    boolean flag ;
}
/**
 * 生产者线程,负责对资源对象中计数器++操作
 */
public class Produce implements Runnable{
    //创建资源对象
    private Resource r ;

    public Produce(Resource r) {
        this.r = r;
    }

    @Override
    public void run() {
        while (true){
            synchronized (r) {
                //判断变量flag =true ,无限等待
                if (r.flag)
                   try{
                       r.wait();
                   }catch (Exception ex){}

                r.count++;
                System.out.println("生产第..." + r.count + "个");
                //改标志位,可消费
                r.flag = true;
                //唤醒对方线程
                r.notify();
            }
        }
    }
}

/**
 * 消费者线程,负责将资源对象中的计数器输出打印
 */
public class Customer implements Runnable{
    //创建资源对象
    private Resource r ;

    public Customer(Resource r) {
        this.r = r;
    }

    @Override
    public void run() {
        while (true){
            synchronized (r) {
                //判断标记 flag=false,不能消费,无限等
                if (!r.flag)
                   try{
                       r.wait();
                   }catch (Exception ex){}

                //输出资源对象中的计数器
                System.out.println("消费第" + r.count + "个");
                //消费完毕改标志位 flag = false 可以生产
                r.flag = false;
                //唤醒对方线程
                r.notify();
            }
        }
    }
}


1.4 wait()和sleep()区别

  • wait()是Object类的,非静态

  • sleep()是Thread类的,静态的

  • wait()等待,需要被唤醒

  • sleep()休眠,时间到自己就醒了

  • wait()方法调用者必须是锁对象

  • sleep()方法出现哪里都可以

  • sleep()方法不会释放同步锁

  • wait()方法会释放同步锁,被唤醒后要重新获取同步锁才能执行

1.5 生产者与消费者案例优化

/**
 * 资源对象,定义产品的计数器
 * 成员私有修饰,提供get set
 */
public class Resource {
   private int count;//定义产品的计数器 default = 0
    /**
     *  定义标志位 default false
     *  flag = false,可以生产,不能消费
     *  flag = true ,可以消费,不能生产
     */
   private boolean flag ;
    /**
     * 定义get方法,被消费者线程调用
     * 完成消费者的工作
     */
    public synchronized void get(){
        //判断标志位
        if (!flag)
            try{this.wait();}catch (Exception ex){}
        //消费
        System.out.println("消费第"+count+"个");
        //改标志位
        flag = false;
        this.notify();
    }

    /**
     * 定义set方法,被生产者线程调用
     * 完成生产者的工作
     */
    public synchronized void set(){
        //判断标志位
        if (flag)
            //等待
            try{this.wait();}catch (Exception ex){}
        //生产
        count++;
        System.out.println("生产第..."+count+"个");
        //修改标志位
        flag = true;
        this.notify();
    }
}

/**
 * 生产者线程,负责对资源对象中计数器++操作
 */
public class Produce implements Runnable{
    //创建资源对象
    private Resource r ;

    public Produce(Resource r) {
        this.r = r;
    }

    @Override
    public void run() {
        while (true)
            //调用资源对象的set方法
            r.set();
    }
}

/**
 * 消费者线程,负责将资源对象中的计数器输出打印
 */
public class Customer implements Runnable{
    //创建资源对象
    private Resource r ;

    public Customer(Resource r) {
        this.r = r;
    }

    @Override
    public void run() {
        while (true)
            //调用资源对象的方法get
            r.get();
    }
}

第二章 线程生命周期

所谓线程的声明周期:线程的状态,反映出线程从创建到结束的生命历程。API已经给出了线程的生命周期。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sXJKKuuw-1682346063126)(imgs\05134.png)]

  • java.util.concurrent.ConcurrentHashMap类:JDK1.5版本
    • Map接口的实现类,键值对的集合
    • 底层的数据结构和HashMap一致
    • ConcurrentHashMap类是一半线程安全,一半线程不安全
    • 如果不修改里面的键值对,线程不安全的
    • 如果动了里面的键值对,线程是安全

第三章 File类

3.1 File类介绍

  • java.io.File

    • 计算机存在路径,目录,文件
    • File类将计算机中的路径,目录,文件做成对象
    • 提供很多的方法,操作路径,目录和文件
  • 计算机操作系统

    • 目录就是文件夹(Directory),不能存储数据,是文件的容器
    • 文件(File),可以存储数据
    • 路径(Path),一个文件或者目录,在计算机中的存储位置

File类,是平台无关性的类

3.2 File类构造方法 (非常重要)

  • File(String pathname)传递字符串的路径,可以表示目录也可以表示文件
/**
     * File(String pathname)传递字符串的路径,可以表示目录也可以表示文件
     * 路径里面,IDEA自动添加转义字符
     */
public static void testConstructor1(){
    File file = new File("E:\\soft\\apache-maven-3.3.9\\bin\\m2.conf");
    System.out.println("file = " + file);
}

  • File(String parent,String child) 传递字符串的父路径,字符串的子路径
    /**
     * File(String parent,String child) 传递字符串的父路径,字符串的子路径
     * E:\soft\apache-maven-3.3.9\bin  为参考点
     * E:\soft\apache-maven-3.3.9\  是父路径
     * E:\soft\apache-maven-3.3.9\bin\ 里面的都是子路径
     */
    public static void testConstructor2(){
        File file = new File("e:\\soft\\apache-maven-3.3.9","bin");
        System.out.println("file = " + file);
    }

  • File(File parent,String child) 传递File类型父类经,字符串的子路径
    /**
     * File(File parent,String child) 传递File类型父类经,字符串的子路径
     * 构造方法的第一个参数是File类型,可以调用File类的方法
     */
    public static void testConstructor3(){
        File parent = new File("E:\\soft\\apache-maven-3.3.9");
        File file = new File(parent,"bin");
        System.out.println("file = " + file);
    }

Windows操作系统:路径,目录,文件的名字,都是不区分大小写。Linux操作系统区分

路径的写法:Windows \,Linux / Java中路径,写 \ 或者 / 都可以

3.3 File类的创建和删除的方法(非常重要)

  • boolean createNewFile() 创建文件的方法,文件的路径和名字定义在File类构造方法中
    /**
     * boolean createNewFile() 创建文件的方法,文件的路径和名字定义在File类构造方法中
     * 创建成功返回true
     * createNewFile() 无论名字怎么写,创建出现来都是文件
     */
    public static void testCreateNewFile() throws IOException {
        //创建File对象,路径和文件名写在构造方法中
        File file = new File("e:/a.txt");
        //创建文件
        boolean b = file.createNewFile();
        System.out.println("b = " + b);
    }

  • boolean mkdirs() 创建目录,目录的名字和路径写在File类构造方法中
    /**
     * boolean mkdirs() 创建目录,目录的名字和路径写在File类构造方法中
     * 创建成功返回true
     */
    public static void testMkdirs(){
        //创建File对象,目录路径写在构造方法中
        File file = new File("e:/a/b/c/d");
        //调用方法创建文件夹
        boolean b = file.mkdirs();
        System.out.println("b = " + b);
    }

  • boolean delete() 删除,要删除的文件或者是目录写在File类构造方法中
/**
     * boolean delete() 删除,要删除的文件或者是目录写在File类构造方法中
     * 删除不走回收站,在硬盘中就没有了
     * 删除有风险,执行需谨慎
     * 如果文件夹不是空的,就删除不掉
     */
public static void testDelete(){
    File file = new File("e:/a");
    //boolean b = file.delete();
    //System.out.println("b = " + b);
}

3.4 File类的判断方法(非常重要)

  • boolean exists() 判断File构造方法中路径,是不是存在的,存在返回true
    /**
     * boolean exists() 判断File构造方法中路径,是不是存在的,存在返回true
     */
    public static void testExists(){
        //建立File对象,构造方法中,写路径
        File file = new File("E:\\SOFT\\APACHE-MAVEN-3.3.9\\BIN");
        //判断路径是否存在
        boolean b = file.exists();
        System.out.println("b = " + b);
    }

  • boolean isFile() 判断构造方法中的路径,是不是文件,是文件返回true
  • boolean isDirectory() 判断构造方法中的路径,是不是目录,是目录返回true
    /**
     *  boolean isFile() 判断构造方法中的路径,是不是文件,是文件返回true
     *  boolean isDirectory() 判断构造方法中的路径,是不是目录,是目录返回true
     */
    public static void testIsFileDirectory(){
        File file = new File("e:\\soft\\apache-maven-3.3.9\\bin\\mvn.cmd");
        if (file.exists()) {
            //判断路径是不是目录
            boolean directory = file.isDirectory();
            System.out.println("directory = " + directory);

            //判断是不是文件
            boolean isFile = file.isFile();
            System.out.println("isFile = " + isFile);
        }
    }

3.5 File类获取方法(非常重要)

  • String getName()获取名字
    /**
     * String getName()获取名字
     * 返回的名字,File构造方法中,路径最后部分的名字
     */
    public static void testGetName(){
        File file = new File("E:\\soft\\apache-maven-3.3.9\\bin\\m2.conf");
        //getName()方法获取名字
        String name = file.getName();
        System.out.println("name = " + name);
    }

  • File getParentFile() 返回File构造方法中,路径的父路径(上一级文件夹)
    /**
     * File getParentFile() 返回File构造方法中,路径的父路径(上一级文件夹)
     * getParentFile()方法的返回值是File对象
     * 当一个方法的返回值是一个对象的时候,继续使用对象调用方法
     * 链式编程,方法调用链
     */
    public static void testGetParentFile(){
        File file = new File("E:\\soft\\apache-maven-3.3.9\\bin");
        //获取构造方法中,路径的父路径
        File parent = file.getParentFile();
        System.out.println("parent = " + parent);
    }

  • File getAbsoluteFile() 返回File构造方法中个,路径的绝对路径
    /**
     * File getAbsoluteFile() 返回File构造方法中个,路径的绝对路径
     * 绝对路径,在计算机系统中,具有唯一性
     * 例子:E:\soft\apache-maven-3.3.9\bin
     *
     * File file = new File("bin");
     * 构造方法中,路径不是绝对路径
     * 返回的绝对路径:是IDEA创建的工程根目录  E:\0411JavaSe\bin
     */
    public static void testGetAbsoluteFile(){
        File file = new File("bin");
        //获取构造方法中路径的绝对路径
        File absoluteFile = file.getAbsoluteFile();
        System.out.println("absoluteFile = " + absoluteFile);
    }

3.6 ListFiles (非常重要)

  • File[] listFiles() 获取File构造方法中,路径下的所有文件和文件夹 (目录遍历)
    /**
     * File[] listFiles() 获取File构造方法中,路径下的所有文件和文件夹 (目录遍历)
     */
    public static void testListFiles(){
        File file = new File("c:/abc");
        //调用方法listFiles 目录的遍历
        File[] fileArray = file.listFiles();
        System.out.println(fileArray.length);
        for (File f : fileArray){
            System.out.println("f = " + f);
        }
    }

  • 文件过滤器接口
    • java.io.FileFiter接口:
      • 接口的实现类,就是文件过滤器
      • 自定义类实现接口,重写方法 accept
/**
 * 自定义文件过滤器
 */
public class MyFileFilter implements FileFilter {
    //重写抽象方法
    /**
     *
     * accept方法是由listFiles调用,传递遍历到的路径
     * 判断这个路径filename,是.java结尾返回true
     * filename = c:\abc\1.docx
     */
    public boolean accept(File filename){
        //filename.getName() 获取路径中的文件名,返回字符串
        //文件名字符串.toLowerCase()变小写
        return filename.getName().toLowerCase().endsWith(".java");
    }
}

    /**
     * listFiles方法,遍历目录,只要java文件
     * listFiles(传递文件过滤器接口实现类对象)
     */
    public static void testListFilesFilter(){
        File file = new File("c:/abc");
        //调用方法listFiles 目录的遍历
        File[] fileArray = file.listFiles( new MyFileFilter() );
        for (File f : fileArray){
            System.out.println("f = " + f);
        }
    }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OA6PkSP4-1682346063127)(imgs\05135.png)]

3.7 递归遍历所有目录

public class FileDemo06 {
    public static void main(String[] args) {
        getDir( new File("c:/java") );
    }

    /**
     * 定义方法:遍历指定的目录
     * 将要遍历的目录传递参数
     */
    public static void getDir(File srcDir){
        System.out.println(srcDir);
        //遍历目录
        File[] arrFile =srcDir.listFiles();
        for (File f : arrFile){
            //判断 路径 f 是不是文件夹(目录)
            if (f.isDirectory()){
                //调用自己,传递f 路径
                getDir(f);
            }else {
                System.out.println(f);
            }
        }
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Qu2vwXyX-1682346063127)(imgs\05136.png)]

第四章 IO流

4.1 IO流对象介绍

IO是两个单词的缩写(Input 输入,Output 输出),流是一种比喻,数据从一个设备流向另一个设备。文件1.txt 可以从硬盘中流向内存中

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nxK11qD1-1682346063128)(images/7.png)]

IO流应用:数据从一个计算机流向另一个计算机,网络通信

4.2 IO流对象的分类(非常重要)

  • 按照数据流的方向分类:
    • 输出流:Java程序中的数据,流到其他设备,写入
    • 输入流:数据从其他设备,流到Java的程序中,读取
  • 按照操作的数据类型分类:
    • 字节流:可以操作任意类型的数据
    • 字符流:只能操作文本类型的数据 (文本工具,记事本,Notepad,editplus)打开这个文件,文本工具会自动查询编码表,结果人能看懂,就是文本
  • 总结归类 (4大类):
    • 字节输出流:可以写入任何数据文件
      • 字节输出流顶级父类:java.io.OutputStream
    • 字节输入流:可以读取任何数据文件
      • 字节输入流顶级父类:java.io.InputStream
    • 字符输出流:只能写入文本文件
      • 字符输出流顶级父类:java.io.Writer
    • 字符输入流:只能读取文本文件
      • 字符输入流顶级父类:java.io.Reader

4.3 编码表

编码表:为了让计算机可以直接识别人类的文字,开发出了编码表,生活中的一个字对应十进制的整数

  • ASCII 编码表:字母,数字,符号,都是1个字节存储,都是正数

    • a-z 97-122
    • A-Z 65-90
    • 0-9 48-57
  • GB系列字符集(多个编码表的集合),简体中文

    • GB2312,简体中文编码表,4000多个汉字
    • GBK,简体中文编码表,21886多个汉字
    • GB18030,简体中文编码表,70244多个汉字
    • 中文版操作系统,默认使用的汉字编码表就是GBK
    • 简体中文编码表中,一个汉字占用2个字节,是负数,第一个字节肯定是负数
  • Unicode字符集(多个编码表的集合),万国码

    • UTF-8,最小用1个字节存储,汉字是三个字节,基本上负数,可变长度的编码
    • UTF-16,定长的编码表,无论什么字,都是2个字节存储
      • Java中的char类型,和String类型,都是UTF-16编码存储
      • JDK9开始char没变,String类型变了
        • 如果存储汉字,都是UTF-16编码存储
        • 字符串没有汉字,全是字母,数组,拉丁文编码表存储,1个字节存储
    • 最常用的编码表UTF-8
  • 文件复制+properties

IO流对象

  • 今日内容
    • 字节输出流
    • 字节输入流
    • 文件复制
    • 缓冲流
    • 字符输出流
    • 字节输入流
    • 缓冲流

第一章 字节输出流

1.1 OutputStream字节输出流

  • OutputStream类:所有字节输出流的顶级父类
  • 字节输出流的方法,都是写入的方法:write
    • write(byte[] b) 写入字节数组
    • write(int i) 写入单个字节
    • write(byte[],int off,int len) 写入字节数组,开始索引,写入个数
    • close()释放资源
  • OutputStream类的子类:FileOutputStream

1.2 FileOutputStream写入文件(非常重要)

  • FileOutputStream构造器
    • FileOutputStream(File file) File对象的路径是文件
    • FileOutputStream(String filename) 字符串路径文件
    • 构造方法中对象:字节输入流的数据输出目的
  • 写入单个字节
    /**
     * write(int i) 写入单个字节
     * FileOutputStream流对象,自动创建文件,如果文件已经存在,覆盖
     */
    public static void testWriteByte()throws IOException {
        //创建字节输出流,构造方法,传递字符串文件名(输出目的)
        FileOutputStream fos =  new FileOutputStream("e:/haha.txt");
        //调用流对象的方法write,写单个字节
        fos.write(49);
        fos.write(48);
        fos.write(48);
        //释放资源,关闭次流对象
        fos.close();
    }
  • 流对象的close()方法问题

close()关闭流,释放系统资源,IO流技术,读写数据,JVM(虚拟机)很聪明,任何一个操作系统(Windows还是Linux)本身就有IO流技术,JVM的IO流技术找操作系统来完成

  • 写入字节数组
    /**
     * write(byte[] b) 写入字节数组
     */
    public static void testWriteByteArray()throws IOException{
        //创建字节输出流对象,构造方法绑定字符串路径
        FileOutputStream fos = new FileOutputStream("e:/haha.txt");
        byte[] bytes = {97,98,99,100,101,102};
        //流对象的方法write写入数组
        fos.write(bytes);
        fos.close();
    }
  • 写入字节数组一部分
    /**
     * write(byte[],int off,int len) 写入字节数组,开始索引,写入个数
     */
    public static void testWriteByteArrayPart()throws IOException{
        //创建字节输出流对象,构造方法绑定字符串路径
        FileOutputStream fos = new FileOutputStream("e:/haha.txt");
        byte[] bytes = {97,98,99,100,101,102};
        //流对象的方法write写入数组,的一部分
        //1索引开始,写3个
        fos.write(bytes,1,3);
        fos.close();
    }

1.3 流对象的异常处理

 /**
     * 字节输出流,写文件
     * IO流对象添加异常处理try catch
     * close() 释放资源,写在finally中
     */
    public static void testWriteByteArray(){
        //提升变量fos的作用域
        //try外定义变量,try内建立对象
        FileOutputStream fos = null;
        try {
            //创建对象失败,fos值依然还是null
            fos = new FileOutputStream("e:/haha.txt");
            byte[] bytes = {97, 98, 99, 100, 101, 102};
            //流对象的方法write写入数组,的一部分
            //1索引开始,写3个
            fos.write(bytes, 1, 3);
        }catch (IOException ex){
            ex.printStackTrace();
        }finally {
            //close()方法抛出异常,继续try catch
            //释放资源之前,fos对象判断空
            if( fos != null)
                try {
                    fos.close();
                }catch (IOException ex){
                    ex.printStackTrace();
                }
        }
    }

1.4 字节流的追加写入

FileOutputStream构造方法:第二个参数写true,写入文件就是追加写入,不会覆盖原有的文件

FileOutputStream fos = new FileOutputStream("e:/haha.txt",true);

第二章 字节输入流

2.1 InputStream字节输入流

  • InputStream类:所有字节输入流的顶级父类
  • 字节输入流的方法,都是读取的方法:read
    • int read() 读取单个字节
    • int read(byte[] b) 读取字节,存储在字节数组中
    • close()释放资源
  • InputStream类的子类:FileInputStream

2.2 FileInputStream读取文件(非常重要)

  • FileInputStream构造器

    • FileInputStream(File file) File对象的路径是文件
    • FileInputStream(String filename) 字符串路径文件
    • 构造方法中对象:字节输入流读取的数据源
  • 读取单个字节

    /**
     * int read() 读取单个字节
     * 将返回读取到的字节,读取到文件末尾返回 -1
     */
    public static void readByte()throws IOException {
        //创建字节输入流对象,构造方法,传递字符串文件名 数据源
        FileInputStream fis = new FileInputStream("e:/haha.txt");
        //fis输入对象的方法read,读取单个字节
        //使用循环读取,结束就是read()返回-1,循环结束
        //定义变量,保存read()方法的返回值
        int i = 0;
        while ( (i = fis.read())  != -1 ){
            System.out.print((char) i);
        }
        fis.close();
    }
  • 读取字节存储数组中

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bOXSorbI-1683640554224)(imgs\05151.png)]

   /**
     * int read(byte[] b) 读取字节,存储在字节数组中
     * read()方法的返回值:
     *   返回read()方法每次读取到的字节个数
     *   流末尾,返回-1
     */
    public static void readByteArray()throws IOException{
        //创建字节输入流对象,构造方法,传递字符串文件名 数据源
        FileInputStream fis = new FileInputStream("e:/haha.txt");
        //定义字节数组,数组长度:建议写1024整数倍
        //1024字节,1KB,1MB
        byte[] bytes = new byte[1024];
        //定义变量,接收 read()读取方法的返回值
        int i = 0;
        while ( (i = fis.read(bytes)) != -1){
            //直接输出数组,不行,读到几个字节,就输出几个字节
            System.out.print(new String(bytes,0,i));
        }
        fis.close();
    }

第三章 文件复制(重要应用)

3.1 字节流读写单个字节方式

   /**
     * 数据源: c:/a.avi
     * 数据目的:e:/a.avi
     * FileInputStream 读取数据源
     * FileOutputStream 写入数据目的
     * 读取一个字节,写入一个字节
     */
    public static void copy_1(){
        //定义好需要的流对象
        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
            //建立字节输入流对象,绑定数据源
            fis = new FileInputStream("c:/a.avi");
            //建立字节输出流对象,绑定数据目的
            fos = new FileOutputStream("e:/a.avi");
            //循环读写字节
            int i = 0;
            //read方法读取1个字节
            while ( (i = fis.read()) != -1){
                //写入1个字节
                fos.write(i);
            }
        }catch (IOException ex){
            ex.printStackTrace();
        }finally {
            if (fis != null)
                try {
                    fis.close();
                }catch (IOException ex){}

            if (fos != null)
                try {
                    fos.close();
                }catch (IOException ex){}
        }
    }

3.2 字节流读写字节数组方式

 /**
     * 数据源: c:/a.avi
     * 数据目的:e:/a.avi
     * FileInputStream 读取数据源
     * FileOutputStream 写入数据目的
     * 读取一个字节数组,写入一个字节字节数组
     */
    public static void copy_2(){
        //定义好需要的流对象
        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
            //建立字节输入流对象,绑定数据源
            fis = new FileInputStream("c:/a.avi");
            //建立字节输出流对象,绑定数据目的
            fos = new FileOutputStream("e:/a.avi");
            //循环读写字节
            int i = 0;
            //定义字节数组
            byte[] bytes = new byte[1024];
            //read方法读取字节,保存数组中
            while ( (i = fis.read(bytes)) != -1){
                //写入字节数组,0索引开始,读取到几个,写入几个
                fos.write(bytes,0,i);
            }
        }catch (IOException ex){
            ex.printStackTrace();
        }finally {
            if (fis != null)
                try {
                    fis.close();
                }catch (IOException ex){}

            if (fos != null)
                try {
                    fos.close();
                }catch (IOException ex){}
        }
    }

3.3 字节流缓冲流

  • java.io.BufferedOutputStream 字节输出流缓冲区流

    • BufferedOutputStream继承OutputStream,本质上也是一个字节输出流

    • BufferedOutputStream构造方法:必须传递字节输出流

    • BufferedOutputStream(OutputStream out),能传递的流只有FileOutputStream

    • 对于缓冲流:构造方法传递哪个流,就会提高哪个流的效率

  • java.io.BufferedInputStream 字节输入流缓冲区流

    • BufferedInputStream继承InputStream,本质上也是一个字节输入流

    • BufferedInputStream构造方法:必须传递字节输入流

    • BufferedInputStream(InputStream in),能传递的流只有FileInputStream

    • 对于缓冲流:构造方法传递哪个流,就会提高哪个流的效率

    /**
     *
     *  数据源: c:/a.avi
     *  数据目的:e:/a.avi
     *  FileInputStream 读取数据源
     *  FileOutputStream 写入数据目的
     *  BufferedInputStream 缓冲流 提高 FileInputStream 的读取速度
     *  BufferedOutputStream 缓冲流 提高 FileOutputStream 的写入速度
     */
    public static void copy_3(){
        //定义缓冲区流对象
        BufferedOutputStream bos = null;
        BufferedInputStream bis = null;
        try{
            //建立字节输出流缓冲区流对象,构造方法,传递字节输出流
            bos = new BufferedOutputStream( new FileOutputStream("e:/a.avi") );
            //建立字节输入流缓冲区流对象,构造方法,传递字节输入流
            bis = new BufferedInputStream( new FileInputStream("c:/a.avi") );
            int i = 0 ;
            byte[] bytes = new byte[1024];
            while ( (i = bis.read(bytes)) != -1){
                bos.write(bytes,0,i);
            }
        }catch (IOException ex){
            ex.printStackTrace();
        }finally {
            if (bos != null) {
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            if (bis != null) {
                try {
                    bis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

第四章 字符流

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-57jjOWDH-1683640554226)(imgs\05152.png)]

4.1 Writer类

  • java.io.Writer类:所有字符输出流的顶级父类
    • 可以写入文本文件数据:写入数据的方法 write
    • write(int c) 写入单个字符
    • write(char[] ch) 写入字符数组
    • write(char[] ch ,int off ,int len) 写入字符数组一部分,开始索引,写入个数
    • write(String s) 写入一个字符串
    • flush() 刷新该流的缓冲

4.2 OutputStreamWriter类(非常重要)

  • OutputStreamWriter:字符输出流,继承Writer

  • OutputStreamWriter流:是字符流通向字节流的桥梁

    • 可以将字符转成字节流

    • OutputStreamWriter又称为转换流

    • 字符流 = 字节流 + 编码表构成

  • OutputStreamWriter构造方法(必须传递字节输出流)

 /**
     * 字符输出流 OutputStreamWriter 写文本文件
     * 指定编码表,GBK
     * 在 OutputStreamWriter的构造方法,第二个参数,写编码表名
     */
    public static void writeGBK()throws IOException{
        //创建字节输出流,绑定文件数据目的
        FileOutputStream fos = new FileOutputStream("e:/gbk.txt");
        //转换流对象,构造方法传递字节输出流,指定使用GBK编码表
        OutputStreamWriter osw = new OutputStreamWriter(fos,"GBK");
        osw.write("你好");
        //osw.flush();
        osw.close();
    }

    /**
     * 字符输出流 OutputStreamWriter 写文本文件
     * 平台默认编码表写入文本
     * 平台就是操作系统(中文版操作系统:默认编码表 GBK)
     * 字符流写数据,要刷新,方法flush
     * close()关闭流,但是要先刷新
     * 建议写一次刷新一次
     * IDEA干的,在JVM启动的时候,添加了一个参数,将编码表改为UTF-8
     * -Dfile.encoding=UTF-8
     */
    public static void writeUTF()throws IOException {
        //创建字节输出流,绑定文件数据目的
        FileOutputStream fos = new FileOutputStream("e:/utf.txt");
        //转换流对象,构造方法传递字节输出流
        OutputStreamWriter osw = new OutputStreamWriter(fos);
        osw.write("你好");
        //osw.flush();
        osw.close();
    }

4.3 Reader类

  • java.io.Reader类:所有字符输入流的顶级父类
    • 可以读取文本文件数据:读取数据的方法 read
    • int read() 读取单个字符
    • int read(char[] ch) 读取字符,存储数组中

字符输入流,不能直接读取字符串

4.4 InputStreamReader(非常重要)

  • java.io.InputStreamReader 类:继承Reader,字符输入流

    • 可以读取文本类型的数据
    • InputStreamReader类,是字节流通向字符流的桥梁
    • 字节转成字符流
  • InputStreamReader构造方法(必须传递字节输入流)下课休息:16:08回

/**
     * InputStreamReader读取gbk文件
     * InputStreamReader构造方法的第二个参数,传递编码表
     */
    public static void readGBK()throws IOException{
        //创建字节流对象,绑定数据源文件
        FileInputStream fis = new FileInputStream("e:/gbk.txt");
        //创建转换流对象,构造方法传递字节输入流,构造方法的第二个参数,传递编码表
        InputStreamReader isr = new InputStreamReader(fis,"gbk");
        //字符数组
        char[] ch = new char[1024];
        int i = 0; //保存输入流read方法返回值
        while ( (i = isr.read(ch)) !=-1){
            //输出数组,数组转成字符串输出
            System.out.print(new String(ch,0,i));
        }
        isr.close();
    }


    /**
     *  InputStreamReader读取utf文件
     *  IDEA的开发环境中,使用默认编码表utf-8
     */
    public static void readUTF()throws IOException {
        //创建字节流对象,绑定数据源文件
        FileInputStream fis = new FileInputStream("e:/utf.txt");
        //创建转换流对象,构造方法传递字节输入流
        InputStreamReader isr = new InputStreamReader(fis);
        //字符数组
        char[] ch = new char[1024];
        int i = 0; //保存输入流read方法返回值
        while ( (i = isr.read(ch)) !=-1){
            //输出数组,数组转成字符串输出
            System.out.print(new String(ch,0,i));
        }
        isr.close();
    }

4.5 字符流操作的便捷类

  • java.io.FileWriter 字符输出流
    • 继承转换流OutputStreamWriter
    • FileWriter构造方法,直接传递字符串文件名即可
    • 只能使用默认的编码写入数据,不能指定编码表
  • java.io.FileReader 字符输入流
    • 继承转换流InputStreamReader
    • FileReader构造方法,直接传递字符串文件名
    • 只能使用默认的编码写入数据,不能指定编码表
 /**
     * FileReader类 读取文本文件
     */
    public static void readFile()throws IOException{
        //创建字符输入流便捷类,构造方法直接传递文件名
        FileReader fr = new FileReader("e:/heihei.txt");
        int i = 0;
        char[] ch = new char[1024];
        while ( (i = fr.read(ch)) != -1){
            System.out.print(new String(ch,0,i));
        }
        fr.close();
    }

    /**
     * FileWriter类 写文本文件
     * IDEA开发环境,默认编码表UTF-8
     */
    public static void writeFile()throws IOException {
        //创建便捷类对象,构造直接写文件名
        FileWriter fw = new FileWriter("e:/heihei.txt");
        fw.write("你好,我好,大家好!!");
        fw.close();
    }

4.6 BufferedWriter

  • java.io.BufferedWriter:字符输出流缓冲区流
    • BufferedWriter继承Writer
    • BufferedWriter构造方法中,必须传递字符输出流
    • void newLine() 写入换行,平台无惯性
      • 安装的JVM是Windows版本的,newLine()方法里面写是 \r\n
      • 安装的JVM是Linux版本的,newLine()方法里面写是 \n
  /**
     * BufferedWriter类的方法newLine()实现换行,平台无关性
     */
    public static void write()throws IOException {
        //创建字符输出流便捷类
        FileWriter fw = new FileWriter("e:/line.txt");
        //创建字符输出流缓冲区对象,构造方法中,传递字符输出流
        BufferedWriter bfw = new BufferedWriter(fw);
        bfw.write("第一行");
        bfw.newLine();
        bfw.flush();
        bfw.write("第二行");
        bfw.newLine();
        bfw.flush();
        bfw.write("第三行");
        bfw.flush();
        bfw.close();
    }

4.7 BufferedReader

  • java.io.BufferedReader:字符输入流缓冲区流
    • BufferedReader继承Reader
    • BufferedReader构造方法中,必须传递字符输入流
    • String readLine() 读取文本一行
      • 读取文本一行,返回字符串,不包含换行符号
      • 读取到流的末尾,返回null
    public static void read() throws IOException {
        //创建字符输入流对象
        FileReader fr = new FileReader("e:/line.txt");
        //创建字符输入流缓冲区对象,构造方法,传递字符输入流
        BufferedReader bfr = new BufferedReader(fr);
        //定义字符串,保存读取到的文本行
        String line = null;
        while ( (line = bfr.readLine()) != null ){
            System.out.println(line);
        }
        bfr.close();
    }

4.8 字符流复制文本文件

字符流复制文本文件:错误应用,根本就不能做

第五章 Properties集合

Properties类的方法:load方法 (字节输入流),集合IO关联使用,字节输入流读取文件,文件中保存数据加载到集合中。IO流对象读取的文件,必须写键值对(不能写中文)

/**
 * 集合IO关联使用
 * 字节输入流读取文件 config.properties
 * 文件中的键值对,存储集合Properties
 *
 * 集合中的数据,不再是开发人员在源码中写好的
 * 而是通过文件获取的(文本)
 */
public class PropertiesDemo {
    public static void main(String[] args)throws IOException {
        //字节输入流,读取 config.properties
        //文件的存储位置到当前的模块中,直接写模块名
        FileInputStream fis = new FileInputStream("day23/config.properties");
        //创建集合Properties
        Properties prop = new Properties();
        //集合对象方法load,传递字节输出流
        prop.load(fis);
        fis.close();
        System.out.println("prop = " + prop);
    }
}
  • config.properties
name=zhangsan
age=21
#address=beijingshi
email=1234567@qq.com

第六章 对象序列化(非常重要)

6.1 对象序列化介绍

  • 对象的序列化:就是写对象
  • 对象的反序列化:就是读对象

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oBnpBKIs-1683640554226)(imgs\05153.png)]

6.2 对象的序列化

  • java.io.ObjectOutputStream类:写对象的字节输出流
    • 继承OutputStream
    • 构造方法,必须传递字节输出流:FileOutputStream
    • 序列化方法,写入对象的方法 writeObject(Object obj)
 /**
     * 对象序列化
     * ObjectOutputStream
     */
    public static void writeObj()throws IOException {
        //创建字节输出流,绑定目的文件
        FileOutputStream fos = new FileOutputStream("e:/person.txt");
        //创建对象的序列化流
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        //写入对象
        Person person = new Person("张三",20);
        oos.writeObject(person);

        oos.close();
    }

6.3 对象的反序列化

  • java.io.ObjectInputStream:读取对象的字节输入流
    • 继承InputStream
    • ObjectInputStream 构造方法传递字节输入流:FileInputStream
    • 反序列化的方法,读取对象的方法 Object readObject()
    /**
     * 对象反序列化
     * ObjectInputStream
     * ClassNotFoundException异常:类找不到异常
     *   反序列化必须有class文件支持
     */
    public static void readObj()throws IOException,ClassNotFoundException{
        //创建字节输入流,绑定序列化文件
        FileInputStream fis = new FileInputStream("e:/person.txt");
        //创建对象的反序列化流,构造方法,传递字节输入流
        ObjectInputStream ois = new ObjectInputStream(fis);
        //读取对象
        Object obj =  ois.readObject();
        System.out.println("obj = " + obj);
        ois.close();
    }

6.4 序列化的异常

目前程序可以正常的反序列化成功,修改成员的修饰符:

private  String name; //原始,修改为public
public  String name;

不进行对象的序列化,不重新写对象,直接进行反序列化,直接读取:

Exception in thread "main" java.io.InvalidClassException: com.atguigu.object.Person; local class incompatible: stream classdesc serialVersionUID = -5016735515273745116, local class serialVersionUID = -6237413986566242958
	at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:699)
	at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1885)
	at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1751)
	at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2042)
	at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1573)
	at java.io.ObjectInputStream.readObject(ObjectInputStream.java:431)
	at com.atguigu.object.ObjectStreamDemo.readObj(ObjectStreamDemo.java:25)
	at com.atguigu.object.ObjectStreamDemo.main(ObjectStreamDemo.java:10)

这个异常,序列号冲突异常

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7kwet7UK-1683640554227)(imgs\05154.png)]

即使我们改变了成员的修饰符,但是不影响后期的功能使用,不序列化,直接可以反序列化成功

不让javac为我们计算序列号,我们要自定义序列号,只要我们写序列号了,javac就不计算了

static final long serialVersionUID = 20000L;

Java基础知识笔记通常会涵盖以下几个核心主题: 1. Java概述:包括Java的历史、平台无关性、JVMJava Virtual Machine)的作用和Java的核心API(如java.lang包)。 2. 数据类型和变量:基本数据类型(如int, float, char等)、引用类型(如String, Object),以及变量的声明、初始化和作用域。 3. 控制结构:条件语句(if-else, switch)、循环(for, while, do-while)、异常处理(try-catch-finally)。 4. 类和对象:封装、继承和多态的概念,类的定义、构造函数和析构函数,以及实例化对象和方法调用。 5. 面向对象编程:接口、抽象类和它们的区别,以及设计模式的基本概念。 6. 数组和集合:数组的定义、操作,以及ArrayList、LinkedList、HashMap等常用集合框架的使用。 7. 输入输出流:文件I/O、标准输入输出流(System.in/out)的处理。 8. 方法和函数:静态方法、重载方法、递归等。 9. 异常处理:异常的抛出、捕获和处理机制。 10. IO流和网络编程:Socket编程、HTTP请求等。 创建一个Markdown格式的笔记,可能会包括标题、列表项、代码示例和注释。例如: ```markdown # Java基础笔记 ## 1. Java简介 - Java语言特点: 平台无关性、垃圾回收机制 - JVM: 负责执行Java字节码 ## 2. 数据类型 - int, double, String等基本类型 - ```java // 声明并初始化一个整型变量 int num = 10; ``` ## 3. 控制结构 - if-else: 条件判断 - ```java if (num > 0) { System.out.println("Positive"); } ``` ... ### 附录:常用类库 - java.util: 集合框架 - java.io: I/O流处理 ``` FileInputStream fileIn = new FileInputStream("file.txt"); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值