栏目分类:
子分类:
返回
终身学习网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
终身学习网 > IT > 软件开发 > 后端开发 > Java

JavaSE - 09 IO相关操作

Java 更新时间:发布时间: 百科书网 趣学号

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录
  • 1.File类
    • 1.1 File文件操作概述
    • 1.2 File的构造方法
    • 1.3 常用的方法
    • 1.4 文件遍历
  • 2.IO流的概述
    • 2.1 IO流的概述
    • 2.2 IO流的分类
    • 2.3 IO的原理
  • 3.字节流
    • 3.1 FileOutputStream类(字节输出流)
    • 3.2 FileInputStream类(字节输入流)
    • 标准代码:文件复制操作
    • 3.3 BufferedOutputStream(高效输出流)
    • 3.4 BufferedInputStream类(高效输入流)
    • 标准代码:文件复制操作
  • 4.字符流
    • 4.1 字符流概述
    • 4.2 FileWrite类(字符输出流)
    • 4.3 FileReader类(字符输入流)
    • 标准代码:文件复制
    • 4.4 BufferedWriter(高效字符输出流)
    • 4.5 BufferedReader (高效字符输入流)
    • 标准代码:文件复制
  • 5.EMS学生管理系统案例
    • 5.1 案例描述
  • 6.字节转化流
    • 6.1 编码与解码
    • 6.2 OutputStreamWriter类
    • 6.3 InputStreamReader类
  • 7.序列化和反序列化
    • 7.1 ObjectOutputStream类(序列化)
    • 7.2 ObjectInputStream类(反序列化)
    • 7.3 序列化和反序列化的问题以及JavaBean
  • 8.Properties类


1.File类 1.1 File文件操作概述

java.io.File类:文件和文件目录路径的抽象表示形式,与平台无关

File 能新建、删除、重命名文件和目录,但 File 不能访问文件内容本身。 如果需要访问文件内容本身,则需要使用输入/输出流。 

想要在Java程序中表示一个真实存在的文件或目录,那么必须有一个File对 象,但是Java程序中的一个File对象,可能没有一个真实存在的文件或目录。

File对象可以作为参数传递给流的构造器

1.2 File的构造方法
-- 常量 
static String pathSeparator : 与系统有关的路径分隔符,为了方便,它被表示为一个字符串。 
static char pathSeparatorChar : 与系统有关的路径分隔符。 
static String separator : 与系统有关的默认名称分隔符,为了方便,它被表示为一个字符串。 
static char separatorChar : 与系统有关的默认名称分隔符。 

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

代码示例:

public class Demo01 {
    public static void main(String[] args) {
        //static String pathSeparator : 与系统有关的路径分隔符,为了方便,它被表示为一个字符串。
        System.out.println("File.pathSeparator = " + File.pathSeparator);
        //static char pathSeparatorChar : 与系统有关的路径分隔符。
        System.out.println("File.pathSeparatorChar = " + File.pathSeparatorChar);
        //static String separator : 与系统有关的默认名称分隔符,为了方便,它被表示为一个字符串。
        System.out.println("File.separator = " + File.separator);
        //static char separatorChar : 与系统有关的默认名称分隔符。
        System.out.println("File.separatorChar = " + File.separatorChar);

        //File(String pathname): 通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例
        File f1 = new File("E:\itcast\java.txt");
        System.out.println(f1);

        //File(String parent, String child): 从父路径名字符串和子路径名字符串创建新的 File实例
        File f2 = new File("E:\itcast","java.txt");
        System.out.println(f2);

        //File(File parent, String child): 从父抽象路径名和子路径名字符串创建新的 File实例
        File f3 = new File("E:\itcast");
        File f4 = new File(f3,"java.txt");
        System.out.println(f4);
    }
}

相对路径、绝对路径

路径 : 找到文件/文件夹
绝对路径 : 绝对能找到文件/文件夹的路径叫绝对路径 -> 文件/文件夹的完整路径
	特点 : 以盘符开头
	优势 : 哪里的文件都可以找到
相对路径 : 对绝对路径的一种简化书写方式
	相对路径中的参照物 : I/O知识体系中 -> 项目(Project)的根目录
	优势 : 是绝对路径的一种简化书写
	弊端 : 不能表示硬盘中所有的位置 (相对路径必须往参照物的内部路径去寻找)
	特点 : 没有以盘符开头
1.3 常用的方法
--创建相关的操作
    boolean mkdir() : 创建一个文件目录
    boolean mkdirs() : 创建多级文件目录(推荐使用)
    boolean createNewFile() : 创建一个文件

-- 删除相关操作
    boolean delete() : 删除文件/文件目录(谨慎使用)

-- 获取相关操作
    long length() : 获取文件大小
    String getName() : 获取文件/目录名称
    
    File getAbsoluteFile() : 获取文件/目录的绝对路径,返回File对象
    String getAbsolutePath() : 获取文件/目录的绝对路径,返回String类型字符串
    
    String getParent() : 获取文件/目录的父级路径,返回String类型字符串
    File getParentFile() : 获取文件/目录的父级路径,返回File对象
    
    long lastModified() : 获取file对象指向的文件/文件夹的最后修改时间 -> 时间单位是毫秒
    String getPath() : 获取File对象的路径 (如何创建的File对象,路径就是什么样子的) //File类中toString的源码

-- 判断功能
	boolean exists() : 判断file对象指向的文件/文件夹是否存在
	boolean isDirectory() : 判断File对象指向的是否是一个文件夹
	boolean isFile() : 判断File对象指向的是否是一个文件
	boolean isAbsolute() : 判断创建File对象时是否使用的是绝对路径
	boolean isHidden() : 判断File对象指向的文件/文件夹 是否是隐藏的

-- 文件遍历的方法
    File[] listFiles() : 返回一个抽象路径名数组,这些路径名表示此抽象路径名表示的目录中的文件。
    File[] listFiles(FileFilter filter) : 返回抽象路径名数组,这些路径名表示此抽象路径名表示的目录中满足指定过滤器的文件和目录。

代码演示:

public class Demo02 {
    public static void main(String[] args) throws IOException {
        // 创建File对象
        File file = new File("\JavaSE_09 IO\test");

        //--创建相关的操作
        //    boolean mkdir() : 创建一个文件目录
        File file1 = new File("\JavaSE_09 IO\test\aaa");
        boolean mkdir = file1.mkdir();
        System.out.println("mkdir = " + mkdir);

        //    boolean mkdirs() : 创建多级文件目录(推荐使用)
        File file2 = new File("\JavaSE_09 IO\test\bbb\ccc");
        boolean mkdirs = file2.mkdirs();
        System.out.println("mkdirs = " + mkdirs);

        //    boolean createNewFile() : 创建一个文件
        File file3 = new File("\JavaSE_09 IO\test\a.txt");
        boolean newFile = file3.createNewFile();
        System.out.println("newFile = " + newFile);
        System.out.println("================================================================");

        //-- 获取相关操作
        //    long length() : 获取文件大小
        System.out.println("file3.length() = " + file3.length());
        //    String getName() : 获取文件/目录名称
        System.out.println("file3.getName() = " + file3.getName());
        //    File getAbsoluteFile() : 获取文件/目录的绝对路径,返回File对象
        System.out.println("file3.getAbsoluteFile() = " + file3.getAbsoluteFile());
        //    String getAbsolutePath() : 获取文件/目录的绝对路径,返回String类型字符串
        System.out.println("file3.getAbsolutePath() = " + file3.getAbsolutePath());
        //    String getParent() : 获取文件/目录的父级路径,返回String类型字符串
        System.out.println("file3.getParent() = " + file3.getParent());
        //    File getParentFile() : 获取文件/目录的父级路径,返回File对象
        System.out.println("file3.getParentFile() = " + file3.getParentFile());
        //    long lastModified() : 获取file对象指向的文件/文件夹的最后修改时间 -> 时间单位是毫秒
        System.out.println("file3.lastModified() = " + file3.lastModified());
        //    String getPath() : 获取File对象的路径 (如何创建的File对象,路径就是什么样子的) //File类中toString的源码
        System.out.println("file3.getPath() = " + file3.getPath());
        System.out.println("================================================================");


        //-- 判断功能
        //	boolean exists() : 判断file对象指向的文件/文件夹是否存在
        System.out.println("file3.exists() = " + file3.exists());
        //	boolean isDirectory() : 判断File对象指向的是否是一个文件夹
        System.out.println("file3.isDirectory() = " + file3.isDirectory());
        //	boolean isFile() : 判断File对象指向的是否是一个文件
        System.out.println("file3.isFile() = " + file3.isFile());
        //	boolean isAbsolute() : 判断创建File对象时是否使用的是绝对路径
        System.out.println("file3.isAbsolute() = " + file3.isAbsolute());
        //	boolean isHidden() : 判断File对象指向的文件/文件夹 是否是隐藏的
        System.out.println("file3.isHidden() = " + file3.isHidden());

        //-- 删除相关操作
        //    boolean delete() : 删除文件/文件目录(谨慎使用)
    }
}
1.4 文件遍历

单级文件遍历:

public class Demo03 {
    public static void main(String[] args) {
        // 1.创建File对象
        File file = new File("C:\Users\86150\Desktop\桌面文件");
        // 2.调用方法listFiles()
        File[] files = file.listFiles();
        // 3.遍历数组
        for (File file1 : files) {
            // 4.打印文件名称
            System.out.println(file1.getName());
        }
    }
}

多级目录遍历:

public class Demo04 {
    public static void main(String[] args) {
        // 1.创建File对象
        File file = new File("C:\Users\86150\Desktop\桌面文件");
        getFileName(file);
    }
    // 构造递归方法
    public static void getFileName(File file){
        // 递归出口:判断是否为文件
        if (file.isFile()){
            System.out.println("tt" + file.getName());
            return ;
        }

        // 递归规律
        System.out.println(file.getName());
        File[] files = file.listFiles();
        for (File ziFile : files) {
            getFileName(ziFile);
        }
    }
}
2.IO流的概述 2.1 IO流的概述

IO: 输入/输出(Input/Output)

流: 是一种抽象概念,是对数据传输的总称.也就是说数据在设备间的传输称为流,流的本质是数据传输

IO流就是用来处理设备间数据传输问题的.常见的应用: 文件复制; 文件上传; 文件下载

2.2 IO流的分类

按单位来分: 字节流,字符流

按流向分: 输入流(文件读取的过程)、输出流(程序写入文件的过程)

按角色分: 处理流、字节流

2.3 IO的原理

I/O是Input/Output的缩写, I/O技术是非常实用的技术,用于 处理设备之间的数据传输。如读/写文件,网络通讯等。

Java程序中,对于数据的输入/输出操作以“流(stream)” 的 方式进行。

java.io包下提供了各种“流”类和接口,用以获取不同种类的 数据,并通过标准的方法输入或输出数据

3.字节流 3.1 FileOutputStream类(字节输出流)

概述: 文件输出流是用于将数据写入 File 或 FileDescriptor 的输出流。文件是否可用或能否可以被创建取决于基础平台。特别是某些平台一次只允许一个 FileOutputStream(或其他文件写入对象)打开文件进行写入。在这种情况下,如果所涉及的文件已经打开,则此类中的构造方法将失败。

常用的方法:

-- 构造方法
    public FileOutputStream(File file) : 创建一个向指定 File 对象表示的文件中写入数据的文件输出流。
    public FileOutputSream(String name) : 创建一个向具有指定名称的文件中写入数据的输出文件流。
    
    
    
    public FileOutputStream(File file , boolean append) : 创建一个向指定 File 对象表示的文件中写入数据的文件输出流。
    public FileOutputStream(String name , boolean append) : 创建一个向具有指定名称的文件中写入数据的输出文件流。

-- 常用的方法
    void write(int b) : 一次向文件中装入一个字节的内容。
    void write(byte[] bys) : 一次向文件中装入一个字节数组的内容。
    void write(byte[] bys , int off , int len) : 一次向文件中转入一个字节数组中的一部分内容。
    void close() : 释放资源

代码示例:

public class Demo01 {
    public static void main(String[] args) throws IOException {
        // 1.创建对象的方式
        // public FileOutputStream(File file)
        FileOutputStream fos1 = new FileOutputStream(new File("JavaSE_09 IO\test\a.txt"));
        fos1.close();
        // public FileOutputStream(String name)
        FileOutputStream fos2 = new FileOutputStream("JavaSE_09 IO\test\a.txt");
        fos2.close();
        // public FileOutputStream(String name , boolean append)
        FileOutputStream fos3 = new FileOutputStream("JavaSE_09 IO\test\a.txt",true);
        fos3.close();
        // public FileOutputStream(File file , boolean append)
        FileOutputStream fos4 = new FileOutputStream(new File("JavaSE_09 IO\test\a.txt"),true);
        fos4.close();

        // 2.常用的方法
        // 创建字节输出流对象
        FileOutputStream fos = new FileOutputStream("JavaSE_09 IO\test\a.txt", true);

        // 一次输入一个字节
        fos.write(97);

        //一次写入一个字节数组
        byte[] bys = {99,100,101};
        fos.write(bys);

        // 一次写入一个字节数组的一部分
        byte[] bys2 = {99,100,101};
        fos.write(bys2,0,2);

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

总结:创建FileOutputStream做了那么些事:

1.创建FileOutputStream对象

2.开辟了堆内存的空间

3.fos指向路径结尾的目标文件

  1. 保证目标文件的前置路径存在 如果目标文件不存在,创建目标文件 如果目标文件存在,覆盖目标文件
3.2 FileInputStream类(字节输入流)

概述: 从文件系统中的某个文件中获得输入字节。哪些文件可用取决于主机环境。

常用的方法:

-- 构造方法
	public FileInputStream(File file) : 
			通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的 File 对象 file 指定。
   	public FileInputStream(String name) 
          	通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的路径名 name 指定。

-- 常用的方法
	int read() : 一次读一个字节
    int read(byte[] bys) : 一次读一个字节数组
    int read(byte[] bys , int off , int len) : 一次读一个字节的一部分
    void close() : 释放资源

代码示例:

public class b_fileinputstream {
    public static void main(String[] args) throws IOException {
        // 创建FileInputStream对象
        FileInputStream fis = new FileInputStream("JavaSE_09 IO\test\a.txt");

        // 一次读一个字节
        int read = fis.read();
        System.out.println("read = " + read);

        // 一次读一个字节数组
        byte[] bys = new byte[5];
        int read1 = fis.read(bys);
        System.out.println("Arrays.toString(bys) = " + Arrays.toString(bys));

        // 一次读一个字节数组的一部分
        byte[] bys2 = new byte[5];
        int read2 = fis.read(bys2, 1, 2);
        System.out.println("Arrays.toString(bys2) = " + Arrays.toString(bys2));


        // 释放资源
        fis.close();
    }
}
标准代码:文件复制操作

一个字节一个字节复制:

public class Demo01 {
    public static void main(String[] args) throws IOException {
        // 创建流对象
        FileInputStream fis = new FileInputStream("源文件路径");
        FileOutputStream fos = new FileOutputStream("目标文件路径");

        int by; // 用来获取读取的内容
        
        // 循环读取,不知道循环次数,用while循环
        while ((by = fis.read()) != -1){
            // 将获取的内容写入目标文件
            fos.write(by);
        }
        
        // 释放资源
        fis.close();
        fos.close();
    }
}

一个字节数组一个字节数组复制:

public class Demo02 {
    public static void main(String[] args) throws IOException {
        // 创建流对象
        FileInputStream fis = new FileInputStream("源文件路径");
        FileOutputStream fos = new FileOutputStream("目标文件路径");

        int len; // 用来获取读取的长度
        byte[] bys = new byte[1024]; // 用来读取内容的数组,长度是1024的整数倍
        
        // 循环读取,不知道循环次数,用while循环
        while ((len = fis.read(bys)) != -1){
            // 将获取的内容写入目标文件
            fos.write(bys , 0 , len);
        }
        
        // 释放资源
        fis.close();
        fos.close();
    }
}
3.3 BufferedOutputStream(高效输出流)

概述: 该类实现缓冲的输出流。通过设置这种输出流,应用程序就可以将各个字节写入底层输出流中,而不必针对每次字节写入调用底层系统。 高效率自带 “缓冲区” , 数据会先存储在缓冲区中 ,当缓冲区中的数据装满了,会自动刷新缓冲区到目 标文件

  1. 带缓冲区的输出流中, void flush() -> 刷新缓冲区
  2. 关流也是带有刷新缓冲区的功能

常用的方法:

-- 构造方法
    BufferedOutputStream(OutputStream out) 
          创建一个新的缓冲输出流,以将数据写入指定的底层输出流。 
	BufferedOutputStream(OutputStream out, int size) 
          创建一个新的缓冲输出流,以将具有指定缓冲区大小的数据写入指定的底层输出流。
    
-- 常用的方法
    void write(int b) : 一次向文件中装入一个字节的内容。
    void write(byte[] bys) : 一次向文件中装入一个字节数组的内容。
    void write(byte[] bys , int off , int len) : 一次向文件中转入一个字节数组中的一部分内容。
    void close() : 释放资源

代码示例:

public class Demo01 {
    public static void main(String[] args) throws IOException {
        // 创建字节缓冲流对象
        BufferedOutputStream bos = new BufferedOutputStream(
            new FileOutputStream("JavaSE_09 IO\test\a.txt"));

        bos.write(103);

        byte[] bys = {109,110,111};
        bos.write(bys);

        bos.write(bys,0,2);

        // 释放资源
        bos.close();
    }
}
3.4 BufferedInputStream类(高效输入流)

概述: BufferedInputStream 为另一个输入流添加一些功能,即缓冲输入以及支持 mark 和 reset 方法的能力。在创建 BufferedInputStream 时,会创建一个内部缓冲区数组。在读取或跳过流中的字节时,可根据需要从包含的输入流再次填充该内部缓冲区,一次填充多个字节。mark 操作记录输入流中的某个点,reset 操作使得在从包含的输入流中获取新字节之前,再次读取自最后一次 mark 操作后读取的所有字节。

常用的方法:

-- 构造方法
    BufferedInputStream(InputStream in) 
          创建一个 BufferedInputStream 并保存其参数,即输入流 in,以便将来使用。 
	BufferedInputStream(InputStream in, int size) 
          创建具有指定缓冲区大小的 BufferedInputStream 并保存其参数,即输入流 in,以便将来使用。 

-- 常用的方法
    int read() : 一次读一个字节
    int read(byte[] bys) : 一次读一个字节数组
    int read(byte[] bys , int off , int len) : 一次读一个字节的一部分
    void close() : 释放资源

代码示例:

public class Demo01 {
    public static void main(String[] args) throws IOException {
        // 创建字节缓冲流对象
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("JavaSE_09 IO\test\a.txt"));

        // 一次读一个字节
        int read = bis.read();
        System.out.println("read = " + read);

        // 一次读一个字节数组
        byte[] bys = new byte[3];
        bis.read(bys);
        System.out.println("Arrays.toString(bys) = " + Arrays.toString(bys));


        // 一次读一个字节数组的一部分
        byte[] bys2 = new byte[2];
        bis.read(bys2,0,1);
        System.out.println(Arrays.toString(bys2));

        // 释放资源
        bis.close();
    }
}
标准代码:文件复制操作

一个字节一个字节复制

public class Demo03 {
    public static void main(String[] args) throws IOException {
        // 创建字节缓冲流对象
        BufferedInputStream bis = 
            new BufferedInputStream(new FileInputStream("源文件路径"));
        BufferedOutputStream bos = 
            new BufferedOutputStream(new FileOutputStream("目标文件路径"));
        
        int by; // 用来获取读取的内容
        
        // 循环读取,不知道循环次数,用while循环
        while ((by = bis.read()) != -1){
            // 将获取的内容写入目标文件
            bos.write(by);
        }
        
        // 释放资源
        bis.close();
        bos.close();
    }
}

一个数组一个数组复制

public class Demo04 {
    public static void main(String[] args) throws IOException {
        // 创建字节缓冲流对象
        BufferedInputStream bis = 
            new BufferedInputStream(new FileInputStream("源文件路径"));
        BufferedOutputStream bos = 
            new BufferedOutputStream(new FileOutputStream("目标文件路径"));

        int len; // 用来获取读取的长度
        byte[] bys = new byte[1024]; // 用来读取内容的数组,长度是1024的整数倍
        
        // 循环读取,不知道循环次数,用while循环
        while ((len = bis.read(bys)) != -1){
            // 将获取的内容写入目标文件
            bos.write(bys , 0 , len);
        }
        
        // 释放资源
        bis.close();
        bos.close();
    }
}

4.字符流 4.1 字符流概述

由于字节流操作中文不是特别的方便,所以Java就提供字符流 。

字符流 = 字节流 + 编码表 。

中文的字节存储方式 用字节流复制文本文件时,文本文件也会有中文,但是没有问题,原因是最终底层操作会自动进行字节拼接 成中文,如何识别是中文的呢? 汉字在存储的时候,无论选择哪种编码存储,第一个字节都是负数

字符流都带缓冲区,但是不是高效的流那就不具备自动刷新缓冲区的功能;

4.2 FileWrite类(字符输出流)

概述: 用来写入字符文件的便捷类。此类的构造方法假定默认字符编码和默认字节缓冲区大小都是可接受的。要自己指定这些值,可以先在 FileOutputStream 上构造一个 OutputStreamWriter。 文件是否可用或是否可以被创建取决于底层平台。特别是某些平台一次只允许一个 FileWriter(或其他文件写入对象)打开文件进行写入。在这种情况下,如果所涉及的文件已经打开,则此类中的构造方法将失败。

常用的方法:

-- 构造方法
    FileWriter(File file) : 根据给定的 File 对象构造一个 FileWriter 对象。
    FileWriter(String fileName) : 根据给定的文件名构造一个 FileWriter 对象
    FileWriter(File file, boolean append) : 根据给定的 File 对象构造一个 FileWriter 对象。
    FileWriter(String fileName, boolean append) : 根据给定的文件名以及指示是否附加写入数据的 boolean 值来构造 FileWriter 对象。

-- 常用的方法
    void write(int c) : 一次向文件中装入一个字符的内容。
    void write(char[] chs) : 一次向文件中装入一个字符数组的内容。
    void write(char[] chs , int off , int len) : 一次向文件中转入一个字符数组中的一部分内容。
   	void write(String str) : 一次写一个字符串
	void write(String str, int off, int len) 一次写一个字符串的一部分

代码演示:

public class Demo02 {
    public static void main(String[] args) throws IOException {
        // 创建流对象
        FileInputStream fis = new FileInputStream("JavaSE_09 IO\test\a.txt");
        FileOutputStream fos = new FileOutputStream("C:\Users\86150\Desktop\1.txt");

        int len; // 用来获取读取的长度
        byte[] bys = new byte[1024]; // 用来读取内容的数组,长度是1024的整数倍
        // 循环读取,不知道循环次数,用while循环
        while ((len = fis.read(bys)) != -1){
            // 将获取的内容写入目标文件
            fos.write(bys , 0 , len);
        }
        // 释放资源
        fis.close();
        fos.close();
    }
}
4.3 FileReader类(字符输入流)

概述: 用来读取字符文件的便捷类。此类的构造方法假定默认字符编码和默认字节缓冲区大小都是适当的。要自己指定这些值,可以先在 FileInputStream 上构造一个 InputStreamReader。 FileReader 用于读取字符流。要读取原始字节流,请考虑使用 FileInputStream。

常用的方法:

-- 构造方法
    FileReader(File file) : 在给定从中读取数据的 File 的情况下创建一个新 FileReader。
    FileReader(String fileName) : 在给定从中读取数据的文件名的情况下创建一个新 FileReader。
-- 常用的方法
   	int read() :一次读一个字符
	int read(char[] cbuf) 一次读一个字符数组
	int read(char[] cbuf, int off, int len) 一次读一个字符数组的一部分
    void close() : 释放资源

代码演示:

public class Demo01 {
    public static void main(String[] args) throws IOException {
        // 创建字符输出流对象
        FileReader fr = new FileReader("JavaSE_09 IO\test\a.txt");

        // int read() :一次读一个字符
        int read = fr.read();
        System.out.println("read = " + read);
        
        //	int read(char[] cbuf) 一次读一个字符数组
        char[] chs = new char[3];
        fr.read(chs);
        System.out.println("Arrays.toString(chs) = " + Arrays.toString(chs));

        //	int read(char[] cbuf, int off, int len) 一次读一个字符数组的一部分
        char[] chs1 = new char[3];
        fr.read(chs1,0,2);
        System.out.println("Arrays.toString(chs1) = " + Arrays.toString(chs1));

        fr.close();
    }
}
标准代码:文件复制

一次一个字节复制

public class Demo05 {
    public static void main(String[] args) throws IOException {
        // 创建字节缓冲流对象
        FileReader fr = new FileReader("源文件路径");
        FileWriter fs = new FileWriter("目标文件路径");
        
        int by; // 用来获取读取的内容
        
        // 循环读取,不知道循环次数,用while循环
        while ((by = fr.read()) != -1){
            // 将获取的内容写入目标文件
            fs.write(by);
            // 刷新
            fs.flush();
        }
        
        // 释放资源
        fr.close();
        fs.close();
    }
}

一次一个字节数组复制

public class Demo06 {
    public static void main(String[] args) throws IOException {
        // 创建字节缓冲流对象
        FileReader fr = new FileReader("源文件路径");
        FileWriter fs = new FileWriter("目标文件路径");
        
        int len; // 用来获取读取的长度
        char[] chs = new char[1024]; // 用来读取内容的数组,长度是1024的整数倍

        // 循环读取,不知道循环次数,用while循环
        while ((len = fr.read(chs)) != -1){
            // 将获取的内容写入目标文件
            fs.write(chs , 0 , len);
            // 刷新
            fs.flush();
        }

        // 释放资源
        fr.close();
        fs.close();
    }
}
4.4 BufferedWriter(高效字符输出流)

概述: 将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。 可以指定缓冲区的大小,或者接受默认的大小。在大多数情况下,默认值就足够大了。 该类提供了 newLine() 方法,它使用平台自己的行分隔符概念,此概念由系统属性 line.separator 定义。并非所有平台都使用新行符 (‘n’) 来终止各行。因此调用此方法来终止每个输出行要优于直接写入新行符。

常用的方法:

-- 构造方法
    BufferedWriter(Writer out) : 创建一个使用默认大小输出缓冲区的缓冲字符输出流。 
	BufferedWriter(Writer out, int sz) : 创建一个使用给定大小输出缓冲区的新缓冲字符输出流。 

-- 常用的方法
    void close() : 关闭此流,但要先刷新它。 
 	void flush() : 刷新该流的缓冲。 
 	void newLine() : 写入一个行分隔符。 
 	void write(char[] cbuf, int off, int len) : 写入字符数组的某一部分。 
 	void write(int c) : 写入单个字符。 
 	void write(String s, int off, int len) : 写入字符串的某一部分。 

代码演示:

public class Deom01 {
    public static void main(String[] args) throws IOException {
        // 1.创建对象
        BufferedWriter bw = new BufferedWriter(new FileWriter("JavaSE_09 IO\test\a.txt"));


        // 	void write(char[] cbuf, int off, int len) : 写入字符数组的某一部分。
        // 	void write(int c) : 写入单个字符。
        // 	void write(String s, int off, int len) : 写入字符串的某一部分。
        // 	void newLine() : 写入一个行分隔符。
        bw.write('a');
        char[] chs = {'a','b','c'};
        bw.write(chs);
        bw.write("AAA".toCharArray(),0,3);
        bw.write("mmmm");
        bw.write("fsafa",0,4);

        //释放资源
        bw.close();
    }
}
4.5 BufferedReader (高效字符输入流)

概述: 从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。 可以指定缓冲区的大小,或者可使用默认的大小。大多数情况下,默认值就足够大了。 通常,Reader 所作的每个读取请求都会导致对底层字符或字节流进行相应的读取请求。因此,建议用 BufferedReader 包装所有其 read() 操作可能开销很高的 Reader(如 FileReader 和 InputStreamReader)。

常用的方法:

-- 构造方法
    BufferedReader(Reader in) : 创建一个使用默认大小输入缓冲区的缓冲字符输入流。 
	BufferedReader(Reader in, int sz) : 创建一个使用指定大小输入缓冲区的缓冲字符输入流。 
-- 常用的方法
    int read() : 读取单个字符。 
    int read(char[] cbuf) 一次读一个字符数组
 	int read(char[] cbuf, int off, int len) : 将字符读入数组的某一部分。 
 	String readLine() : 读取一个文本行。 
	void close() : 释放资源

代码示例:

public class Demo01 {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new FileReader("JavaSE_09 IO\test\a.txt"));

        //  int read() : 读取单个字符。
        int read = br.read();
        System.out.println("read = " + read);
        //  int read(char[] cbuf) 一次读一个字符数组
        char[] chs = new char[3];
        br.read(chs);
        System.out.println("Arrays.toString(chs) = " + Arrays.toString(chs));

        // 	int read(char[] cbuf, int off, int len) : 将字符读入数组的某一部分。
        char[] chs2 = new char[3];
        br.read(chs2,0,2);
        System.out.println("Arrays.toString(chs2) = " + Arrays.toString(chs2));
        // 	String readLine() : 读取一个文本行。
        System.out.println("br.readLine() = " + br.readLine());

        // 释放资源
        br.close();
    }
}
标准代码:文件复制

一次复制一行:

public class Demo07 {
    public static void main(String[] args) throws IOException {
        // 创建字符缓冲区对象
        BufferedReader br = new BufferedReader(new FileReader("源文件路径"));
        BufferedWriter bw = new BufferedWriter(new FileWriter("目标文件路径"));

        String line;

        while ((line = br.readLine()) != null){
            bw.write(line);
            bw.newLine();
        }

        // 释放资源
        br.close();
        bw.close();
    }
}
5.EMS学生管理系统案例 5.1 案例描述

制作一个可以永久存储数据的EMS学生信息管理系统,功能有:

1.添加学生信息

2.删除学生信息

3.修改学生信息

4.按照成绩降序将学生信息展现在控制台。

包含的知识点有:mvc架构、面向对象思想、集合、IO流、异常处理。。。

源码链接:EMS学生信息管理系统

6.字节转化流 6.1 编码与解码

码: 俗称的二进制代码,类似于101010代码

编码: 类似于将字符串(String)通过某种编码格式翻译成二进制的过程。String->二进制

解码: 类似于将某段二进制代码通过某种编码格式解析成字符串的过程。二进制->String

编码表: 类似于“密码本”,是字符与数字之间的一种对照表,里面存在数字与字符的对照关系。

--最基础的编码表: ASCII 美国标准信息交换码表;后续所有编码表的前128个字符全都是ASCII码表
--GB字符集:
    GB2312:最古老的中文编码表
    GBK :如今最常用的编码表
--国际统一(标准化)组织 -> UniCode字符集 -> 只能使用此字符集中的一个编码表作为网页的文字编码格式
    utf-8
    utf-16
在utf-8中一个汉字占3个字节
在GBK中一个汉字占2个字节
6.2 OutputStreamWriter类

概述: 将字节字节输出流转成字符输出流,是字符流通向字节流的桥梁:可使用指定的 charset 将要写入流中的字符编码成字节。它使用的字符集可以由名称指定或显式给定,否则将接受平台默认的字符集。

常用的方法:

-- 构造方法
    public OutputStreamWriter(OutputStream out) : 创建使用默认字符编码的 OutputStreamWriter 
    public OutputStreamWriter(OutputStream out , String charsetName) : 创建使用指定字符集的 OutputStreamWriter。

-- 常用的方法
    write(int c) : 一次写入一个字符。
    write(char[] chs) : 一次写入一个字符数组。
    write(char[] , int offer , int len) : 一次写入字符数组的一部分。
    write(String str) : 一次写入一个字符串。
    write(String str , int offer , int len) : 一次写入一个字符串一部分。

代码示例:

public class Demo01 {
    public static void main(String[] args) throws IOException {
        // 创建对象
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("avaSE_09 IO\test\a.txt"));

        // write(int c) : 一次写入一个字符。
        osw.write('c');
        //  write(char[] chs) : 一次写入一个字符数组。
        char[] chs = {'a','b','c'};
        osw.write(chs);
        //  write(char[] , int offer , int len) : 一次写入字符数组的一部分。
        char[] chs2 = {'a','b','c'};
        osw.write(chs2,0,1);
        //  write(String str) : 一次写入一个字符串。
        osw.write("abc");
        //  write(String str , int offer , int len) : 一次写入一个字符串一部分。
        osw.write("abcd3e",0,4);

        // 释放资源
        osw.close();
    }
}
6.3 InputStreamReader类

概述: InputStreamReader 是字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符。它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集。

常用的方法:

-- 构造方法
    public InputStreamReader(InputStream in) : 创建一个使用默认字符集的 InputStreamReader
    public InputStreamReader(InputStream in , String charsetName) : 创建使用指定字符集的 InputStreamReader。

-- 常用的方法
    int read() : 一次读一个字符
    int read(char[] chs) : 一次读一个字符数组
    int read(char[] chs , int offer , int len) : 一次读一个字符数组的一部分

代码示例:

public class Demo01 {
    public static void main(String[] args) throws IOException {
        // 创建对象
        InputStreamReader isr = new InputStreamReader(new FileInputStream("JavaSE_09 IO\test\a.txt"));

        // 一次读一个字符
        int read = isr.read();
        System.out.println("read = " + read);

        // 一次读一个字符数组
        char[] chs = new char[2];
        isr.read(chs);
        System.out.println("Arrays.toString(chs) = " + Arrays.toString(chs));

        // 一次读一个数组的一部分
        char[] chs2 = new char[3];
        isr.read(chs2,0,1);
        System.out.println("Arrays.toString(chs2) = " + Arrays.toString(chs2));
        
        // 释放资源
        isr.close();
    }
}
7.序列化和反序列化 7.1 ObjectOutputStream类(序列化)

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

常用的方法:

-- 构造方法
    public ObjectOutputStream(OutputStream out) : 创建写入指定 OutputStream 的 ObjectOutputStream。
    
-- 常用的方法
    void write(int b) : 一次写一个字节
    void write(byte[] bys) : 一次写一个字节数组
    void write(byte[] bys , int offer , int len) : 一次写一个字节数组的一部分
    
    *重要 void writeObject(Object o) : 将一个对象永久化存储

代码示例:

public class Demo01 {
    public static void main(String[] args) throws IOException {
        // 创建序列化对象
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("JavaSE_09 IO\test\stu.txt"));

        // 存储一个学生对象
        oos.writeObject(new Student("张三",12));

        oos.close();
    }
}
7.2 ObjectInputStream类(反序列化)

概述: ObjectInputStream 对以前使用 ObjectOutputStream 写入的基本数据和对象进行反序列化。

常用的方法:

-- 构造方法
    public ObjectInputStream(InputStream in) : 创建从指定 InputStream 读取的 ObjectInputStream。

-- 常用的方法
    int read() : 一次读一个字节
    int read(byte[] bys) : 一次读一个字节数组
    int read(byte[] bys , int off , int len) : 一次读一个字节的一部分
    
   	*重要 Object readObject() : 从 ObjectInputStream 读取对象。

代码示例:

public class Demo01 {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        // 创建对象
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("JavaSE_09 IO\test\stu.txt"));

        Student student = (Student) ois.readObject();

        System.out.println("student = " + student);
        ois.close();
    }
}
7.3 序列化和反序列化的问题以及JavaBean

序列化和反序列化的注意事项:

1.当自定义类创建对象进行序列化和反序列化操作时,自定义类需要实现序列化接口(Serializable)

2.当自定类中的属性发生变化时,反序列化操作就会报出InvalidClassException 异常。这是由于我们进行反序列化操作时,系统会将自定义类中的信息与文件存储的信息进行比对,若属性、方法不相同则会报出该异常信息。解决方式时给自定义类一个唯一标识Java | ‘serialVersionUID’

JavaBean事务描述类的书写步骤

1. 私有所有属性
2. 自动生成无参构造
3. 自动生成全参构造
4. 自动生成getter and setter方法
5. 自动重写hashCode 和 equals方法
6. 自动重写toString()方法
7. 实现Serializable序列化接口
8. 自动生成序列化versionUID (类的身份证号)
//9. 编写行为/功能

代码示例:

public class Student implements Serializable {

    private static final long serialVersionUID = 6958333654743411179L;
    private String name;
    private int age;

    public Student() {
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return age == student.age &&
                Objects.equals(name, student.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + ''' +
                ", age=" + age +
                '}';
    }
}
8.Properties类

概述: Properties 类表示了一个持久的属性集。Properties 可保存在流中或从流中加载。属性列表中每个键及其对应值都是一个字符串。

常用的方法:

-- 构造方法
    Properties() : 创建一个无默认值的空属性列表。

-- 常用的方法
	Object setProperty(String key , String val) : 调用 Hashtable 的方法 put方法,向集合中添加一个元素
    String getProperty(String key) : 根据键获取值
    String getProperty(String key , String val) :  用指定的键在属性列表中搜索属性。
    Set stringPropertyNames() : 获取所有的键返回一个set集合
    void load(InputStream in) : 从字节输入流中读入集合属性
    void load(Reader reader) : 从字符输入流中读入集合属性
    void store(OutputStream out, String comments) 
          以适合使用 load(InputStream) 方法加载到Properties表中的格式,将此Properties表中的属性列表(键和元素对)
    	  写入输出流。 
 	void store(Writer writer, String comments) 
          以适合使用 load(Reader) 方法的格式,将此 Properties 表中的属性列表(键和元素对)写入输出字符。 

代码演示:

public class Demo01 {
    public static void main(String[] args) throws IOException {
        // 1.创建Properties集合对象
        Properties properties = new Properties();

        // 2.向集合中添加元素
        properties.setProperty("username","admin");
        properties.setProperty("password","123456");

        // 3.创建字节输出流
        FileOutputStream fos = new FileOutputStream("JavaSE_09 IO\test\test.properties");

        // 4.利用store(OutputStream out , String comments)方法将元素持久化存储到文件中
        properties.store(fos,"");

        // 5.释放资源
        fos.close();
    }
}


public class Demo02 {
    public static void main(String[] args) throws IOException {
        // 1.创建Properties对象
        Properties properties = new Properties();

        // 2.创建字节输入流对象
        FileInputStream fis = new FileInputStream("JavaSE_09 IO\test\test.properties");

        // 3.利用load(InputStream in)方法加载数据到集合中
        properties.load(fis);

        // 4.释放资源
        fis.close();

        // 5.利用stringPropertyNames()方法获取所有的键
        Set keySet = properties.stringPropertyNames();

        // 6.遍历集合
        for (String key : keySet) {
            // 7.利用getProperty(String key)方法获取到对应的值
            String value = properties.getProperty(key);

            System.out.println(key + " --- " + value);
        }
    }
}
转载请注明:文章转载自 www.051e.com
本文地址:http://www.051e.com/it/1065145.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 ©2023-2025 051e.com

ICP备案号:京ICP备12030808号