JAVA学习 API_day09(文件操作, I/O流)

1. 文件操作

IO: Input/读文件 Output/写文件
所属软件包: java.io

1.File - 文件类, 可以表示文件或者目录

构造方法:
   new File(String 文件路径)
   new File(String 父路径, String 子路径)
常用API:
   获得文件/目录的绝对路径
   获得file对象中所有的文件 listFiles()
    File file = new File(".");
    file.listFiles(new FileFilter() {
        @Override
        public boolean accept(File f) {
            // 处理了f, 让他返回true, 表示f要保留
            // 处理了f, 返回false, 表示f不想保留了
            return false;
        }
    });
    // filter.accept(f) --> 返回true

    public File[] listFiles(FileFilter filter) {
        // 得到了这个目录下面所有的文件名字
        String ss[] = list();
        if (ss == null) return null;
        // 创建了一个存储File对象的集合
        ArrayList<File> files = new ArrayList<>();
        // 迭代这个名字的数组
        for (String s : ss) {
            // 使用文件名, 创建了一个对应的File对象
            File f = new File(s, this);
            if ((filter == null) || filter.accept(f))
                // 当accept方法返回true, 将这个文件对象加入到list列表中
                files.add(f);
        }
        // 将list变成数组返回
        return files.toArray(new File[files.size()]);
    }

2.路径

绝对路径: window是 - 从盘符开始 C:\xx\xx...
         Linux是 - /xx/xx (从根目录开始)
相对路径: 会有一个参照对象  a.txt
         参考值: /Users/bonnie/Desktop 相对路径是: a.txt
            那么a.txt的真实路径: /Users/bonnie/Desktop/a.txt
         现在a.txt的真实路径: /Users/bonnie/IdeaWorks/corejava/API_day09/a.txt
            那么现在的参考值: /Users/bonnie/IdeaWorks/corejava/API_day09

         参考值 我们称之为 - 当前目录

         参考值: C:\IdeaWorks\day09\src   相对路径: com/zzxx/demo01/a.txt
            那么a.txt的真实路径: C:/IdeaWorks/day09/src/com/zzxx/demo01/a.txt
         . : 当前目录 - 现在的参考值
         ..: 上一级目录 - 现在的参考值 往上一层

根据相对路径, 获得当前程序环境下的绝对路径
复习: 1.xx.class.getResource("相对路径") -> 得到一个绝对路径
     2.xx.class.getClassLoader().getResource("相对路径") -> 得到一个绝对路径

注意:
  类路径 classpath: 就是src编译后的目录, 也叫编译根目录
  以上 1 和 2 代码得到的绝对路径, 都是在编译后的目录中, 和src没有直接关系
  在开发中, 我们是先将文件放入src中的, 会自动编译到类路径中
import org.junit.Test;

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

public class FileDemo {
    @Test
    public void test01(){
        //传输文件的相对路径给File的构造方法,创建File对象
        //路径的参考值为当前module目录 E:\ideaWorkplace\com
        //注意:new 出来的文件对象只在jvm中存在,和本地磁盘有没有这个文件无关
        File file1 = new File("a/b/c.txt");
        System.out.println(file1);//File类的toString方法已经重写
        // 输出文件路径和文件名 参考值:(E:\ideaWorkplace\com\) + 相对路径:(a\b\c.txt) 括号和+只是为了分隔路径的参考值以及相对路径
        //参考值改变,相对路径所代表的绝对路径也会改变

        //传输文件父路径和子路径给File的构造方法,创建File对象
        File file2 = new File("a/b", "b/c.txt");
        System.out.println(file2);
        //获取绝对路径(即文件存在的真实路径),windows从盘符开始
        System.out.println(file1.getAbsolutePath());
        //
    }
    @Test
    public void test02(){
        //class.getResource 查找具有给定名称的资源
        // url.getPath()获取此 URL的路径部分。
        //在编译后(注意:class文件为字节码文件,是编译后的文件,所以找的是out目录中的包目录)的包目录下查找具有给定名称的资源,获取资源a.txt存在的目录
       String path = FileDemo.class.getResource("com/hzt/file/a.txt").getPath();
       //a.txt 路径参考值:当前类的编译目录 - 就是当前这个包
        //直接理解为:a.txt 和当前这个类 同一包
       System.out.println(path);
    }

    @Test
    public void test03(){
        //getClassLoader 返回类的类加载器
/*      在编译后(注意:class文件为字节码文件,而getClassLoader是获取了此类的类加载器类,相当于模组的编译后的文件目录,
        所以找的是out目录中的模组目录)的模组目录下查找具有给定名称的资源,获取资源a.txt存在的目录*/
        String path = FileDemo.class.getClassLoader().getResource("com/hzt/file/a.txt").getPath();
        //b.txt 路径的参考值:当前这个模块编译后的根目录 classpath
        //直接理解为: a.txt 就是在src下的
        System.out.println(path);
    }

    @Test
    public void test04(){
        File file = new File("src/com/hzt/file/a.txt");//文件相对路径为 src/com/hzt/file/a.txt
        //判断此文件或目录是否存在
        System.out.println(file.exists());
        //创建此文件对象的文件或目录
        //windows系统中\/都可以用作路径分隔符,但是在字符串中\需要转义且/在linux和windows中都可以用,所以推荐用/
        //因为路径的参考值为当前module目录 E:\ideaWorkplace\com,所以文件创建在了E:\ideaWorkplace\com/src/com/hzt/file/a.txt
        try {
            file.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
        }
        //判断此文件是否为目录
        System.out.println(file.isDirectory());
        //判断此文件是否为文件
        System.out.println(file.isFile());
        //删除此文件 返回true为删除成功
        System.out.println(file.delete());//delete方法,如果此File表示目录,则目录必须为空才能删除。否则必须先删除目录中的文件
        //以上方法返回值均为boolean类型
    }

    @Test
    public void test05(){
        File file = new File("src/newDir");
        System.out.println(file.exists());//目录是否存在
        System.out.println(file.mkdir());//创建目录
        System.out.println(file.exists());
        File file1 = new File("src/parentDir/newDir");//创建多级目录文件
        System.out.println(file1.exists());
        System.out.println(file1.mkdir());//因为只能在已有目录下在创建一级目录,所以会返回false创建失败
        System.out.println(file1.mkdirs());//创建多级目录
        File file2 = new File("src/parentDir/newDir1");//创建多级目录文件
        file2.mkdirs();
    }

    @Test
    public void test06(){
        //创建一个File对象,"."表示参考值即当前模组目录
        File file = new File(".");
        System.out.println(file.getAbsolutePath());//当前文件的绝对目录为E:\ideaWorkplace\com\.
        //创建一个File数组,存储file对象中所有的文件和目录
        //file对象是文件,数组为null, file对象是空文件夹,数组存在有地址且长度为0
        File[] files = file.listFiles();
        for(File f: files){
            //因为存储类型为File类型所以可以使用文件对象的方法
            System.out.println(f + "此文件对象为是否为文件:" + f.isFile());
        }
        //返回一个String数组,表示file对象中的所有文件和目录
        String[] strings = file.list();
        for(String s: strings){
            System.out.println(s);
        }
    }

    @Test
    public void test07(){
        //创建一个File对象,".."表示参考值的上一级目录
        File file = new File("../com/src/com/hzt");
        System.out.println(file.getAbsolutePath());
        //文件过滤器 FileFilter
        //FileFilter为函数式接口,只有一个抽象方法,作为listFiles方法的参数用于过滤文件,过滤条件通过重写accept方法自定义
        //创建File数组,存储file文件下的所有文件和文件夹
        File[] files = file.listFiles(new FileFilter() {
            @Override
            public boolean accept(File pathname) {
                return true;//接受所有文件
            }
        });
        //函数式接口在作为方法参数时可以用lambda表达式简化
        //重写accept方法为只保留文件,不保留目录
        File[] files1 = new File(".").listFiles((pathname)->{return pathname.isFile();});
        System.out.println("只接受文件");
        for(File f: files1){
            System.out.println(f.getName());//输出数组中的文件名
        }
        //只接受后缀名为.txt的文件
        System.out.println("只接受后缀名为.txt的文件");
        files1 = new File(".").listFiles((p)->{ return p.getName().endsWith(".txt");});
        for(File f: files1){
            System.out.println(f.getName());//输出数组中的文件名
        }
    }

    @Test
    public void test08(){
        //创建文件
        try {
            new File("./src/newDir/a").mkdirs();
            new File("./src/newDir/a/c.txt").createNewFile();
            new File("./src/newDir/a/a.txt").createNewFile();
            new File("./src/newDir/b.txt").createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
        }
        //调用deleteDirectory方法删除非空目录
        File file = new File("./src/newDir");
        deleteDirectory(file);
    }

    public void deleteDirectory(File file){
        //用迭代删除非空文件夹
        //创建要删除的文件夹对象数组
        File[] files = file.listFiles();
        //如果文件类型是目录,目录为空的情况因为长度是0所以无法进入foreach循环所以对判断无影响 调用方法删除文件夹对象中的文件
        if(file.isDirectory()){
            for (File f: files){
                deleteDirectory(f);
            }
        }
        //如果文件类型是文件 直接删除
        file.delete();
    }
}

2. IO 流

1.以单位来分: 字节流 字符流
2.以层级来分: 底层流 包装流

字节流: InputStream/OutputStream
子类: FileInputStream/FileOutputStream
字符流: Reader/Writer

注意:
1.IO所有跟文件相关的流中, 构造方法中需要File作为参数的都可以使用文件路径直接取代
2.字节流写和读都是以字节为单位的, 单个字节能不能正常显示出来, 是不确定的

字节流

API:
void write(int) : 写入这个int值得低八位
int read() : 读文件中一个字节, 并且存入int的低八位, 其余空位补0
当返回 -1 的时候, 说明文件读到了末尾

import org.junit.Test;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class File_IO_Demo {
    //file字节输出流(用程序把字节写入文件)
    @Test
    public void FileOutput() throws IOException {
        //创建文件输出流对象,参数为(File file/ String path[, append true])
        //参数中的所有文件类对象都可以用路径字符串替换(jdk中创建了构造方法来简化), append = true为在文件末尾写入即为可拼接,默认为false即直接重写
        //如果目标输出文件不存在,则创建一个文件
        FileOutputStream os = new FileOutputStream("./src/com/hzt/stream/a.txt",true);
        //使用输出流对象的write方法写入字节
        //重载1:参数为int write只写入参数转化为二进制补码(java中所有基本数据类型都以二进制补码存储)后的低八位bit数据
        os.write(0);//写入 00000000 00000000 00000000 00000000 的低8位 00000000 转化为空白字符
        os.write(97);//写入 00000000 00000000 00000000 01100001 的低8位 01100001 转化为字符为a
        os.write(48);//写入 00000000 00000000 00000000 00110000 的低8位 01100001 转化为字符为0
        os.write(-1);//写入 11111111 11111111 11111111 11111111 的低8位 11111111 255转化为无法识别的字符
        //关闭输出流
        os.close();
    }
    @Test
    //file字节输入流(用程序把字节从文件读入)
    public void FileInput() throws IOException {
        //创建文件输出流, 参数为(File file/ String path)
        //如果文件不存在则抛出异常
        FileInputStream is = new FileInputStream("./src/com/hzt/stream/a.txt");
        //循环读取文件字符,将字符转换为字节
        //用read方法读取数据
        //重载1:读一个字节 8位 放入int的 32位 中的低八位, 其他空位都补0
        int i;
        while(( i = is.read()) != -1){
            System.out.println(i);
        }
    }

    @Test
    //复制文件
    public void copy() throws IOException {
        FileInputStream is = new FileInputStream("./src/com/hzt/stream/a.txt");
        FileOutputStream os = new FileOutputStream("./src/com/hzt/stream/a_bak.txt");
        //循环读取正本文件的一个字节,同时写入副本中
        int i;
        while((i = is.read()) != -1){
            os.write(i);
        }
    }
}

字符流

Reader/Writer
InputStreamReader(InputStream in, String charsetName) - 指定字符集
InputStreamReader(InputStream in) - 默认字符集
int read() 读一个字符
int read(char[] cbuf) 将字符读入数组。
int read(char[] cbuf, int off, int len) 将字符读入数组的一部分。- 了解
注: 以上三个方法, 返回 -1 都标记着读到文件末尾

OutputStreamWriter(OutputStream out, String charsetName)
OutputStreamWriter(OutputStream out)
void write(char[] cbuf) 写入一个字符数组。
void write(char[] cbuf, int off, int len) 写入字符数组的一部分。
void write(int c) 写入单个字符

代码实现:

import org.junit.Test;

import java.io.*;

//字符流
public class WriterAndReader {
    @Test
    //使用字符流读取数据
    public void reader() throws IOException {
        File fileI = new File("src/com/hzt/stream/a.txt");
        FileInputStream is = new FileInputStream(fileI);
        //构造方法1:使用字符流包装一个字节流
        InputStreamReader isr1 = new InputStreamReader(is);
        int i;
        //循环读取一个字符,返回值为int,将读取的16位放入int的低16位
        while ((i = isr1.read()) != -1){
            System.out.print((char)i);
        }
    }

    @Test
    //使用字符流写入数据
    public void writer() throws IOException {
        File fileI = new File("src/com/hzt/stream/a.txt");
        FileOutputStream os = new FileOutputStream(fileI);
        //构造方法1:创建一个使用默认字符编码的OutputStreamWriter。
        OutputStreamWriter osw1 = new OutputStreamWriter(os);
        char[] ch = new char[]{'h', 'e', 'l', 'l', 'o'};
        //写入字符数组的一部分。
        osw1.write("Hello,World!");
        //写出换行
        osw1.write("\n");
        //写入字符数组的一部分
        osw1.write(ch);
        //因为已经不是底层字符流了,需要进行刷新
//        osw1.flush();
        //或者直接close释放字符流
        osw1.close();
    }

    @Test
    //文件复制
    public void copy(){
        File fileI = new File("src/com/hzt/stream/a.txt");
        File fileO = new File("src/com/hzt/stream/a_bak.txt");
        try{
            //FileReader/FileWriter 字符流的便捷类
            FileReader fr = new FileReader(fileI);
            FileWriter fw = new FileWriter(fileO);
            int i;
            while ((i = fr.read()) != -1){
                fw.write(i);
                fw.flush();
            }
        }
        catch(IOException e){
            e.printStackTrace();
        }

    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值