Flie类,字节流,字符流

一,file类

1.1 概述
java.io.File 类是文件和目录路径名的抽象表示,主要用于文件和目录的创建、获取和删除等操作。
记住三个单词:file:文件、directory:文件夹/目录、path:路径

1.2 构造方法
public File(String pathname) :通过将给定的路径名字符串转换为抽象路径名来创建新的File实例。
public File(String parent, String child) :从父路径名字符串和子路径名字符串创建新的 File实例。
public File(File parent, String child) :从父抽象路径名和子路径名字符串创建新的 File实例。
// 文件路径名
String pathName = "d:\\a.txt";
File file1 = new File(pathName);
// 文件路径名
String pathName2 = "d:\\a\\b.txt";
File file2 = new File(pathName2);
// 通过父路径和子路径字符串
String parent = "d:\\a";
String child = "b.txt";
File file3 = new File(parent, child);
// 通过父级File对象和子路径字符串
File parentDir = new File("d:\\a");
String child = "b.txt";
File file4 = new File(parentDir, child);
注意:
1.一个File对象代表硬盘中实际存在的一个文件或者目录。 
2.无论该路径下是否存在文件或者目录,都不影响File对象的创建。
3.由于不同系统,路径分隔符使用不一样,在windows中是"d:\a",linux是"d:/a",
可以使用静态方法separator,路径分隔符,windows是分号,linux是冒号,用静态方法pathSeparator。
4.路径不区分大小写。

绝对路径和相对路径 
绝对路径:从盘符开始的路径,这是一个完整的路径。 
相对路径:相对于项目目录的路径,这是一个便捷的路径,开发中经常使用。
public class FilePath {
    public static void main(String[] args) {
        // D盘下的a.java文件
        File f1 = new File("D:\\a.java");
        System.out.println(f1.getAbsolutePath());
        // 项目下的a.java文件
        File f2 = new File("a.java");
        System.out.println(f2.getAbsolutePath());
    }
}
1.3 常用方法
获取功能的方法
public String getAbsolutePath() :返回此File的绝对路径名字符串。 
public String getPath() :将此File转换为路径名字符串。 
public String getName() :返回由此File表示的文件或目录的名称。 
public long length() :返回由此File表示的文件的长度。
public class FileGet {
    public static void main(String[] args) {
        File f = new File("d:/a/b.java");
        System.out.println("文件绝对路径:"+f.getAbsolutePath());
        System.out.println("文件路径:"+f.getPath());
        System.out.println("文件名称:"+f.getName());
        System.out.println("文件长度:"+f.length()+"字节");
    }
}

注意:
1.文件夹是没有大小概念的,不能获取文件夹的大小
2.如果构造方法中给出的路径不存在,那么length方法返回0
3.获取的是构造方法指定的文件的大小,以字节为单位
4.无论路径是绝对的还是相对的,getAbsolutePath方法返回的都是绝对路径

判断功能的方法
public boolean exists() :此File表示的文件或目录是否实际存在。 
public boolean isDirectory() :此File表示的是否为目录。 
public boolean isFile() :此File表示的是否为文件。
public class FileIs {
    public static void main(String[] args) {
        File f = new File("d:\\aaa\\bbb.java");
        File f2 = new File("d:\\aaa");
        // 判断是否存在
        System.out.println("d:\\aaa\\bbb.java 是否存在:"+f.exists());
        System.out.println("d:\\aaa 是否存在:"+f2.exists());
        // 判断是文件还是目录
        System.out.println("d:\\aaa 文件?:"+f2.isFile());
        System.out.println("d:\\aaa 目录?:"+f2.isDirectory());
    }
}

注意:
1.电脑的硬盘中只有文件/文件夹,两个方法是互斥
2.这两个方法使用前提,路径必须是存在的,否则都返回false

创建删除功能的方法
public boolean createNewFile() :当且仅当具有该名称的文件尚不存在时,创建一个新的空文件。 
public boolean delete() :删除由此File表示的文件或目录。 
public boolean mkdir() :创建由此File表示的目录。 
public boolean  mkdirs() :创建由此File表示的目录,包括任何必需但不存在的父目录。
public class FileCreateDelete {
    public static void main(String[] args) throws IOException {
        // 文件的创建
        File f = new File("aaa.txt");
        System.out.println("是否存在:" + f.exists()); 
        System.out.println("是否创建:" + f.createNewFile());
        System.out.println("是否存在:" + f.exists());
        // 目录的创建
        File f2 = new File("d:\\aaa");
        System.out.println("是否存在:" + f2.exists());
        System.out.println("是否创建:" + f2.mkdir()); 
        System.out.println("是否存在:" + f2.exists());
        // 创建多级目录
        File f3 = new File("d:\\workspace");
        System.out.println(f3.mkdir());
        File f4 = new File("d:\\workspace");
        System.out.println(f4.mkdirs());
        // 文件的删除
        System.out.println(f.delete());
        // 目录的删除
        System.out.println(f2.delete());
        System.out.println(f4.delete());
    }
}
注意:
    1.delete方法是直接在硬盘删除文件/文件夹,不走回收站,删除要谨慎
2.public boolean mkdir() :创建单级空文件夹,public boolean mkdirs() :既可以创建单级空文件夹,也可以创建多级文件夹

1.4 目录的遍历
public String[] list() :返回一个String数组,表示该File目录中的所有子文件或目录。 
public File[] listFiles() :返回一个File数组,表示该File目录中的所有的子文件或目录。
public class FileFor {
    public static void main(String[] args) {
        File dir = new File("d:\\workspace");
        //获取当前目录下的文件以及文件夹的名称。
        String[] names = dir.list();
        for(String name : names){
            System.out.println(name);
        }
        //获取当前目录下的文件以及文件夹对象
        File[] files = dir.listFiles();
        for (File file : files) {
            System.out.println(file);
        }
    }
}

注意:
list方法和listFiles方法遍历的是构造方法中给出的目录,如果构造方法中给出的目录的路径不存在,会抛出空指针异常,如果构造方法中给出的路径不是一个目录,也会抛出空指针异常

1.5 递归打印多级目录
分析:多级目录的打印,就是目录的嵌套。遍历之前,无从知道到底有多少级目录,所以我们还是要使用递归实现。(终止条件就是当前遍历项是文件名)
public class DiGuiDemo2 {
    public static void main(String[] args) {
        // 创建File对象
        File dir = new File("D:\\workspace");
        // 调用打印目录方法
        printDir(dir);
    }
    public static void printDir(File dir) {
        // 获取子文件和目录
        File[] files = dir.listFiles();
        // 循环打印
        for (File file : files) {
            //对遍历得到的File对象f进行判断,判断是否是文件夹
            if (file.isFile()) {
                // file是文件,输出文件绝对路径
                System.out.println("文件名:"+ file.getAbsolutePath());
            } else {
                // 是目录,输出目录绝对路径
                System.out.println("目录:"+file.getAbsolutePath());
                // 继续遍历,调用printDir,形成递归
                printDir(file);
            }
        }
    }
}
1.6 文件搜索
搜索 D:\workspace 目录中的 .java 文件。
分析: 
1.目录搜索,无法判断多少级目录,所以使用递归,遍历所有目录。 
2.遍历目录时,获取的子文件,通过文件名称,判断是否符合条件。
目录不存在,会报NullPointerException异常
public class DiGuiDemo3 {
    public static void main(String[] args) {
        // 创建File对象
        File dir = new File("D:\\workspace");
        // 调用打印目录方法
        printDir(dir);
    }
    public static void printDir(File dir) {
        // 获取子文件和目录
        File[] files = dir.listFiles();
        // 循环打印
        for (File file : files) {
            if (file.isFile()) {
                // file是文件,判断文件名并输出文件绝对路径
                if (file.getName().endsWith(".java")) {
                    System.out.println("文件名:" + file.getAbsolutePath());
                }
            } else {
                // 是目录,继续遍历,形成递归
                printDir(file);
            }
        }
    }
}
1.7 文件过滤器优化
java.io.FileFilter是一个接口,是File的过滤器。 该接口的对象可以传递给File类的listFiles(FileFilter ff) 作为参数, 接口中只有一个方法。
boolean accept(File pathname) :测试pathname是否应该包含在当前File目录中,符合则返回true。
分析:
 1. 接口作为参数,需要传递子类对象,重写其中方法。我们选择匿名内部类方式,比较简单。 
2. accept 方法,参数为File,表示当前File下所有的子文件和子目录。保留住则返回true,过滤掉则返回 false。
保留规则: 
1.要么是.java文件。 
2.要么是目录,用于继续遍历。 
3.通过过滤器的作用, listFiles(FileFilter) 返回的数组元素中,子文件对象都是符合条件的,可以直接打印。
代码实现:
过滤器FileFilter的实现类:
public class FileFilterImpl implements FileFilter{
    @Override
    public boolean accept(File pathname) {
        //如果pathname是一个文件夹,返回true,继续遍历这个文件夹
        if(pathname.isDirectory()){
            return true;
        }

        return pathname.getName().toLowerCase().endsWith(".java");
    }
}
测试类1public class Demo01Filter {
    public static void main(String[] args) {
        File file = new File("D:\\workspace");
        getAllFile(file);
    }
    public static void getAllFile(File dir){
        File[] files = dir.listFiles(new FileFilterImpl());//传递过滤器对象
        for (File f : files) {
            //对遍历得到的File对象f进行判断,判断是否是文件夹
            if(f.isDirectory()){
                //f是一个文件夹,则继续遍历这个文件夹
                getAllFile(f);
            }else{
                //f是一个文件,直接打印即可
                System.out.println(f);
            }
        }
    }
}
测试类2public class Demo02Filter {
    public static void main(String[] args) {
        File file = new File("D:\\workspace");
        getAllFile(file);
    }

    public static void getAllFile(File dir){
        //传递过滤器对象 使用匿名内部类
        File[] files = dir.listFiles(new FileFilter() {
            @Override
            public boolean accept(File pathname) {
                //过滤规则,pathname是文件夹或者是.java结尾的文件返回true
                return pathname.isDirectory() || pathname.getName().toLowerCase().endsWith(".java");
            }
        });

        for (File f : files) {
            //对遍历得到的File对象f进行判断,判断是否是文件夹
            if(f.isDirectory()){
                //f是一个文件夹,则继续遍历这个文件夹
                getAllFile(f);
            }else{
                //f是一个文件,直接打印即可
                System.out.println(f);
            }
        }
    }
}

二,字节流

1.1 什么是IO
生活中,你肯定经历过这样的场景。当你编辑一个文本文件,忘记了 ctrl+s ,可能文件就白白编辑了。当你电脑 插入一个U盘,可以把一个视频,拷贝到你的电脑硬盘里。那么数据都是在哪些设备上的呢?键盘、内存、硬盘、外接设备等等。我们把这种数据的传输,可以看做是一种数据的流动,按照流动的方向,以内存为基准,分为输入input和输出output,即流向内存是输入流,流出内存的输出流。
Java中I/O操作主要是指使用 java.io 包下的内容,进行输入、输出操作。输入也叫做读取数据,输出也叫做作写出数据。

1.2 IO的分类
  根据数据的流向分为:输入流和输出流。
输入流 :把数据从其他设备上读取到内存中的流。 
输出流 :把数据从内存中写出到其他设备上的流。
根据数据的类型分为:字节流和字符流。
字节流 :以字节为单位,读写数据的流。 
字符流 :以字符为单位,读写数据的流。

1.3顶级父类
在这里插入图片描述字节流
一切文件数据(文本、图片、视频等)在存储时,都是以二进制数字的形式保存,都一个一个的字节,那么传输时一样如此。所以,字节流可以传输任意文件数据。在操作流的时候,我们要时刻明确,无论使用什么样的流对象,底层传输的始终为二进制数据。

2.1 字节输出流OutputStream
java.io.OutputStream 抽象类是表示字节输出流的所有类的超类,将指定的字节信息写出到目的地。它定义了字节输出流的基本共性功能方法。
public void close() :关闭此输出流并释放与此流相关联的任何系统资源。 
public void flush() :刷新此输出流并强制任何缓冲的输出字节被写出。 
public void write(byte[] b) :将 b.length字节从指定的字节数组写入此输出流。 
public void write(byte[] b, int off, int len) :从指定的字节数组写入 len字节,从偏移量 off开始输 出到此输出流。 
public abstract void write(int b) :将指定的字节输出流。

2.2 FileOutputStream类
OutputStream 有很多子类,java.io.FileOutputStream 类是文件输出流,用于将数据写出到文件。
当你创建一个流对象时,必须传入一个文件路径。《**该路径下,如果没有这个文件,会创建该文件**》。如果有这个文件,会清空这个文件的数据。

构造方法:
    FileOutputStream(String name):创建一个向具有指定名称的文件中写入数据的输出文件流。
    FileOutputStream(File file):创建一个向指定 File 对象表示的文件中写入数据的文件输出流。
    参数:写入数据的目的
        String name:目的地是一个文件的路径
        File file:目的地是一个文件
    构造方法的作用:
        1.创建一个FileOutputStream对象
        2.会根据构造方法中传递的文件/文件路径,创建一个空的文件
        3.会把FileOutputStream对象指向创建好的文件
public class FileOutputStreamConstructor  {
    public static void main(String[] args) throws FileNotFoundException {
        // 使用File对象创建流对象
        File file = new File("a.txt");
        FileOutputStream fos1 = new FileOutputStream(file);
        // 使用文件名称创建流对象
        FileOutputStream fos2 = new FileOutputStream("D:\\a.txt");
    }
}
写出字节数据:
写出数据的原理(内存-->硬盘):
        java程序-->JVM(java虚拟机)-->OS(操作系统)-->OS调用写数据的方法-->把数据写入到文件中

字节输出流的使用步骤(重点):
    1.创建一个FileOutputStream对象,构造方法中传递写入数据的目的地
    2.调用FileOutputStream对象中的方法write,把数据写入到文件中
    3.释放资源(流使用会占用一定的内存,使用完毕要把内存清空,提供程序的效率)
1.写出字节: write(int b) 方法,每次可以写出一个字节数据,代码使用演示:
public class FOSWrite {
	    public static void main(String[] args) throws IOException {
	        //1.创建一个FileOutputStream对象,构造方法中传递写入数据的目的地
	        FileOutputStream fos = new FileOutputStream("D:\\a.txt");
	        //2.调用FileOutputStream对象中的方法write,把数据写入到文件中
	        fos.write(97); 
	        fos.write(98); 
	        fos.write(99); 
	        // 关闭资源
	        fos.close();
	    }
	}
2.写出字节数组: write(byte[] b) ,每次可以写出数组中的数据,代码使用演示:
public class FOSWrite {
    public static void main(String[] args) throws IOException {
        //1.创建一个FileOutputStream对象,构造方法中传递写入数据的目的地
        FileOutputStream fos = new FileOutputStream("D:\\a.txt");
        //2.创建字节数组
        byte[] b = "Good Good Study".getBytes();
        //3.调用FileOutputStream对象中的方法write,把数据写入到文件中
        fos.write(b);
        // 关闭资源
        fos.close();
    }
}
3.写出指定长度字节数组: write(byte[] b, int off, int len) ,每次写出从off索引开始,len个字节,代码使用演示:
public class FOSWrite {
	    public static void main(String[] args) throws IOException {
	        // 使用文件名称创建流对象
	        FileOutputStream fos = new FileOutputStream("D:\\a.txt");
	        // 字符串转换为字节数组
	        byte[] b = "day day up".getBytes();
	        // 写出从索引2开始,2个字节
	        fos.write(b,2,2);
	        // 关闭资源
	        fos.close();
	    }
	}

注意:
①如果写的第一个字节是正数(0-127),那么显示的时候会查询ASCII表
②如果写的第一个字节是负数,那第一个字节会和第二个字节,两个字节组成一个中文显示,查询系统默认码表(GBK)

数据追加续写:
经过以上的演示,每次程序运行,创建输出流对象,都会清空目标文件中的数据。如何保留目标文件中数据,还能继续添加新数据呢?
public FileOutputStream(File file, boolean append) : 创建文件输出流以写入由指定的 File对象表示的文件。 
public FileOutputStream(String name, boolean append) : 创建文件输出流以指定的名称写入文件。
这两个构造方法,参数中都需要传入一个boolean类型的值, true 表示追加数据, false 表示清空原有数据。这样创建的输出流对象,就可以指定是否追加续写了
public class FOSWrite {
    public static void main(String[] args) throws IOException {
        // 使用文件名称创建流对象
        FileOutputStream fos = new FileOutputStream("D:\\a.txt",true);
        // 字符串转换为字节数组
        byte[] b = "day day up".getBytes();
        // 写出从索引2开始,2个字节
        fos.write(b,2,2);
        // 关闭资源
        fos.close();
    }
}

写出换行
Windows系统里,换行符号是 \r\n 。把以指定是否追加续写了,代码使用演示:

public class FOSWrite {
    public static void main(String[] args) throws IOException {
        // 使用文件名称创建流对象
        FileOutputStream fos = new FileOutputStream("D:\\a.txt");
        // 定义字节数组
        byte[] words = {97,98,99,100,101};
        // 遍历数组
        for (int i = 0; i < words.length; i++) {
        // 写出一个字节
            fos.write(words[i]);
        // 写出一个换行, 换行符号转成数组写出
            fos.write("\r\n".getBytes());
        }
        // 关闭资源
        fos.close();
    }
}

注意:
回车符 \r 和换行符 \n :
回车符:回到一行的开头(return)。
换行符:下一行(newline)。
系统中的换行:
Windows系统里,每行结尾是回车+换行,即 \r\n ;
Linux系统里,每行结尾只有换行,即 \n ;
Mac系统里,每行结尾是 回车,即 \r 。

2.3 字节输入流InputStream
java.io.InputStream 抽象类是表示字节输入流的所有类的超类,可以读取字节信息到内存中。它定义了字节输入流的基本共性功能方法。
public void close() :关闭此输入流并释放与此流相关联的任何系统资源。  
public abstract int read() :从输入流读取数据的下一个字节。 
public int read(byte[] b) :从输入流中读取一些字节数,并将它们存储到字节数组中。

2.4 FileInputStream类
java.io.FileInputStream 类是文件输入流,从文件中读取字节。

构造方法:
FileInputStream(File file) : 通过打开与实际文件的连接来创建一个FileInputStream ,该文件由文件系统中的 File对象 file命名。 
FileInputStream(String name) : 通过打开与实际文件的连接来创建一个 
FileInputStream ,该文件由文件系统中的路径名 name命名。 当你创建一个流对象时,必须传入一个文件路径。该路径下,如果没有该文件,会抛出 FileNotFoundException 。 
public class FileInputStreamConstructor {
    public static void main(String[] args) throws FileNotFoundException {
        // 使用File对象创建流对象
        File file = new File("a.txt");
        FileInputStream fos1 = new FileInputStream(file);
        // 使用文件名称创建流对象
        FileInputStream fos2 = new FileInputStream("b.txt");
    }
}
读取数据的原理(硬盘-->内存)
    java程序-->JVM-->OS-->OS调用读取数据的方法-->读取文件

字节输入流的使用步骤(重点):
    1.创建FileInputStream对象,构造方法中绑定要读取的数据源
    2.使用FileInputStream对象中的方法read,读取文件
    3.释放资源

读取字节数据 
1.读取字节: read()方法,每次可以读取一个字节的数据,提升为int类型,读取到文件末尾,返回 -1,代码使用演示:
public class FISRead {
    public static void main(String[] args) throws IOException{
        // 使用文件名称创建流对象
        FileInputStream fis = new FileInputStream("D:\\a.txt");
        // 读取数据,返回一个字节
        int b;
        // 循环读取
        while ((b = fis.read())!=-1) {
            System.out.println((char)b);
        }
        // 关闭资源
        fis.close();
    }
}
2.使用字节数组读取: read(byte[] b) ,每次读取b长度个字节到数组中,返回读取到的有效字节个数,读取到末尾时,返回 -1 。
明确两件事情:
    1.方法的参数byte[]的作用?
        起到缓冲作用,存储每次读取到的多个字节
        数组的长度一般定义为1024(1kb)或者1024的整数倍
    2.方法的返回值int是什么?
        每次读取的有效字节个数

String类的构造方法
    String(byte[] bytes) :把字节数组转换为字符串
    String(byte[] bytes, int offset, int length) 把字节数组的一部分转换为字符串 offset:数组的开始索引 length:转换的字节个数
public class FISRead {
    public static void main(String[] args) throws IOException {
        // 使用文件名称创建流对象.
        FileInputStream fis = new FileInputStream("D:\\a.txt");//112233a
        // 定义变量,作为有效个数
        int len;
        // 定义字节数组,作为装字节数据的容器
        byte[] b = new byte[2];
        // 循环读取
        while ((len = fis.read(b)) != -1) {
            // 每次读取后,把数组变成字符串打印
            System.out.println(new String(b));
        }
        // 关闭资源
        fis.close();
    }
}
错误数据 3 ,是由于最后一次读取时,只读取一个字节 a ,数组中,上次读取的数据没有被完全替换,所以要通过 len ,获取有效的字节,代码使用演示:
public class FISRead {
    public static void main(String[] args) throws IOException {
        // 使用文件名称创建流对象.
        FileInputStream fis = new FileInputStream("D:\\a.txt");//112233a
        // 定义变量,作为有效个数
        int len;
        // 定义字节数组,作为装字节数据的容器
        byte[] b = new byte[2];
        // 循环读取
        while ((len = fis.read(b)) != -1) {
            // 每次读取后,把数组变成字符串打印
            System.out.println(new String(b,0,len));// len 每次读取的有效字节个数

        }
        // 关闭资源
        fis.close();
    }
}

三,字符流

当使用字节流读取文本文件时,可能会有一个小问题。就是遇到中文字符时,可能不会显示完整的字符,那是因为一个中文字符可能占用多个字节存储。所以Java提供一些字符流类,以字符为单位读写数据,专门用于处理文本文件。(GBK:占用两个字节;UTF-8:占用3个字节)

3.1 字符输入流Reader
java.io.Reader 抽象类是表示用于读取字符流的所有类的超类,可以读取字符信息到内存中。它定义了字符输入流的基本共性功能方法。 
public void close() :关闭此流并释放与此流相关联的任何系统资源。 
public int read() : 从输入流读取一个字符。 
public int read(char[] cbuf) : 从输入流中读取一些字符,并将它们存储到字符数组 cbuf中。

3.2 FileReader类
java.io.FileReader 类是读取字符文件的便利类。构造时使用系统默认的字符编码和默认字节缓冲区。

注意:
1.字符编码:字节与字符的对应规则。Windows系统的中文编码默认是GBK编码表。 idea中UTF-8 
2.字节缓冲区:一个字节数组,用来临时存储字节数据。

构造方法:
FileReader(File file) : 创建一个新的 FileReader ,给定要读取的File对象。 
FileReader(String fileName) : 创建一个新的 FileReader ,给定要读取的文件的名称。

构造方法:
    FileReader(String fileName)
    FileReader(File file)
    参数:读取文件的数据源
        String fileName:文件的路径
        File file:一个文件
    FileReader构造方法的作用:
        1.创建一个FileReader对象
        2.会把FileReader对象指向要读取的文件

字符输入流的使用步骤:
    1.创建FileReader对象,构造方法中绑定要读取的数据源
    2.使用FileReader对象中的方法read读取文件
    3.释放资源


读取字符数据
1.读取字符: read 方法,每次可以读取一个字符的数据,提升为int类型,读取到文件末尾,返回 -1 ,循环读 取,代码使用演示:
public class FRRead {
    public static void main(String[] args) throws IOException {
        // 使用文件名称创建流对象
        FileReader fr = new FileReader("D:\\a.txt");//112233a
        // 定义变量,保存数据
        int b;
        // 循环读取
        while ((b = fr.read()) != -1) {
            System.out.println((char) b);
        }
        // 关闭资源
        fr.close();
    }

}
2.使用字符数组读取: read(char[] cbuf) ,每次读取b的长度个字符到数组中,返回读取到的有效字符个数, 读取到末尾时,返回 -1 ,代码使用演示:

public class FRRead {
    public static void main(String[] args) throws IOException {
        // 使用文件名称创建流对象
        FileReader fr = new FileReader("D:\\a.txt");//112233a
        // 定义变量,保存有效字符个数
        int len;
        // 定义字符数组,作为装字符数据的容器
        char[] cbuf = new char[3];
        // 循环读取
        while ((len = fr.read(cbuf)) != -1) {
            System.out.println(new String(cbuf));
        }
        // 关闭资源
        fr.close();
    }
}
获取有效的字符改进,代码使用演示:
public class FRRead {
    public static void main(String[] args) throws IOException {
        // 使用文件名称创建流对象
        FileReader fr = new FileReader("D:\\a.txt");//112233a
        // 定义变量,保存有效字符个数
        int len;
        // 定义字符数组,作为装字符数据的容器
        char[] cbuf = new char[2];
        // 循环读取
        while ((len = fr.read(cbuf)) != -1) {
            System.out.println(new String(cbuf,0,len));
        }
        // 关闭资源
        fr.close();
    }
}
3.3 字符输出流Writer
java.io.Writer 抽象类是表示用于写出字符流的所有类的超类,将指定的字符信息写出到目的地。它定义了字节 输出流的基本共性功能方法。
pulic void write(int c) 写入单个字符。 
pulic void write(char[] cbuf) 写入字符数组。 
pulic abstract void write(char[] cbuf, int off, int len) 写入字符数组的某一部分,off数组的开始索引,len 写的字符个数。 
pulic void write(String str) 写入字符串。 
pulic void write(String str, int off, int len) 写入字符串的某一部分,off字符串的开始索引,len写的字符个 数。 
public void flush() 刷新该流的缓冲。 
public void close() 关闭此流,但要先刷新它。

3.4 FileWriter类
java.io.FileWriter 类是写出字符到文件的便利类。构造时使用系统默认的字符编码和默认字节缓冲区。

构造方法: 
FileWriter(File file) :创建一个新的 FileWriter,给定要读取的File对象。 
FileWriter(String fileName) :创建一个新的 FileWriter,给定要读取的文件的名称。

构造方法:
    FileWriter(File file)根据给定的 File 对象构造一个 FileWriter 对象。
    FileWriter(String fileName) 根据给定的文件名构造一个 FileWriter 对象。
    参数:写入数据的目的地
        String fileName:文件的路径
        File file:是一个文件

构造方法的作用:
        1.会创建一个FileWriter对象
        2.会根据构造方法中传递的文件/文件的路径,创建文件
        3.会把FileWriter对象指向创建好的文件
字符输出流的使用步骤(重点):
    1.创建FileWriter对象,构造方法中绑定要写入数据的目的地
    2.使用FileWriter中的方法write,把数据写入到内存缓冲区中(字符转换为字节的过程)
    3.使用FileWriter中的方法flush,把内存缓冲区中的数据,刷新到文件中
    4.释放资源(会先把内存缓冲区中的数据刷新到文件中)
public class FileWriterConstructor {
    public static void main(String[] args) throws IOException {
        // 使用File对象创建流对象
        File file = new File("a.txt");
        FileWriter fw1 = new FileWriter(file);
        // 使用文件名称创建流对象
        FileWriter fw2 = new FileWriter("b.txt");
    }
}
写出数据 
	写出字符: write(int b) 方法,每次可以写出一个字符数据,代码使用演示:
public class FWWrite {
    public static void main(String[] args) throws IOException {
        // 使用文件名称创建流对象
        FileWriter fw = new FileWriter("D:\\a.txt");
        // 写出数据
        fw.write(97); // 写出第1个字符
        fw.write('b'); // 写出第2个字符
        fw.write('C'); // 写出第3个字符
        fw.write(30000); // 写出第4个字符,中文编码表中30000对应一个汉字。
        fw.close();//关闭流
    }
}
注意:关闭资源时,与FileOutputStream不同。如果不关闭,数据只是保存到缓冲区,并未保存到文件。

关闭和刷新
因为内置缓冲区的原因,如果不关闭输出流,无法写出字符到文件中。但是关闭的流对象,是无法继续写出数据的。如果我们既想写出数据,又想继续使用流,就需要 flush 方法了。
flush :刷新缓冲区,流对象可以继续使用。 
close :先刷新缓冲区,然后通知系统释放资源。流对象不可以再被使用了。
代码使用演示:
public class FWWrite {
    public static void main(String[] args) throws IOException {
        // 使用文件名称创建流对象
        FileWriter fw = new FileWriter("D:\\a.txt");
        // 写出数据,通过flush
        fw.write('刷'); // 写出第1个字符
        fw.flush();
        fw.write('新'); // 继续写出第2个字符,写出成功
        fw.flush();
        // 写出数据,通过close
        fw.write('关'); // 写出第1个字符
        fw.close();
//        fw.write('闭'); // 继续写出第2个字符,【报错】java.io.IOException: Stream closed
//        fw.close();
    }
}
写出其他数据
1.写出字符数组 : write(char[] cbuf) 和 write(char[] cbuf, int off, int len) ,每次可以写出字符数组中的数据,用法类似FileOutputStream,代码使用演示:
public class FWWrite {
    public static void main(String[] args) throws IOException {
        // 使用文件名称创建流对象
        FileWriter fw = new FileWriter("D:\\a.txt");
        // 字符串转换为字节数组
        char[] chars = "hello man".toCharArray();
        // 写出从索引2开始,2个字节。
        fw.write(chars,2,2); 
        // 关闭资源
        fw.close();
    }
}
2. 写出字符串: write(String str) 和 write(String str, int off, int len) ,每次可以写出字符串中的 数据,更为方便,代码使用演示:
public class FWWrite {
    public static void main(String[] args) throws IOException {
        // 使用文件名称创建流对象
        FileWriter fw = new FileWriter("D:\\a.txt");
        // 字符串
        String msg = "程序员";
        // 写出从索引2开始,2个字节。
        fw.write(msg, 2, 1);
        // 关闭资源
        fw.close();
    }
}

练习:修改代码,完成续写和换行。

public class FWWrite {
    public static void main(String[] args) throws IOException {
        // 使用文件名称创建流对象,可以续写数据
        FileWriter fw = new FileWriter("D:\\a.txt",true);
        // 写出字符串
        fw.write("hello");
        // 写出换行
        fw.write("\r\n");
        // 写出字符串
        fw.write("man");
        // 关闭资源
        fw.close();
    }
}

注意:字符流,只能操作文本文件,不能操作图片,视频等非文本文件。当我们单纯读或者写文本文件时使用字符流其他情况使用字节流。

好的,我来为您整理一下 File 字节流字符流的相关知识点。 1. File File Java 中用于操作文件和目录的,可以用来创建、删除、重命名、遍历目录等操作。常用的方法有: - exists():判断文件或目录是否存在 - isFile():判断是否为文件 - isDirectory():判断是否为目录 - createNewFile():创建新文件 - mkdir():创建新目录 - delete():删除文件或目录 - renameTo():重命名文件或目录 - list():获取目录下的所有文件名 - listFiles():获取目录下的所有文件对象 2. 字节流 字节流是以字节为单位进行读写的流,常用的字节流有 FileInputStream 和 FileOutputStream。它们可以用来读写二进制文件,如图片、音频、视频等。常用的方法有: - read():读取一个字节 - write():写入一个字节 - read(byte[]):读取一定数量的字节到字节数组中 - write(byte[]):写入字节数组中的数据 - close():关闭流 3. 字符流 字符流是以字符为单位进行读写的流,常用的字符流有 FileReader 和 FileWriter。它们可以用来读写文本文件,如 .txt 文件。常用的方法有: - read():读取一个字符 - write():写入一个字符 - read(char[]):读取一定数量的字符到字符数组中 - write(char[]):写入字符数组中的数据 - close():关闭流 总的来说,字节流适用于读写二进制文件,字符流适用于读写文本文件。同时,在使用流时应该注意及时关闭流,以防止资源浪费和文件损坏。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值