java(File、IO流)

一、IO流和File类

IO:

  • 将数据从内存读取出来
  • 或者从本地文件保存到内存中

File类:

  • 它是文件和目录路径名的抽象表示
  • 文件和目录是可以通过File封装成对象的
  • 对于File而言,其封装的并不是一个真正存在的文件,仅仅是一个路径名而已.它可以是存在的,也可以是不存在的.将来是要通过具体的操作把这个路径的内容转换为具体存在的

二 、File类

File类的构造方法

方法名说明
File(String pathname)通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例
File(String parent, String child)从父路径名字符串和子路径名字符串创建新的 File实例
File(File parent, String child)从父抽象路径名和子路径名字符串创建新的 File实例

示范代码:

public class FileDemo01 {
    public static void main(String[] args) {
        //File(String pathname): 通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例
        File f1 = new File("E:\\FileText\\java.txt");
        System.out.println(f1);

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

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

绝对路径和相对路径

  • 绝对路径

    是一个完整的路径,从盘符开始

  • 相对路径

    是一个简化的路径,相对当前项目下的路径

public class FileDemo02 {
    public static void main(String[] args) {
        // 是一个完整的路径,从盘符开始
        File file1 = new File("D:\\itheima\\a.txt");

        // 是一个简化的路径,从当前项目根目录开始
        File file2 = new File("a.txt");
        File file3 = new File("模块名\\a.txt");
    }
}

file的成员方法

file的创建方法

方法名说明
public boolean createNewFile()当具有该名称的文件不存在时,创建一个由该抽象路径名命名的新空文件 ,文件存在则创建失败返回false,文件夹必须存在
public boolean mkdir()创建由此抽象路径名命名的目录,只能创建单级文件夹,不管有没有后缀
public boolean mkdirs()可以创建单级文件夹也可以创建多级文件夹,不管有没有后缀 只能创建文件夹
  • 示范代码:
public class MapStream {
    public static void main(String[] args) throws IOException {

        File file = new File("E:\\a.txt");
        File file1 = new File("E:\\aaa\\bbb");
        File file2 = new File("E:\\aaa\\bbb\\ccc");
        //可以创建多级文件夹,也可以创建单级文件夹。若文件夹存在也是返回flase,不管有没有后缀,都是创建文件夹
        boolean mkdirs = file1.mkdirs();
        //若要创建的文件存在,则创建失败,返回flase,成功返回true
        boolean newFile = file.createNewFile();
        //创建成功,是会在原有的文件夹基础下继续创建ccc文件夹
        boolean mkdirs1 = file2.mkdirs();
        System.out.println(newFile);
        System.out.println(mkdirs);
        System.out.println(mkdirs1);
    }
}

file的删除方法

方法分类

方法名说明
public boolean delete()删除由此抽象路径名表示的文件或目录

delete方法的特点:

  • 删除不会走回收站
  • 如果删除的是文件,直接删除,如果删除文件夹只能删除空文件夹,删除有内容的文件夹,只能进入文件夹,删除文件夹中的内容,才能删除该文件夹
  • 如果删除多级文件夹,只能一层一层的删除

file的判断和获取功能

  • 判断功能

    方法名说明
    public boolean isDirectory()测试此抽象路径名表示的File是否为文件夹
    public boolean isFile()测试此抽象路径名表示的File是否为文件
    public boolean exists()测试此抽象路径名表示的File是否存在
  • 获取功能

    方法名说明
    public String getAbsolutePath()返回此抽象路径名的绝对路径名字符串
    public String getPath()将此抽象路径名转换为路径名字符串
    public String getName()返回由此抽象路径名表示的文件或目录的名称
    public File[] listFiles()返回此抽象路径名表示的目录中的文件和目录的File对象数组

getName():
如果是文件夹,获取的就是文件夹名,如果是文件,获取的是文件名+后缀

  • 代码演示
public class MapStream {
    public static void main(String[] args) throws IOException {

        File file1 = new File("E:\\aaa\\bbb");
        //创建多级文件夹,若文件夹存在也是返回flase,不管有没有后缀,都是创建文件夹
       boolean mkdirs = file1.mkdirs();
        System.out.println("创建"+mkdirs);//创建失败
        boolean file = file1.isFile();
        System.out.println("文件"+file);//不是文件
        boolean directory = file1.isDirectory();
        System.out.println("文件夹"+directory);//是文件夹
        String name = file1.getName();
        System.out.println(name);//文件夹的名称
        System.out.println(file1.getAbsolutePath());//文件夹的绝对路径
        System.out.println(file1.getPath());//文件夹的路径
        System.out.println("存在"+file1.exists());//文件夹是否存在
    }
}
结果:
创建false
文件false
文件夹true
bbb
E:\aaa\bbb
E:\aaa\bbb
存在true

高级获取方法listFiles()

listFiles():

  • 进入文件夹,获取该文件夹中的所有的文件夹和文件(包括所有的隐藏文件和隐藏文件夹)
  • 当调用者为null时
    放回null
  • 当调用者是一个文件时
    方法会返回一个null
  • 当调用者是一个空文件夹时
    返回一个长度为0的数组
  • 当调用者是一个有内容的文件夹时
    将里面所有的文件和文件夹的路径返回到数组中

file的练习

1、 案例需求
在当前模块下的aaa文件夹中创建一个a.txt文件

  • 实现步骤
    • 创建File对象,指向aaa文件夹
    • 判断aaa文件夹是否存在,如果不存在则创建
    • 创建File对象,指向aaa文件夹下的a.txt文件
    • 创建这个文件
      演示代码:
  public class FileT1 {
    public static void main(String[] args) throws IOException {
        File file = new File("aaa");
        File file1 = new File(file,"a.txt");
        if(file.exists()==false)
        {
            file.mkdirs();
        }
        System.out.println( file1.createNewFile());

    }
}

2、案例需求

删除一个多级文件夹

  • 实现步骤

    • 定义一个方法,接收一个File对象
    • 遍历这个File对象,获取它下边的每个文件和文件夹对象
    • 判断当前遍历到的File对象是文件还是文件夹
    • 如果是文件,直接删除
    • 如果是文件夹,递归调用自己,将当前遍历到的File对象当做参数传递
    • 参数传递过来的文件夹File对象已经处理完成,最后直接删除这个空文件夹
      演示代码:
  public class FileT2 {
    public static void main(String[] args) throws IOException {
        File file1 = new File("E:\\xxx");
        deleFiles(file1);
    }

    private static void deleFiles(File file) {
        File[] files = file.listFiles();
        for (File file1 : files) {
            if(file1.isDirectory())
                deleFiles(file1);
            else if(file1.isFile()) {
                file1.delete();
            } 
        }
        System.out.println(file.delete());
    }
}

3、案例需求
统计一个文件夹中每种文件的个数并打印
结果如下:

txt的个数为:2
ppt的个数为:2
doc的个数为:1

提醒:

  • 字符串中存在 . 和 | 的时候,不能直接用String.split(".")进行分隔,而是String.split("\\ .")或者String.split("\\ |");
    代码演示:
public class FileT3 {
    public static void main(String[] args) {
        File file = new File("E:\\xxx");
        HashMap<String,Integer> hashMap=new HashMap<>();
        Statistics(hashMap,file);
        hashMap.forEach((s,num)-> System.out.println(s+"的个数为:"+num));
    }

    private static void Statistics(HashMap<String, Integer> hashMap,File file) {
        File[] files = file.listFiles();
        for (File file1 : files) {
            if(file1.isDirectory())
                Statistics(hashMap, file1);
            else
            {
                String name = file1.getName();
                String[] split = name.split("\\.");
                //只考虑一个点的情况
                if(split.length==2){
                    if(hashMap.containsKey(split[1])){
                        Integer integer = hashMap.get(split[1]);
                        integer++;
                        hashMap.put(split[1],integer);
                    }else
                        hashMap.put(split[1],1);
                }
            }
        }
    }
}

三、IO流

  • IO流介绍

    • IO:输入/输出(Input/Output),以内存为参照物,内存在读,内存在写
    • 流:是一种抽象概念,是对数据传输的总称.也就是说数据在设备间的传输称为流,流的本质是数据传输
    • IO流就是用来处理设备间数据传输问题的.常见的应用: 文件复制; 文件上传; 文件下载
  • IO流的分类

    • 按照数据的流向
      • 输入流:读数据
      • 输出流:写数据
    • 按照数据类型来分
      • 字节流
        • 字节输入流
        • 字节输出流
      • 字符流
        • 字符输入流
        • 字符输出流
  • IO流的使用场景

    • 如果操作的是纯文本文件(office不是纯文本),优先使用字符流
    • 如果操作的是图片、视频、音频等二进制文件,优先使用字节流
    • 如果不确定文件类型,优先使用字节流.字节流是万能的流

    字节流

    字节流抽象基类

  • InputStream:这个抽象类是表示字节输入流的所有类的超类

  • OutputStream:这个抽象类是表示字节输出流的所有类的超类

  • 子类名特点:子类名称都是以其父类名作为子类名的后缀

字节输出流(FileOutputStream)写

  • FileOutputStream(String name):创建文件输出流以指定的名称写入文件

  • 使用字节输出流写数据的步骤

    • 创建字节输出流对象(调用系统功能创建了文件,创建字节输出流对象,让字节输出流对象指向文件,如果文件不存在,会创建文件,如果存在,会清空文件内容)
    • 调用字节输出流对象的写数据方法(写的如果是整数,认为是ASCll码值)
    • 释放资源(关闭此文件输出流并释放与此流相关联的任何系统资源)
public class OutputDemo1 {
    public static void main(String[] args) throws IOException {
        //1.创建字节输出流的对象 --- 告诉虚拟机我要往哪个文件中写数据了
        //如果文件不存在,会创建文件,如果存在,会清空文件内容
        FileOutputStream fos = new FileOutputStream("D:\\a.txt");
        //FileOutputStream fos = new FileOutputStream(new File("D:\\a.txt"));

        //2,写数据
        fos.write(97);

        //3,释放资源
        fos.close();

    }
}

ASCLL码表:
在这里插入图片描述

字节流写数据的方式(内存到硬盘)

写数据的方法分类

方法名说明
void write(int b)将指定的字节写入此文件输出流 一次写一个字节数据
void write(byte[] b)将 b.length字节从指定的字节数组写入此文件输出流 一次写一个字节数组数据
void write(byte[] b, int off, int len)将 len字节从指定的字节数组开始,从偏移量off开始写入此文件输出流 一次写一个字节数组的部分数据
  • 代码演示
package com.itheima.output;

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

public class OutputDemo4 {
  public static void main(String[] args) throws IOException {
        FileOutputStream fos = new FileOutputStream("bytestream\\a.txt");

        /*byte [] bys = {97,98,99};
        fos.write(bys);*/

        byte [] bys = {97,98,99,100,101,102,103};
      fos.write(bys,1,2);

        fos.close();
    }
}

字节流写数据的二个小问题
1、换行
.字节流写数据如何实现换行

  • windows:\r\n
  • linux:\n
  • mac:\r
		fos.write(98);
        //能加一个换行
        fos.write("\r\n".getBytes());

2、追加续写
字节流写数据如何实现追加写入

  • public FileOutputStream(String name,boolean append)
  • 创建文件输出流以指定的名称写入文件。如果第二个参数为true ,则字节将写入文件的末尾而不是开头
//第二个默认为false,不续写
FileOutputStream fos = new FileOutputStream("bytestream\\a.txt",true);
字节流写数据的异常处理

1.如何捕获异常呢?

try-catch-finally

2.异常处理格式

try{
	可能出现异常的代码;
}catch(异常类名 变量名){
	异常的处理代码;
}finally{
	执行所有清除操作;
}

3.为什么要使用finally
被finally控制的语句一定会执行 不管有没有异常,也不管异常有没有被捕获,除非JVM退出
示范代码:

 public class IOtest {
    public static void main(String[] args)  {
        FileOutputStream fos = null;
        try {
            fos=new FileOutputStream("a.txt", true);
            byte[] bArr=new byte[]{97,98,99};
            fos.write(102);
            fos.write("\r\n".getBytes());
            fos.write(103);

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

字节输入流(FileInputStream)读

1.如何读文件?

import java.io.FileInputStream类

2.构造方法

方法说明
FileInputStream(File file)通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的 File对象 file命名。
FileInputStream(String name)通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的路径名 name命名

3.字节输入流读取文件数据的步骤

  • 创建字节输入流对象(如果文件不存在,直接报错)
  • 调用字节输入流对象的读数据方法(read,一次只读取一个数据)
  • 释放资源

4.代码演示:

public class IOInputtest {
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("a.txt");
        char read = (char)fis.read();
        System.out.println(read);
        fis.close();
    }
}

读取多个数据:

public class IOInputtest {
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("a.txt");
       int b=0;
       while((b=fis.read())!=-1)
           System.out.println((char)b);
        fis.close();
    }
}
文件的复制(先读在写)
  • 代码演示:
public class IOInputtest {
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("a.txt");
        FileOutputStream fos = new FileOutputStream("E:\\b.txt");
        int b=0;
       while((b=fis.read())!=-1)
           fos.write(b);
        fis.close();
        fos.close();
    }
}
  • 如何提高文件拷贝的速度?
    定义数组
    一次性读写多个字节
  • int read(byte[] b):返回的是读到的有效的数据,会把读到的有效数据存到数组中
  • write(byte b[], int off, int len):把数组中的数据,从off索引处开始,写入len个数据
方法说明
public int read(byte[] b) throws IOException从输入流读取最多b.length个字节的数据放入数组中 ,返回读取的个数
public void write(byte b[], int off, int len) throws IOException从字节数组下标off开始,将其中len个数据写入到文件的输出流中
  • 代码演示:
public class IOInputtest {
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("a.txt");
        FileOutputStream fos = new FileOutputStream("E:\\b.txt");
        byte[] bytes = new byte[1024];
        int len;//表示读到了几个有效的数据,read(byte[] b)方法会把读到的有效数据存到数组中
        while((len=fis.read(bytes))!=-1){
            System.out.println(Arrays.toString(bytes));
            fos.write(bytes,0,len);
        }
        fis.close();
        fos.close();
    }
}

字节缓冲流

字节缓冲流介绍

  • BufferedOutputStream:字节缓冲输出流(写)
  • BufferedInputStream: 字节缓冲输入流(读)
  • 不能直接操作文件,需要借助字节流间接操作文件
    如何使用?

构造方法:

方法名说明
BufferedOutputStream(OutputStream out)创建字节缓冲输出流对象
BufferedInputStream(InputStream in)创建字节缓冲输入流对象

为什么构造方法需要的是字节流,而不是具体的文件或者路径?
在这里插入图片描述
常用方法

方法说明
public int read() throws IOException从输入流中读出8192个字节到缓冲数组中,再从缓冲数组中取出一个字节
public void write(int b) throws IOException将字节b写入到缓冲数组中,当缓冲数组满时,一次性写入目标文件
字节缓冲流一次读取一个字节实现Copy文件

代码演示:

public class OutputDemo11 {
    public static void main(String[] args) throws IOException {
        //就要利用缓冲流去拷贝文件

        //创建一个字节缓冲输入流
        //在底层创建了一个默认长度为8192的字节数组。
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("bytestream\\a.avi"));
        //创建一个字节缓冲输出流
        //在底层也创建了一个默认长度为8192的字节数组。
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("bytestream\\copy.avi"));

        int b;
        while((b = bis.read()) != -1){
            bos.write(b);
        }

        //方法的底层会把字节流给关闭。
        bis.close();
        bos.close();

    }
}
字节缓冲流一次读取一个字节数组实现Copy文件

.方法

方法说明
public int read(byte b[]) throws IOException从输入流中读出8192个字节到缓冲数组中,再从缓冲数组中取出数组b.length个字节到数组b中
public void write(byte b[], int off, int len) throws IOException将数组b中的元素,从下标0开始,向缓冲数组中写入len个字节,当缓冲数组满时,一次性写入目的地

代码演示:

public class BufferedIO {
    public static void main(String[] args) throws IOException {
        //创建字节输入缓冲流
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("a.txt"));
        //创建字节输出缓冲流
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("E:\\a.txt"));

        byte[] bArr=new byte[1024];
        int len;
        while((len=bis.read(bArr))!=-1){
            bos.write(bArr, 0, len);
        }
        bis.close();
        bos.close();
    }
}

1.字节缓冲输入流每次读取buffer长度个字节

2.字节缓冲输出流写数据时先将缓冲字节输入流缓冲数组中的数据每次转移bytes长度个字节到自己的缓冲数组中,当缓冲数组满时,字节流一次性写出缓冲数组长度个字节

3.如果缓冲数组不满时,当调用缓冲流的close()方法时会将缓冲数组中数据写出

小结

在这里插入图片描述

字符流

字符流可以解决中文乱码问题
1.常见的编码/解码方式

  • ASCII编码: ASCII字符集(码表)的编码方式,1个字节,最多能表示256个字符,适用于英文

  • GBK编码:GBK字符集(码表)的编码式,用1个字节表示英文,用2个字节表示中文

  • UTF-8编码:Unicode字符集(码表)的编码方式,用1个字节表示英文,用3个字节表示中文

  • windows平台默认编码方式是GBK(2个字节默认1个字符),而ideal和工作中用的编码方式是UTF-8(3个字节默认1个字符)

字符串-编码和解码

1.编码方法

方法说明
public byte[] getBytes()使用平台的默认字符集将该String编码为一系列字节,将结果存储到新的字节数组中
public byte[] getBytes(String charsetName)使用命名的字符集将这个String编码成一个字节序列,将结果存储到一个新的字节数组中

2.解码方法(通过String的构造方法进行解码)

方法说明
String(byte[] bytes)通过使用平台的默认字符集解码指定的字节数组来构造新的 String
String(byte[] bytes, String charsetName)构造一个新的String由指定用指定的字节的数组解码

代码演示:

public class tt {
    public static void main(String[] args) {
        String s="测试";
        byte[] bytes = s.getBytes();
        //在Ideal中默认编码是UTF-8,中文用三个字节表示
        System.out.println(Arrays.toString(bytes));
        //[-26, -75, -117, -24, -81, -107]
        //字节转字符
        String s1 = new String(bytes);
        //测试
        System.out.println(s1);
    }
}
为什么会出现中文乱码
  • 在Ideal中默认编码是UTF-8,中文用三个字节表示,而用字节流读出中文时,如果一次只读取一个字节就强转,就造成了乱码

字符流写数据

  • 介绍

    Writer: 用于写入字符流的抽象父类

    FileWriter: 用于写入字符流的常用子类

  • 构造方法

方法名说明
FileWriter(File file)根据给定的 File 对象构造一个 FileWriter 对象
FileWriter(File file, boolean append)根据给定的 File 对象构造一个 FileWriter 对象
FileWriter(String fileName)根据给定的文件名构造一个 FileWriter 对象
FileWriter(String fileName, boolean append)根据给定的文件名以及指示是否附加写入数据的 boolean 值来构造 FileWriter 对象
  • 成员方法
方法名说明
void write(int c)写一个字符
void write(char[] cbuf)写入一个字符数组
void write(char[] cbuf, int off, int len)写入字符数组的一部分
void write(String str)写一个字符串
void write(String str, int off, int len)写一个字符串的一部分

刷新和关闭的方法

方法名说明
flush()刷新流,之后还可以继续写数据
close()关闭流,释放资源,但是在关闭之前会先刷新流。一旦关闭,就不能再写数据

代码演示:

public class test {
    public static void main(String[] args) throws IOException {
        //文件不存在会创建,文件存在则清空
        FileWriter fileWriter = new FileWriter("a.txt");
        char[] cArr=new char[]{'a','b','中','国'};
        //直接传String数据
        fileWriter.write("来把");
        //写入一个char数组
        fileWriter.write(cArr);
        //从数组的off索引开始,写入len个长度
        fileWriter.write(cArr, 0, 2);
        fileWriter.close();
    }
}

刷新和关闭的方法
flush():
刷新流,之后还可以继续写数据
close():
关闭流,,释放资源,但是在关闭之前会先刷新流。一旦关闭,就不能再写数据
代码演示:

	public class test {
    public static void main(String[] args) throws IOException {
        //文件不存在会创建,文件存在则清空
        FileWriter fileWriter = new FileWriter("a.txt");
        char[] cArr=new char[]{'a','b','中','国'};
        //直接传String数据
        fileWriter.write("来把");
        //刷新流,流不关闭,可继续写数据
        fileWriter.flush();
        //写入一个char数组
        **fileWriter.close();**  //close之后不可在写数据,不然报错
        fileWriter.write(cArr);
        //从数组的off索引开始,写入len个长度
        fileWriter.write(cArr, 0, 2);

    }
}
报错:
java.io.IOException: Stream closed

字符流读数据

  • 介绍

Reader: 用于读取字符流的抽象父类

FileReader: 用于读取字符流的常用子类

  • 构造方法
方法名说明
FileReader(File file)在给定从中读取数据的 File 的情况下创建一个新 FileReader
FileReader(String fileName)在给定从中读取数据的文件名的情况下创建一个新 FileReader
  • 成员方法
方法名说明
int read()一次读一个字符数据
int read(char[] cbuf)一次读一个字符数组数据

代码演示:

public class test {
    public static void main(String[] args) throws IOException {
        //文件不存在会报错
        FileReader fread = new FileReader("a.txt");
        char[] cArr=new char[1024];
        int len;
        while((len=fread.read(cArr))!=-1){
            //使用String的构造方法,转char数组为String
            System.out.println(new String(cArr,0,len));
        }
        fread.close();
    }
}

小案例:

  • 案例需求

    将键盘录入的用户名和密码保存到本地实现永久化存储

  • 实现步骤

    • 获取用户输入的用户名和密码
    • 将用户输入的用户名和密码写入到本地文件中
    • 关流,释放资源
  • 代码演示:

 public class IOcase {
    public static void main(String[] args) throws IOException {
        String path="b.txt";
        SaveUP(path);
        System.out.println("=================");
        TakeUP(path);
    }

    private static void SaveUP(String path) throws IOException {
        FileWriter fwriter = new FileWriter(path);
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入你的用户名");
        String username = scanner.next();
        System.out.println("请输入密码");
        String password = scanner.next();
        fwriter.write(username);
        fwriter.write("\r\n");
        fwriter.write(password);
        fwriter.close();
    }

    private static void TakeUP(String path) throws IOException {
        FileReader freader = new FileReader(path);
        char[] cArr=new char[1024];
        int len;
        while ((len=freader.read(cArr))!=-1)
            System.out.println(new String(cArr,0,len));
        freader.close();
    }
}

字符缓冲流

字符缓冲流介绍

  • BufferedWriter:将文本写入字符输出流,缓冲字符,以提供单个字符,数组和字符串的高效写入,可以指定缓冲区大小,或者可以接受默认大小。默认值足够大,可用于大多数用途

  • BufferedReader:从字符输入流读取文本,缓冲字符,以提供字符,数组和行的高效读取,可以指定缓冲区大小,或者可以使用默认大小。 默认值足够大,可用于大多数用途(一次读取多个字符)

  • 构造方法

方法名说明
BufferedWriter(Writer out)创建字符缓冲输出流对象
BufferedReader(Reader in)创建字符缓冲输入流对象

代码演示:

public class BufferedStreamDemo01 {
    public static void main(String[] args) throws IOException {
        //BufferedWriter(Writer out)
        BufferedWriter bw = new BufferedWriter(new FileWriter("myCharStream\\bw.txt"));                                                           
        bw.write("hello\r\n");
        bw.write("world\r\n");
        bw.close();

     BufferedReader br = new BufferedReader(newFileReader("myCharStream\\bw.txt"));                                                          

        //一次读取一个字符数据
//        int ch;
//        while ((ch=br.read())!=-1) {
//            System.out.print((char)ch);
//        }

        //一次读取一个字符数组数据
        char[] chs = new char[1024];
        int len;
        while ((len=br.read(chs))!=-1) {
            System.out.print(new String(chs,0,len));
        }

        br.close();
    }
}

字符缓冲流特有功能

方法介绍

BufferedWriter:

方法名说明
void newLine()写一行行分隔符,行分隔符字符串由系统属性定义

BufferedReader:

方法名说明
String readLine()读一行文字。 结果包含行的内容的字符串,不包括任何行终止字符如果流的结尾已经到达,则为null

利用字符缓冲流修改上面的案例
代码演示:

public class IOcase {
    public static void main(String[] args) throws IOException {
        String path="b.txt";
        SaveUP(path);
        System.out.println("=================");
        TakeUP(path);
    }

    private static void SaveUP(String path) throws IOException {
        FileWriter fwriter = new FileWriter(path);
        BufferedWriter bw = new BufferedWriter(fwriter);
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入你的用户名");
        String username = scanner.next();
        System.out.println("请输入密码");
        String password = scanner.next();
        bw.write(username);
        //写一个回车,回车字符串由系统的属性定义
        bw.newLine();
        bw.write(password);
        bw.close();
    }

    private static void TakeUP(String path) throws IOException {
        FileReader freader = new FileReader(path);
        BufferedReader br = new BufferedReader(freader);
        String len;
        //readLine:读一行文字,不会读回车。返回的是String类型,不包括任何行终止字符如果流的结尾已经到达,则为null
        while ((len=br.readLine())!=null)
            System.out.println(len);
        br.close();
    }
}

小案例

需求:
取出a.txt中的数字,进行排序后再存入a.txt

public class test {
    public static void main(String[] args) throws IOException {
      //字符缓冲输入流
        BufferedReader breader = new BufferedReader(new FileReader("a.txt"));
        String str=breader.readLine();
        breader.close();
        String[] s = str.split(" ");
        System.out.println("排序前");
        System.out.println(Arrays.toString(s));
        Integer[] Iarr=new Integer[s.length];
        for (int i = 0; i < s.length; i++) {
            //String转int类型
            //转换方式:
            //方式一:先t通过Integer.valueOf()将字符串数字转成Integer,再调用intValue()方法
            //方式二:通过Integer静态方法parseInt()进行转换
            //int转换为String
            //转换方式:
            //方式一:直接在数字后加一个空字符串
            //方式二:通过String类静态方法valueOf()
           // Integer integer = new Integer(s[i]);
            int integer = Integer.parseInt(s[i]);
            Iarr[i]=integer;
        }
        System.out.println("排序后");
        Arrays.sort(Iarr);
        System.out.println(Arrays.toString(Iarr));
        BufferedWriter bw = new BufferedWriter(new FileWriter("a.txt"));
        for (int i = 0; i < Iarr.length; i++) {
            //要把int类型转为String类型存入文件中。字符缓冲流存的是字符
            bw.write(String.valueOf(Iarr[i]));
            bw.flush();
        }
        bw.close();
    }
}

IO流小结

在这里插入图片描述

转换流

  • InputStreamReader:是从字节流到字符流的桥梁,父类是Reader

    ​ 它读取字节,并使用指定的编码将其解码为字符

    ​ 它使用的字符集可以由名称指定,也可以被明确指定,或者可以接受平台的默认字符集

  • OutputStreamWriter:是从字符流到字节流的桥梁,父类是Writer

    ​ 是从字符流到字节流的桥梁,使用指定的编码将写入的字符编码为字节

    ​ 它使用的字符集可以由名称指定,也可以被明确指定,或者可以接受平台的默认字符集

JDk11以后,可直接使用字符流的构造方法,传递编码格式(FileReader)

对象操作流

  • 对象序列化介绍

    • 对象序列化:就是将对象保存到磁盘中,或者在网络中传输对象
    • 这种机制就是使用一个字节序列表示一个对象,该字节序列包含:对象的类型、对象的数据和对象中存储的属性等信息
    • 字节序列写到文件之后,相当于文件中持久保存了一个对象的信息
    • 反之,该字节序列还可以从文件中读取回来,重构对象,对它进行反序列化
  • 对象序列化流: ObjectOutputStream

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

序列化对象的方法

方法名说明
void writeObject(Object obj)将指定的对象写入ObjectOutputStream

对象需要实现 implements Serializable
注意事项

  • 一个对象要想被序列化,该对象所属的类必须必须实现Serializable 接口
  • Serializable是一个标记接口,实现该接口,不需要重写任何方法

对象的反序列化流(读)

对象反序列化流: ObjectInputStream

  • ObjectInputStream反序列化先前使用ObjectOutputStream编写的原始数据和对象
  • 构造方法
方法名说明
ObjectInputStream(InputStream in)创建从指定的InputStream读取的ObjectInputStream

反序列化对象的方法

方法名说明
Object readObject()从ObjectInputStream读取一个对象

serialVersionUID&transient

erialVersionUID

  • 用对象序列化流序列化了一个对象后,假如我们修改了对象所属的类文件,读取数据会不会出问题呢?

    • 会出问题,会抛出InvalidClassException异常
  • 如果出问题了,如何解决呢?

    • 重新序列化
    • 给对象所属的类加一个serialVersionUID
      • private static final long serialVersionUID = 42L;
        transient
  • 如果一个对象中的某个成员变量的值不想被序列化,又该如何实现呢?

    • 给该成员变量加transient关键字修饰,该关键字标记的成员变量不参与序列化过程

Properties集合

Properties介绍

  • 是一个Map体系的集合类
  • Properties可以保存到流中或从流中加载
  • 只存字符串

Properties和IO流相结合的方法

方法名说明
void load(Reader reader)从输入字符流读取属性列表(键和元素对)
void store(Writer writer, String comments)将此属性列表(键和元素对)写入此 Properties表中,以适合使用 load(Reader)方法的格式写入输出字符流

代码演示:

public class PropertiesDemo03 {
    public static void main(String[] args) throws IOException {
        //把集合中的数据保存到文件
//        myStore();

        //把文件中的数据加载到集合
        myLoad();

    }

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

        //void load(Reader reader):
        FileReader fr = new FileReader("myOtherStream\\fw.txt");
        prop.load(fr);
        fr.close();

        System.out.println(prop);
    }

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

        prop.setProperty("001","张三");
        prop.setProperty("002","李四");
        prop.setProperty("003","王二毛子");

        //void store(Writer writer, String comments):
        FileWriter fw = new FileWriter("myOtherStream\\fw.txt");
        prop.store(fw,null);
        fw.close();
    }
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值