JAVA期末速成(下)

发布于:2024-12-20 ⋅ 阅读:(17) ⋅ 点赞:(0)

目录

一:IO流(输入输出流)

1:File类(位于java.io包下)

1.1:File的创建

1.2:获取File类信息的方法

1.3:文件的 递归 删除操作(不走回收站) 

2:字节流

        2.1:字节流概述

        2.2:字节输入流 FileInputStream

2.3:字节输出流FileOutputStream

2.4:使用字节流进行文件的复制操作

3:字符流

        3.1:字符流概述

       3.2:Reader类和Writer类的核心方法

(1) Reader

(2) Writer

4:缓存流

        4.1:缓冲流概念

        4.2:主要实现类:

二:多线程

1:认识线程

2:线程的创建

2.1:继承Thread类

2.2:实现Runnable接口

2.3:匿名内部类实现Runnable接口

2.4:使用Lambda表达式创建线程

3:Thread类常用API

3.1:常见构造方法

3.2:线程状态方法 

3.3:线程的生命周期

3.4:关于synchronized关键字解决线程共享问题


一:IO流(输入输出流)

1:File类(位于java.io包下)

1.1:File的创建

        常用构造方法

                文件绝对路径在idea的位置:右键文件,选择Copy Path,获取绝对路径

这些构造方法均未声明异常 

        

File(File parent, String child)
          根据 parent 抽象路径名和 child 路径名字符串创建一个新 File 实例。
File(String pathname)
          通过将给定路径名字符串转换为抽象路径名来创建一个新 File 实例。 
File(String parent, String child)
          根据 parent 路径名字符串和 child 路径名字符串创建一个新 File 实例。

        

import java.io.File;

public class FileTest {
    public static void main(String[] args) {
        //方式1 绝对路径创建
        File file1 = new File("D:\\IDEA\\hello.txt");

        //方式二 相对路径创建
        File file2 = new File("src\\hello.txt");

        //方式三  根据父类路径下创建
        File file3 = new File("D:\\IDEA", "hello.txt");

    }
}

        


1.2:获取File类信息的方法

        使用:对象名. 方法

方法摘要
 boolean createNewFile()
          当且仅当不存在具有此抽象路径名指定名称的文件时,不可分地创建一个新的空文件。
 boolean delete()
          删除此抽象路径名表示的文件或目录。
 void deleteOnExit()
          在虚拟机终止时,请求删除此抽象路径名表示的文件或目录。
 boolean equals(Object obj)
          测试此抽象路径名与给定对象是否相等。
 boolean exists()
          测试此抽象路径名表示的文件或目录是否存在。
 File getAbsoluteFile()
          返回此抽象路径名的绝对路径名形式。
 String getAbsolutePath()
          返回此抽象路径名的绝对路径名字符串
 String getName()
          返回由此抽象路径名表示的文件或目录的名称。
 String getParent()
          返回此抽象路径名父目录的路径名字符串;如果此路径名没有指定父目录,则返回 null
 File getParentFile()
          返回此抽象路径名父目录的抽象路径名;如果此路径名没有指定父目录,则返回 null
 String getPath()
          将此抽象路径名转换为一个路径名字符串。
 boolean isAbsolute()
          测试此抽象路径名是否为绝对路径名。
 boolean isDirectory()
          测试此抽象路径名表示的文件是否是一个目录。
 boolean isFile()
          测试此抽象路径名表示的文件是否是一个标准文件。
 long length()
          返回由此抽象路径名表示的文件的长度。
 String[] list()
          返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中的文件和目录。
 File[] listFiles()
          返回一个抽象路径名数组,这些路径名表示此抽象路径名表示的目录中的文件。

import java.io.File;  
import java.io.IOException;  

public class FileExample {  
    public static void main(String[] args) {  
        // 创建一个 File 对象  
        File file = new File("example.txt");  

        // 创建新文件  
        try {  
            if (file.createNewFile()) {  //如果为true 则在相对路径下创建
                System.out.println("文件已创建: " + file.getName()); //获取文件名 
            } else {  
                System.out.println("文件已存在。");  
            }  
        } catch (IOException e) {  
            System.out.println("发生了一个错误。");  
            e.printStackTrace();  
        }  

        // 获取文件信息  
        System.out.println("绝对路径: " + file.getAbsolutePath());  
        System.out.println("文件大小: " + file.length() + " 字节");  

        // 删除文件  
        if (file.delete()) {  
            System.out.println("文件已删除。");  
        } else {  
            System.out.println("删除文件失败。");  
        }  
    }  
}


1.3:文件的 递归 删除操作(不走回收站) 

                为什么不能直接delete(),因为如果是目录下还存在文件,无法执行此方法。

                下面示例包含了对文件数组的增强for遍历(listFiles()方法),与集合不同的是,输入输出流可以在增强for循环内进行删除操作。 

import java.io.File;  

public class FileDeletion {  

    public static void main(String[] args) {  
        // 指定要删除的目录路径  
        File directoryToDelete = new File("path/to/directory");  

        // 调用递归删除方法  
        if (deleteDirectory(directoryToDelete)) {  

            System.out.println("目录及其内容已成功删除: " + directoryToDelete.getAbsolutePath());  

        } else {  

            System.out.println("删除操作失败。");  

        }  
    }  



    // 递归删除文件和目录  
    public static boolean deleteDirectory(File directory) {  

        // 确保传入的是一个目录  
        if (!directory.exists()) {  

            System.out.println("目录不存在: " + directory.getAbsolutePath()); 
 
            return false;  
        }  
        
        if (directory.isDirectory()) {//如果是目录
  
            // 获取目录中的所有文件和子目录  

            File[] files = directory.listFiles();  //返回文件数组
            if (files != null) {  
                for (File file : files) {  

                    // 递归删除子文件和子目录  
                    if (file.isDirectory()) {  

                        deleteDirectory(file); // 递归调用  

                    } else { 
 
                        // 删除文件  
                        if (file.delete()) {  

                            System.out.println("删除文件: " + file.getAbsolutePath()); 
 
                        } else {  

                            System.out.println("删除文件失败: " + file.getAbsolutePath());  
                        }  
                    }  
                }  
            }  
        }  

        // 删除目录本身  
        return directory.delete();  
    }  
}

2:字节流

        2.1:字节流概述

        以字节为单位,适用于处理二进制数据(如图像、音频和所有文件类型)。

        主要接口 输入流 InputStream 输出流 OutputStream。

        他们的主要实现类 :FileInputStream 和 FileOutputStream

        2.2:字节输入流 FileInputStream

构造方法摘要
FileInputStream(File file)
          通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的 File 对象 file 指定。   ***会抛出异常FileNotFoundException***
FileInputStream(String name)
          通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的路径名 name 指定。


方法摘要
 void close()
          关闭此文件输入流并释放与此流有关的所有系统资源。
 int read()
          从此输入流中读取一个数据字节。返回读取的字节(范围:0-255)或 -1 表示到达流的末尾。
 int read(byte[] b)
          从此输入流中将最多 b.length 个字节的数据读入一个 byte 数组中。
 int read(byte[] b, int off, int len)
          从此输入流中将最多 len 个字节的数据读入一个 byte 数组中。

 示例,现目录下有一个hello.txt文件,内容是:helloworld,使用字节输入流依次读此文件。

import java.io.*;

public class FileTest {
    public static void main(String[] args) {
        FileInputStream fis=null;
        //创建字节输入流
        try {
            fis= new FileInputStream("csdn/src/hello.txt");

            int len1 = fis.read();

            System.out.println(len1+"  "+(char)(len1));
            
            int len2 = fis.read();
            System.out.println((char)(len2));
        } catch (IOException e) {
            e.printStackTrace();
        } finally {//用于关闭流资源
            try {
                fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
     }

}


        // 结果是
        104  h
        e

           


使用字节输入流循环读取文件。 

import java.io.*;

public class FileTest {
    public static void main(String[] args) {
        FileInputStream fis=null;
        //创建字节输入流
        try {
            fis= new FileInputStream("csdn/src/hello.txt");
            int len;
            while((len=fis.read())!=-1){
                //使用循环挨个读取 并打印
                System.out.print((char)len+" ");
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {//用于关闭流资源
            try {
                fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
     }

}
        //结果为:h e l l o w o r l d 


        使用字节输入流一次读取一个字节数组。

import java.io.*;

public class FileTest {
    public static void main(String[] args) {
        FileInputStream fis=null;
        byte[] bytes = new byte[10];
        //创建字节输入流
        try {
            fis= new FileInputStream("csdn/src/hello.txt");
            
            fis.read(bytes);//把helloworld 共十个字节读入bytes数组中
            
            for (byte aByte : bytes) {
                //循环遍历输出 元素
                System.out.print((char) aByte+" ");
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {//用于关闭流资源
            try {
                fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
     }
}
  //结果 h e l l o w o r l d


2.3:字节输出流FileOutputStream

构造方法摘要
FileOutputStream(File file)
          创建一个向指定 File 对象表示的文件中写入数据的文件输出流。
FileOutputStream(File file, boolean append)
          创建一个向指定 File 对象表示的文件中写入数据的文件输出流。
构造器后面的布尔类型代表此文件可以追加输出
FileOutputStream(String name)
          创建一个向具有指定名称的文件中写入数据的输出文件流。
FileOutputStream(String name, boolean append)
          创建一个向具有指定 name 的文件中写入数据的输出文件流。

方法摘要
 void close()
          关闭此文件输出流并释放与此流有关的所有系统资源。
 void write(byte[] b)
          将 b.length 个字节从指定 byte 数组写入此文件输出流中。
 void write(byte[] b, int off, int len)
          将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此文件输出流。
 void write(int b)
          将指定字节写入此文件输出流。

往文件中添加单个字符。


import java.io.*;

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

            //1 创建输出流对象,并指定在hello.txt文件中写出
        FileOutputStream fos = new FileOutputStream("csdn/src/hello.txt");

        //往文件中写一个字符a

        fos.write(97);//a的ASCII值



        //释放流资源
        fos.close();

    }
}
  //结果文件为a


往文件中写出字符串。 

    import java.io.*;

    public class FileTest {
        public static void main(String[] args) throws IOException {//往外抛异常

                //1 创建输出流对象,并指定在hello.txt文件中写出
            FileOutputStream fos = new FileOutputStream("csdn/src/hello.txt");

            //往文件中写一个字符串

            String s="helloworld";

            //转化为字节数组
            byte[] bytes = s.getBytes();

            fos.write(bytes);//写一个字节数组
            

            //释放流资源
            fos.close();

        }
    }
      //结果文件为 helloworld

在上述结果下,继续在后面添加“你好世界!”。

    import java.io.*;

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

                //1 创建输出流对象,并指定在hello.txt文件中写出
            FileOutputStream fos = new FileOutputStream("csdn/src/hello.txt",true);

            //往文件中写一个字符串

            String s="你好世界!";

            //转化为字节数组
            byte[] bytes = s.getBytes();

            fos.write(bytes);//写一个字节数组


            //释放流资源
            fos.close();

        }
    }
      //结果文件为 helloworld你好世界!


         从字节数组的特定位置写特定个字节

import java.io.*;

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

                //1 创建输出流对象,并指定在hello.txt文件中写出
            FileOutputStream fos = new FileOutputStream("csdn/src/hello.txt");

            //往文件中写一个字符串

            String s="hello!";

            //转化为字节数组
            byte[] bytes = s.getBytes();

            fos.write(bytes,0,2);//从字节数组的0索引开始写2个字节


            //释放流资源
            fos.close();

        }
    }
      //结果文件为 he

2.4:使用字节流进行文件的复制操作


import java.io.*;
public class FileTest {
    public static void main(String[] args) throws IOException {
            String sourceFile = "source.txt"; // 源文件路径  

            String destinationFile = "destination.txt"; // 目标文件路径  

            FileInputStream fis = new FileInputStream(sourceFile);//创建输入流读取源文件
            
            FileOutputStream fos = new FileOutputStream(destinationFile);//创建输出流写出文件

                byte[] buffer = new byte[1024]; // 缓冲区 ,一次读一个字节数组 
        
                int len;
                // 从源文件读取数据并写入目标文件  
                while ((len = fis.read(buffer)) != -1) {
                    
                    fos.write(buffer, 0, len); //读到多少个,往文件写出len个字节
                }
    } 
}

3:字符流

        3.1:字符流概述

        字符流是处理字符(文本)数据的流,旨在支持字符数据的高效读写。Java中的字符流主要包含两种类型:ReaderWriter

       3.2:Reader类和Writer类的核心方法

(1) Reader

构造方法摘要
FileReader(File file)
          在给定从中读取数据的 File 的情况下创建一个新 FileReader。
FileReader(String fileName)
          在给定从中读取数据的文件名的情况下创建一个新 FileReader。
  • read(): 读取单个字符。
  • read(char[] cbuf): 将字符读入字符数组。
  • readLine(): 从输入流读取一行字符(在BufferedReader中使用)。
(2) Writer

构造方法摘要
FileWriter(File file)
          根据给定的 File 对象构造一个 FileWriter 对象。
FileWriter(File file, boolean append)
          根据给定的 File 对象构造一个 FileWriter 对象。
FileWriter(String fileName)
          根据给定的文件名构造一个 FileWriter 对象。
FileWriter(String fileName, boolean append)
          根据给定的文件名以及指示是否附加写入数据的 boolean 值来构造 FileWriter 对象。
  • write(int c): 写入单个字符。
  • write(char[] cbuf): 写入字符数组。
  • write(String str): 写入字符串。  
  • flush(): 刷新输出流,确保所有数据都被写入。
  • close(): 关闭流,释放资源。

示例代码:使用 FileReader 和 FileWriter进行文件复制

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

public class FileTest {
    public static void main(String[] args) {
        String sourceFile = "source.txt";          // 源文件路径  
        String destinationFile = "destination.txt"; // 目标文件路径  

        // 使用 FileReader 读取字符文件  
        try {
            FileReader fr = new FileReader(sourceFile);
            FileWriter fw = new FileWriter(destinationFile);
            int character; // 用于存放每次读取的字符  
            // 逐个字符读取源文件并写入目标文件  
            while ((character = fr.read()) != -1) {
                fw.write(character); // 写入目标文件  
            }
            System.out.println("文件复制成功!");
        } catch (IOException e) {
            System.err.println("文件复制失败: " + e.getMessage());
        }
    }
}

4:缓存流

        4.1:缓冲流概念

缓存流在输入输出流的基础上增加了一层缓存,数据先被读取到内存中,然后再由缓存批量传输到目标位置。这样可以显著减少对磁盘或网络的直接访问次数。

        4.2:主要实现类:

  • BufferedInputStream:为字节输入流提供缓存。
  • BufferedOutputStream:为字节输出流提供缓存。
  • BufferedReader:为字符输入流提供缓存,同时还可以通过 readLine() 方法逐行读取字符串。
  • BufferedWriter:为字符输出流提供缓存,能够以字符为单位写入数据,有助于提高写入效率。


 字节缓冲流复制文件示例代码

import java.io.BufferedInputStream;  
import java.io.BufferedOutputStream;  
import java.io.FileInputStream;  
import java.io.FileOutputStream;  
import java.io.IOException;  

public class FileCopy {  

    public static void main(String[] args) {  

        // 源文件路径  
        String sourceFilePath = "path/to/source/file.txt";  

        // 目标文件路径  
        String destinationFilePath = "path/to/destination/file.txt";  

        // 调用复制文件的方法  
        copyFile(sourceFilePath, destinationFilePath);  
    }  

    public static void copyFile(String source, String destination) {
  
        // 创建流对象  
        try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(source));  
             BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destination))) {  

            // 设置一个缓冲区  
            byte[] buffer = new byte[8192]; // 8KB的缓冲区  
            int bytesRead;  

            //循环读取和写入  
            while ((bytesRead = bis.read(buffer)) != -1) {  
                bos.write(buffer, 0, bytesRead);  
            }  

            System.out.println("文件复制成功!");  

        } catch (IOException e) {  
            System.err.println("文件复制失败: " + e.getMessage());  
        }  
    }  
}

字符缓存流文件复制示例代码

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

public class CharFileCopy {  

    public static void main(String[] args) {  

        // 源文件路径  
        String sourceFilePath = "path/to/source/file.txt";  

        // 目标文件路径  
        String destinationFilePath = "path/to/destination/file.txt";  

        // 调用复制文件的方法  
        copyFile(sourceFilePath, destinationFilePath);  
    }  

    public static void copyFile(String source, String destination) {  

        // 创建流对象  
        try (BufferedReader br = new BufferedReader(new FileReader(source));  
             BufferedWriter bw = new BufferedWriter(new FileWriter(destination))) {  

            String line;  
            // 循环读取每一行并写入目标文件  
            while ((line = br.readLine()) != null) {  

                bw.write(line);  
                bw.newLine();  // 添加换行符  

            }  

            System.out.println("文件复制成功!");  

        } catch (IOException e) {  
            System.err.println("文件复制失败: " + e.getMessage());  
        }  
    }  
}

二:多线程

1:认识线程

⼀个线程就是⼀个 “执行流”. 每个线程之间都可以按照自己的代码. 多个线程之间 “同时” 执行着多份代码,main()⼀般被称为主线程(Main Thread)。

  • 进程是包含线程的. 每个进程至少有⼀个线程存在,即主线程。
  • 进程和进程之间不共享内存空间. 同⼀个进程的线程之间共享同⼀个内存空间.
  • 进程是系统分配资源的最小单位,线程是系统调度的最小单位。

2:线程的创建

2.1:继承Thread类

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

        MyThread t = new MyThread();
        t.start();//开启线程方式   对象.start() 方法

    }
}

public class MyThread extends Thread { 
    @Override
    public void run() {
        System.out.println("这⾥是线程运⾏的代码");
    }
}

2.2:实现Runnable接口

        为了克服单继承(继承了其他类不能再继承Thread类)的局限性,可以实现此接口

class MyRunnable implements Runnable {

    @Override
    public void run() {

        System.out.println("线程开启了");
    }

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

        Thread t = new Thread(new MyRunnable());

        t.start();//启动线程
    }
}

2.3:匿名内部类实现Runnable接口

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

         // 使⽤匿名类创建 Runnable ⼦类对象
        Thread t2 = new Thread(new Runnable() {

            @Override
            public void run() {

                System.out.println("开启线程");

            }
        });
        t2.start();

    }
}

2.4:使用Lambda表达式创建线程

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

        
           new Thread(() -> System.out.println("使用lambda表达式创建线程")).start();

    }
}

3:Thread类常用API

3.1:常见构造方法

构造方法摘要
Thread()
          分配新的 Thread 对象。
Thread(Runnable target)
          分配新的 Thread 对象。
Thread(Runnable target, String name)
          分配新的 Thread 对象。
Thread(String name)
          分配新的 Thread 对象。 

Thread th1 = new Thread(new MyRunnable());
Thread th2= new Thread("我的名字");
Thread th3 = new Thread(new MyRunnable(), "我的名字");
 


3.2:线程状态方法 

方法摘要
static Thread currentThread()
          返回对当前正在执行的线程对象的引用。
 long getId()
          返回该线程的标识符。
 String getName()
          返回该线程的名称。
 int getPriority()
          返回线程的优先级。
 StackTraceElement[] getStackTrace()
          返回一个表示该线程堆栈转储的堆栈跟踪元素数组。
 Thread.State getState()
          返回该线程的状态。
 void interrupt()
          中断线程。
 boolean isAlive()
          测试线程是否处于活动状态。
 boolean isInterrupted()
          测试线程是否已经中断。
 void join()
          等待该线程终止。
 void join(long millis)
          等待该线程终止的时间最长为 millis 毫秒。
 void setName(String name)
          改变线程名称,使之与参数 name 相同。
 void setPriority(int newPriority)
          更改线程的优先级。
static void sleep(long millis)
          在指定的毫秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响。
 void start()
          使该线程开始执行;Java 虚拟机调用该线程的 run 方法。
 void stop(Throwable obj)
          已过时。 该方法具有固有的不安全性。有关详细信息,请参阅 stop()。该方法的附加危险是它可用于生成目标线程未准备处理的异常(包括若没有该方法该线程不太可能抛出的已检查的异常)。有关更多信息,请参阅为何不赞成使用 Thread.stop、Thread.suspend 和 Thread.resume?
 String toString()
          返回该线程的字符串表示形式,包括线程名称、优先级和线程组。
static void yield()
          暂停当前正在执行的线程对象,并执行其他线程。
public class Test {
    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
                    for (int i = 0; i < 5; i++) {
                        try {
                            System.out.println(Thread.currentThread().getName());
                            Thread.sleep(10000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println(Thread.currentThread().getName() + ": 线程结束");
                });

        System.out.println(Thread.currentThread().getName() + ": ID: " + thread.getId());System.out.println(Thread.currentThread().getName() + ": 名称: " + thread.getName());
        System.out.println(Thread.currentThread().getName() + ": 状态: " + thread.getState());
        System.out.println(Thread.currentThread().getName() + ": 优先级: " + thread.getPriority());
        System.out.println(Thread.currentThread().getName() + ": 活着: " + thread.isAlive());System.out.println(Thread.currentThread().getName() + ": 被中断: " + thread.isInterrupted());
        thread.start();
    }
}
    


3.3:线程的生命周期

  1. 新建状态 (New): 线程被创建但尚未开始运行。
  2. 就绪状态 (Runnable): 线程可以运行并正在等待CPU的时间片。
  3. 运行状态 (Running): 线程正在执行其任务。
  4. 阻塞状态 (Blocked): 线程因等待另一个线程释放某个对象的锁而阻塞。
  5. 死亡状态 (Terminated): 线程的执行结束,无法再次启动。

3.4:关于synchronized关键字解决线程共享问题

这里以存取钱为例子

                同步方法:

class BankAccount {  

    private int balance = 0;  

    // 同步方法,确保线程安全  
    public synchronized void deposit(int amount) {  

        balance += amount;  
        System.out.println("Deposited: " + amount + ", New Balance: " + balance);  

    }  

    public synchronized void withdraw(int amount) {  

        if (balance >= amount) {  
            balance -= amount;  
            System.out.println("Withdrew: " + amount + ", New Balance: " + balance);  
        } else {  
            System.out.println("Insufficient funds for withdrawal of: " + amount);  
        }  
    }  

    public int getBalance() {  
        return balance;  
    }  
}

                同步代码块:

class BankAccount {  

    private int balance = 0;  

    public void deposit(int amount) {  

        synchronized (this) {  // 使用同步代码块  
            balance += amount;  

            System.out.println("Deposited: " + amount + ", New Balance: " + balance);  
        }  
    }  

    public void withdraw(int amount) { 
 
        synchronized (this) {  // 使用同步代码块  

            if (balance >= amount) {  
                balance -= amount;  
                System.out.println("Withdrew: " + amount + ", New Balance: " + balance);  
            } else {  
                System.out.println("Insufficient funds for withdrawal of: " + amount);  
            }  
        }  
    }  

    public int getBalance() {  
        return balance;  
    }  
}