Java IO流(详解)

Posted 364.99°

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java IO流(详解)相关的知识,希望对你有一定的参考价值。

1. File

文件: 保存数据的地方。

1. 创建

构造器:
new File

  • (String pathName) // 根据路径构建一个 File对象
  • (File parent, String child) // 根据父目录文件 + 子路径构建
  • (String parent, String child) // 根据父目录 + 子路径构建

创建对象:
createNewFile


(String pathName) —— 目录必须存在,才能创建文件
如果 D:\\Study\\file_demo\\ 路径不存在,会抛出异常:java.io.IOException: 系统找不到指定的路径

    public static File create_01(String path) 
        File file = new File(path);
        try 
            file.createNewFile();
         catch (IOException e) 
            e.printStackTrace();
        
        return file;
    

    public static void main(String[] args) 
        String path = "D:\\\\Study\\\\file_demo\\\\demo1.txt";
        File file = create_01(path);
    

(File parent, String child)
如果 D:\\Study\\file_demo\\ 路径不存在,会抛出异常:java.io.IOException: 系统找不到指定的路径

    public static File create_02(File parent, String child) 
        File file = new File(parent, child);
        try 
            file.createNewFile();
         catch (IOException e) 
            e.printStackTrace();
        
        return file;
    

    public static void main(String[] args) 
        File parent = new File("D:\\\\Study\\\\file_demo\\\\");
        String path = "demo2.txt";
        File file = create_02(parent, path);
    

(String parent, String child)
如果 D:\\Study\\file_demo\\ 路径不存在,会抛出异常:java.io.IOException: 系统找不到指定的路径

    public static File create_03(String parent, String child) 
        File file = new File(parent, child);
        try 
            file.createNewFile();
         catch (IOException e) 
            e.printStackTrace();
        
        return file;
    

    public static void main(String[] args) 
        String parent = "D:\\\\Study\\\\file_demo\\\\";
        String child = "demo3.txt";
        File file = create_03(parent, child);
    

注意:

  • new File 只是在内存中创建了一个对象
  • createNewFile 才是在磁盘上创建了一个文件

2. 操作

1. 获取文件信息

方法:

  • getName
  • getAbsolutePath
  • getParent
  • length
  • exists
  • isFile
  • isDirectory
    public static Map<String, String> getFileInfo(File file) 
        Map<String, String> info = new HashMap<>();
        info.put("文件名", file.getName());
        info.put("文件绝对路径", file.getAbsolutePath());
        info.put("文件父级目录", file.getParent());
        info.put("文件大小(byte)", String.valueOf(file.length()));
        info.put("文件是否存在", file.exists() + "");
        info.put("是否是文件", file.isFile() + "");
        info.put("是否是目录", String.valueOf(file.isDirectory()));
        return info;
    

    public static void main(String[] args) 
        File file = new File("D:\\\\Study\\\\file_demo\\\\demo1.txt");
        getFileInfo(file).forEach((k, v) -> 
            System.out.println(k + ":" + v);
        );
    

2. 目录创建/删除

方法:

  • mkdir
    创建一级目录
  • mkdirs
    创建多级目录
  • delete
    删除空目录/文件

注意: Java中,目录也被当做文件。

    public static void create_01(String path) 
        File file = new File(path);
        String flagE = null;
        String flagM = null;
        String flagMs = null;
        if (file.exists()) 
            flagE = file.delete() ? "文件删除成功" : "文件删除失败";
         else 
            flagE = "文件不存在";
        
        System.out.println(flagE);
        boolean isMk = file.mkdir();
        flagM = isMk ? "一级目录创建成功" : "一级目录创建失败";
        System.out.println(flagM);
        if (!isMk) 
            flagMs = file.mkdirs() ? "多级目录创建成功" : "多级目录创建失败";
            System.out.println(flagMs);
        
    

    public static void main(String[] args) 
        String path = "D:\\\\Study\\\\file_demo\\\\test";
        create_01(path);
    

2. IO流

IO Input/Output,处理数据传输的技术。

Stream 流,Java中的数据的输入/输出都以流的方式进行。

  • 分类(数据单位)
    • 字节流(1 byte)—— InputStreamOutputStream
    • 字符流(1 字符)—— ReaderWriter
  • 分类(流向)
    • 输入流
    • 输出流
  • 分类(角色)
    • 节点流
    • 处理流/包装流

1. FileInputStream

1. 简单使用

    public static String readFile_01(String path) 
        FileInputStream inputStream = null;
        StringBuilder sb = new StringBuilder();
        int curr = 0;
        try 
            inputStream = new FileInputStream(path);
            while ((curr = inputStream.read()) != -1) 
                // read ———— 每次读取 1byte, 读取完毕就返回 -1
                sb.append((char) curr + "");
            
         catch (IOException e) 
            e.printStackTrace();
         finally 
            try 
                inputStream.close();
             catch (IOException e) 
                e.printStackTrace();
            
        
        return sb.toString();
    

    public static void main(String[] args) throws IOException 
        String path = "D:\\\\Study\\\\file_demo\\\\user.txt";
        System.out.println(readFile_01(path));
    

注意:

  • read 每次读取 1byte,读取完毕返回 -1
  • 每次使用完流,都得使用 close 关闭流,避免资源浪费
  • 使用 FileInputStream 读取中文可能会出现中文乱码问题
    • 原因:
      FileInputStream 每次读取大小为 1byte = 8bit,在 GBK 编码模式下,每个中文为 2bit,但在 UTF-8 编码 模式下,每个中文为 3bit,显然不能刚好装进一个 byte 数组。
    • 解决方案:
      • 使用 FileReader
      • 使用 read(byte b[]),并将 byte 数组的容量设置足够大
        这个方法就是自定义每次读取的字节数组的大小

2. 读取中文

思路: 声明一个容量足够大的 byte 数组(能一次性吧文件读完),然后使用 public int read(byte b[]) 读取文件(会将文件内容存入 b[],并返回 b.length)。

    public static String readFile_01(String path) 
        FileInputStream inputStream = null;
        StringBuilder sb = new StringBuilder();
        // 用一个足够大的 byte 数组来装下内容
        byte [] bytes = new byte[83];
        int readLen = 0;
        try 
            inputStream = new FileInputStream(path);
            // 返回值是读取的字节长度
            while ((readLen = inputStream.read(bytes)) != -1) 
                // read ———— 每次读取 1byte, 读取完毕就返回 -1
                sb.append(new String(bytes, 0, readLen));
            
         catch (IOException e) 
            e.printStackTrace();
         finally 
            try 
                inputStream.close();
             catch (IOException e) 
                e.printStackTrace();
            
        
        return sb.toString();
    

    public static void main(String[] args) throws IOException 
        String path = "D:\\\\Study\\\\file_demo\\\\user.txt";
        System.out.println(readFile_01(path));
    

2. FileOutputStream

1. 简单使用

write

  • write(int b)

  • write(byte b[])

  • write(byte b[], int off, int len)

    public static void write_01(String path, String words) 
        FileOutputStream outputStream = null;
        try 
            outputStream = new FileOutputStream(path);
            //
            outputStream.write(words.getBytes());
         catch (IOException e) 
            e.printStackTrace();
         finally 
            try 
                outputStream.close();
             catch (IOException e) 
                e.printStackTrace();
            
        
    

    public static void main(String[] args) 
        String words = "在龟友百货上班,规规矩矩地纳税。";
        String path = "D:\\\\Study\\\\file_demo\\\\user.txt";
        write_01(path, words);
    

注意:

  • 直接这样 write 会覆盖掉之前的内容
  • 进行写操作的时候,文件可以不存在,但目录必须存在

2. 追加写入

在初始化 FileOutputStream 的时候,传入一个参数 true,表明——在文件末尾追加内容。

outputStream = new FileOutputStream(path, true);

3. 文件拷贝

需求: 将如图所示的四种文件拷贝到另外一个文件夹:

步骤: 输入流(读取到内存)→ 输出流(写入到磁盘)
读取部分数据,就写入磁盘,不能一次性读完再写(防止内存不够)。

    public static void copy(String resPath, String tarPath) 
        FileInputStream inputStream = null;
        FileOutputStream outputStream = null;
        byte []bytes = new byte[1024 * 1024]; // 一次读 1MB
        int len = 0;


        try 
            inputStream = new FileInputStream(resPath);
            outputStream = new FileOutputStream(tarPath);

            while ((len = inputStream.read(bytes)) != -1) 
                outputStream.write(bytes, 0, len); // 这里必须使用此方法,防止文件读取时没装完
            
         catch (IOException e) 
            e.printStackTrace();
         finally 
            try 
                if (inputStream != null) 
                    inputStream.close();
                
                if (outputStream != null) 
                    outputStream.close();
                
             catch (IOException e) 
                e.printStackTrace();
            
        
    

    public static void main(String[] args) 
        String res1 = "D:\\\\Study\\\\file_demo\\\\resource\\\\pic.jpg";
        String res2 = "D:\\\\Study\\\\file_demo\\\\resource\\\\user.txt";
        String res3 = "D:\\\\Study\\\\file_demo\\\\resource\\\\电锯人5.mp4";
        String res4 = "D:\\\\Study\\\\file_demo\\\\resource\\\\周杰伦 - 我是如此相信.mp3";

        String tar1 = "D:\\\\Study\\\\file_demo\\\\target\\\\pic.jpg";
        String tar2 = "D:\\\\Study\\\\file_demo\\\\target\\\\user.txt";
        String tar3 = "D:\\\\Study\\\\file_demo\\\\target\\\\电锯人5.mp4";
        String tar4 = "D:\\\\Study\\\\file_demo\\\\target\\\\周杰伦 - 我是如此相信.mp3";

        copy(res1, tar1);
        copy(res2, tar2);
        copy(res3, tar3);
        copy(res4, tar4);
    

4. FileReader

1. 简单使用

    public static String readFile_02(String path) 
        FileReader reader = null;
        StringBuilder sb = new StringBuilder();
        int curr = 0;

        try 
            reader = new FileReader(path);
            while (true) 
                if ((curr = reader.read()) == -1) break;
                sb.append((char) curr + "");
            
         catch (IOException e) 
            e.printStackTrace();
         finally 
            if (reader != null) 
                try 
                    reader.close();
                 catch (IOException e) 
                    e.printStackTrace();
                
            
        
        return sb.toString();
    

    public static void main(String[] args) 
        String path = "D:\\\\Study\\\\file_demo\\\\target\\\\user.txt";
        System.out.println(readFile_02(path));
    

注意: 因为 FileReader 是一个字符一个字符地读取的,所以不存在中文乱码问题。

2. 提高读取速度

按照上面的写法,每次只读取一个字符,效率太低,为了提高读取效率,可以使用这个方法:public int read(char cbuf[])

    public static String readFile_02(String path) 
        FileReader reader = null;
        StringBuilder sb = new StringBuilder();
        char []chars = new char[8]; // 一次读取 8 个字符
        《java基础知识》Java IO流详解

Java连载98-FileReader和FileWriter详解

Java常用IO流详解

Java之文件IO流详解完结

Java IO详解(四)------字符流

Java IO详解(四)------字符流