跳转至

Java File

Pursue your object, be it what it will, steadily and indefatigably. 

1. IO流

1.1 概述与分类

  Java中的IO流技术主要用于传输数据。典型的应用场景有:读写本地文件、上传下载文件等。按照数据传输的方向可以分为两种:

  • 输入流(Input):即让数据进入应用程序中。
  • 输出流(Output):即让数据离开应用程序。

按照数据的种类还可以有另外一种分法:

  • 字节流:可以处理任何一种数据。
  • 字符流:只能处理纯文本数据。

  • 以Stream结尾的为字节流
  • 以Writer或者Reader结尾的为字符流。
  • 所有的输入流都是抽象类IuputStream(字节输入流)或者抽象类Reader(字符输入流)子类,
  • 所有的输出流都是抽象类OutputStream(字节输出流)或者抽象类Writer(字符输出流)子类。
  • 字符流能实现的功能字节流都能实现,反之不一定。如:图片,视频等二进制文件,只能使用字节流读写。

处理纯文本 字符流和字节流都可以但是处理视频,音频,图片等只能使用万能的字节流。

  Java文件类以抽象的方式代表文件名和目录路径名。该类主要用于文件和目录的创建、文件的查找和文件的删除等。

2 FileWriter 写文件

2.1 写文件

  File对象代表磁盘中实际存在的文件和目录。通过以下构造方法创建一个File对象。

通过给定的父抽象路径名和子路径名字符串创建一个新的File实例。

File(File parent, String child);
通过将给定路径名字符串转换成抽象路径名来创建一个新 File 实例。
File(String pathname) 
根据 parent 路径名字符串和 child 路径名字符串创建一个新 File 实例。
File(String parent, String child) 
通过将给定的 file: URI 转换成一个抽象路径名来创建一个新的 File 实例。
File(URI uri) 
创建File对象成功后,可以使用以下列表中的方法操作文件。

FileWriter写文件一般步骤

使用java.io.FileWriter类可以将数据写到文本文件当中,使用步骤为三步:

1.调用构造方法来创建一个FileWriter对象:
public FileWriter(String fileName):构造参数为文件路径名。
备注:创建对象时,如果文件不存在,则会自动创建该文件。

2.调用写数据的成员方法向文件中写入数据:
public void write(String text):参数为需要写入的字符串。

3.调用关闭的成员方法释放相关资源:
public void close()
写文件
package new_IO;

import java.io.FileWriter;
import java.io.IOException;

/**
 * @author summer
 * @create 2020-02-13 13:52
 */
public class Demo01FileWriter {
    public static void main(String[] args) throws IOException {
        FileWriter fw = new FileWriter("file01.txt");
        fw.write("武汉加油"); // 写数据
        fw.write("武汉加油\n"); // \n 表示换行
        fw.write("武汉加油\n"); // 写数据
        fw.close();// 关闭
    }
}

三步走:“创、写、关”

序号 方法描述
1 public String getName() 返回由此抽象路径名表示的文件或目录的名称。
2 public String getParent()**、** 返回此抽象路径名的父路径名的路径名字符串,如果此路径名没有指定父目录,则返回 null
3 public File getParentFile() 返回此抽象路径名的父路径名的抽象路径名,如果此路径名没有指定父目录,则返回 null
4 public String getPath() 将此抽象路径名转换为一个路径名字符串。
5 public boolean isAbsolute() 测试此抽象路径名是否为绝对路径名。
6 public String getAbsolutePath() 返回抽象路径名的绝对路径名字符串。
7 public boolean canRead() 测试应用程序是否可以读取此抽象路径名表示的文件。
8 public boolean canWrite() 测试应用程序是否可以修改此抽象路径名表示的文件。
9 public boolean exists() 测试此抽象路径名表示的文件或目录是否存在。
10 public boolean isDirectory() 测试此抽象路径名表示的文件是否是一个目录。
11 public boolean isFile() 测试此抽象路径名表示的文件是否是一个标准文件。
12 public long lastModified() 返回此抽象路径名表示的文件最后一次被修改的时间。
13 public long length() 返回由此抽象路径名表示的文件的长度。
14 public boolean createNewFile() throws IOException 当且仅当不存在具有此抽象路径名指定的名称的文件时,原子地创建由此抽象路径名指定的一个新的空文件。
15 public boolean delete() 删除此抽象路径名表示的文件或目录。
16 public void deleteOnExit() 在虚拟机终止时,请求删除此抽象路径名表示的文件或目录。
17 public String[] list() 返回由此抽象路径名所表示的目录中的文件和目录的名称所组成字符串数组。
18 public String[] list(FilenameFilter filter) 返回由包含在目录中的文件和目录的名称所组成的字符串数组,这一目录是通过满足指定过滤器的抽象路径名来表示的。
19 public File[] listFiles() 返回一个抽象路径名数组,这些路径名表示此抽象路径名所表示目录中的文件。
20 public File[] listFiles(FileFilter filter) 返回表示此抽象路径名所表示目录中的文件和目录的抽象路径名数组,这些路径名满足特定过滤器。
21 public boolean mkdir() 创建此抽象路径名指定的目录。
22 public boolean mkdirs() 创建此抽象路径名指定的目录,包括创建必需但不存在的父目录。
23 public boolean renameTo(File dest) 重新命名此抽象路径名表示的文件。
24 public boolean setLastModified(long time) 设置由此抽象路径名所指定的文件或目录的最后一次修改时间。
25 public boolean setReadOnly() 标记此抽象路径名指定的文件或目录,以便只可对其进行读操作。
26 public static File createTempFile(String prefix, String suffix, File directory) throws IOException 在指定目录中创建一个新的空文件,使用给定的前缀和后缀字符串生成其名称。
27 public static File createTempFile(String prefix, String suffix) throws IOException 在默认临时文件目录中创建一个空文件,使用给定前缀和后缀生成其名称。
28 public int compareTo(File pathname) 按字母顺序比较两个抽象路径名。
29 public int compareTo(Object o) 按字母顺序比较抽象路径名与给定对象。
30 public boolean equals(Object obj) 测试此抽象路径名与给定对象是否相等。
31 public String toString() 返回此抽象路径名的路径名字符串。
文件操作
package FileIoDemo;

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

/**
 * @author summer
 * @create 2020-02-07 17:35
 */
public class fileDemo {
    public static void main(String[] args) {
        File file =new File("src/abc.txt");
        try {
            //创建文件
            file.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
        }

        // 判断权限,都会返回bool类型
        file.canExecute();
        file.canRead();
        file.canWrite();
        file.exists();
        System.out.println("文件名: "+file.getName());
        System.out.println("文件绝对路径: "+file.getAbsolutePath());
        System.out.println("文件父路径: "+file.getParent());
        System.out.println("文件对象: "+file.getAbsoluteFile());
        System.out.println("系统文件分隔符: "+File.separator);

        // 无论当前文件是否存在,只要给定具体的路径,都可以返回对应路径名称等
        File file1 = new File("d:/cmz.txt");
        System.out.println(file1.getAbsolutePath());

        //判断文件、目录是否存在。前提是必须存在
        System.out.println(file1.isDirectory());
        System.out.println(file1.isFile());

        File file2 = new File("d:/");
        String[] list = file2.list();
        File[] files = file2.listFiles();
        System.out.println("------lists------");
        for (String s : list) {
            System.out.println(s);
        }
        System.out.println("------files------");
        for (File f : files) {
            System.out.println(f);
        }
        System.out.println("-----以下打印当前系统的所有盘符----");
        File[] dfiles1 = File.listRoots();
        for (int i = 0; i < dfiles1.length; i++) {
            System.out.println(dfiles1[i]);
        }

        File file3 = new File("d:/test");
        //创建单级目录
        file3.mkdir();
        File file4 = new File("d:/test1/test2");
        //创建多级目录
        file4.mkdirs();

        /**
         *
         * 文件在遍历的时候,会出现空指针的问题,原因在于当前文件系统受保护,某些文件没有访问权限,此时会报空指针异常
         * @param file
         */
        System.out.println("------D盘下所有文件的绝对路径------");
        File file5 = new File("d:/");
        System.out.println("------递归------");
        printFile(file5);
    }
    public static void printFile(File file){
        if(file.isDirectory()){
            File[] Dfiles = file.listFiles();
            for (File f:Dfiles){
                printFile(f);
            }
        }else{
//            System.out.println("此文件是一个具体的文件");
            System.out.println(file.getAbsolutePath());
        }
    }
}

2.2 覆盖与追加

  在使用FileWriter写文件的时候,如果指定的文件不存在,则会自动创建;如果文件已经存在,则会覆盖写入;如果不希望覆盖写入,实现追加写入的效果,则需要使用另一种重载的构造方法:

public FileWriter(String fileName, boolean append)
当第2个参数为true时,将会实现追加写入的效果。

追加写
package new_IO;

import java.io.FileWriter;
import java.io.IOException;

public class Demo01FileWriter {
    public static void main(String[] args) throws IOException {
        FileWriter fw = new FileWriter("file01.txt",true); // 追加写
        fw.write("爱一直在线!\n"); // 写数据
        fw.write("爱一直在线!\n"); // 写数据
        fw.close();// 关闭
    }
}

2.3 换行

  不同的平台使用不同的字符来代表换行

  • Windows操作系统:\r\n(两个字符)
  • macOS操作系统:\r(早期)或者\n(现在)
  • Linux操作系统:\n
换行写
package new_IO;

import java.io.FileWriter;
import java.io.IOException;

/**
 * @author summer
 * @create 2020-02-13 14:01
 */
public class Demo03FileWriterLine {
    public static void main(String[] args) throws IOException {
        FileWriter fw = new FileWriter("file03.txt",true);
        fw.write("第一行数据\n");
        fw.write("第二行数据\n");
        fw.close();
    }
}

2.4 数字与文字的转换

  其实所有数据在计算机底层都是二进制数字,所以一切数据都是数字。文件当中存放的其实并不是文字图形,而是数字序列。之所以打开文件可以看到文字图形,是因为软件对文件当中的数字进行了“翻译”。而翻译就需要一个对照词典,如:ASCII码表或Unicode码表。

  ASCII当中的字符种类比较少;而Unicode包含了ASCII的内容,还扩展了数以万计的字符,可以涵盖全世界所有的文字。FileWriter提供了一种重载形式的write方法,可以省去将文字翻译成为数字的步骤,直接在文件当中写对应的数字:

public void write(int ch):参数就是ASCII或Unicode表当中的数字,最小为0

Character
package new_IO;

import java.io.FileWriter;
import java.io.IOException;

/**
 * @author summer
 * @create 2020-02-13 14:05
 */
public class Demo04FileWriterCharacter {
    public static void main(String[] args) throws IOException {
        FileWriter fw = new FileWriter("file04.txt");
        fw.write("Hello");
        fw.write(20013); // 代表“中”
        fw.write("国");
        fw.close();
    }
}

2.5 write方法的重载

  FileWriter中写数据的方法write其实有5种重载形式,可以在写字符到文件中时提供更加灵活的选择:

-public void write(int ch):参数为单个文字对应的数字(参考对照码表)。 -public void write(String str):写完整字符串。 -public void write(String str, int offset, int count):写字符串的一部分。 -public void write(char[] array):写完整字符数组。 -public void write(char[] array, int offset, int count):写字符数组的一部分。

2. FileReader读文件

使用java.io.FileReader类可以读取文本文件当中的字符(对应的ASCII或Unicode值)。使用步骤为:

FileReader读文件步骤

1.调用构造方法来创建一个FileReader对象:
public FileReader(String fileName):参数仍然为文件的路径名。
备注:如果文件不存在,不会自动创建,而会发生异常。

2.调用读取数据的read方法获取单个字符:
public int read():返回值为单个字符对应的ASCII或Unicode值。
备注:每次调用都会读取下一个字符,如果没有更多,将返回-1值。

3.调用close方法关闭流:
public void close():释放相关资源。
由于并不确定文件当中包含多少个字符,所以次数不确定的重复代码,应该使用while循环。当得到-1值时退出循环。
读取单个字符
package new_IO;

import java.io.FileReader;
import java.io.IOException;

/**
 * @author summer
 * @create 2020-02-13 14:16
 */
public class Demo02FileReaderWhile {
    public static void main(String[] args) throws IOException {
        FileReader fileReader = new FileReader("file04.txt");
        System.out.println("---------");
        int ch; // 代表一个单个字符(对应的ASCII/Unicode)
        while ((ch = fileReader.read()) != -1) {
            System.out.println((char) ch);
        }
        fileReader.close(); // 关闭
    }
}

2.2 读取字符数组

一个字一个字地读取,很明显效率很低。如果能够五个五个地批量读取,那么效率会有大幅度的提升。FileReader中提供另一种重载形式的read方法:

public int read(char[]buf):
参数buf是用来装载多个字符结果的数组,返回值代表数组当中读取到的字符有效个数。

读取字符数组
package new_IO;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

/**
 * @author summer
 * @create 2020-02-13 14:23
 */
public class Demo04FileReaderArrayWhile {
    public static void main(String[] args) throws IOException {
        FileReader fileReader = new FileReader("file04.txt");

        char [] buf = new char[1024];
        int len = 0; // 代表读取的有效个数
        while ((len = fileReader.read(buf))!=-1){ //读取到数据放入buf
            String str = new String(buf,0,len);
            System.out.println(str);
        }

    }
}

2.3 读写数据的过程

  Java程序并不会直接去操作硬盘,而是交给JVM;JVM再与操作系统交互;操作系统去操作硬盘。然而硬盘的速度比内存慢很多,所以如果每一个单个字符都去操作一次硬盘,性能非常低下。为了提高性能,应该使用数组来达到批量操作,缓冲的目的。

3. BufferedWriter

3.1 BufferedWriter

  为了提高写文件的效率,java.io.BufferedWriter类内部包含了一个缓冲数组,可以大幅度提高FileWriter写数据的性能。

  BufferedWriter类内部包含一个长度为8192的char[]字符数组,每次写数据都是在向数组当中添加字符。如果数组满了,将会整体写到硬盘中;如果数组没满,那么在调用close方法的时候,也会将最后剩余的有效部分写到硬盘中。

  BufferedWriter类的构造方法可以将一个普通的FileWriter作为参数,而使用起来与FileWriter基本一样,性能却大幅度提高。构造方法:

public BufferedWriter(FileWriter fw):构造参数就是普通的FileWriter对象。

BufferedWriter
package new_IO;

import java.io.*;

/**
 * @author summer
 * @create 2020-02-13 14:34
 */
public class Demo01BufferedWriter {
    public static void main(String[] args) throws IOException {
        // 首先创建一个普通的FileWriter
        FileWriter fw = new FileWriter("file05.txt");
        // 将这个普通的FileWriter对象传递给BufferedWriter构造方法即可。
        BufferedWriter bw = new BufferedWriter(fw);
        // 后面bw的时候,和fw基本没有区别。
        bw.write("Hello");
        // 关闭流
        bw.close();
    }
}

3.2 newLine

  除了性能比FileWriter更高之外,BufferedWriter还提供一个换行的方法:

public void newLine():该方法会根据操作系统的不同,自动选择写入\r\n或者\r或者\n。

newLine
package new_IO;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;

/**
 * @author summer
 * @create 2020-02-13 14:41
 */
public class Demo02NewLine {
    public static void main(String[] args) throws IOException {
        FileWriter fileWriter = new FileWriter("file06.txt");
        BufferedWriter bw = new BufferedWriter(fileWriter);

        bw.write("cmz");
        bw.newLine();
        bw.write("加油");
        bw.close();
    }
}

4. BufferedReader

  类似地,BufferedReader类内部包含一个长度为8192的char[]字符数组,读数据的时候将会一次最多读取8192个字符放在数组中,而read方法只是从数组中取出字符使用。如果数组被“取空”,会自动再次读取最多8192个字符供使用。从而达到减少硬盘读取次数的目的。

  BufferedReader类的构造方法可以将一个普通的FileReader作为参数,而使用起来与FileReader基本一样,性能却大幅度提高。构造方法:

public BufferedReader(FileReader fr):构造参数就是普通的FileReader对象。
readLine方法

除了性能比FileReader更高之外,BufferedReader还额外提供一个方法,可以读取一整行字符串:

public String readLine():返回值为一整行字符串内容,不包含换行符。

逐行读
package new_IO;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

/**
 * @author summer
 * @create 2020-02-13 14:45
 */
public class Demo04ReadLine {
    public static void main(String[] args) throws IOException {
        FileReader fileReader = new FileReader("file04.txt");
        BufferedReader bufferedReader = new BufferedReader(fileReader);

        String line = bufferedReader.readLine();
        System.out.println(line);

        String line1 = bufferedReader.readLine();
        System.out.println(line1);

        String line2 = bufferedReader.readLine();
        System.out.println(line2);

        String line3 = bufferedReader.readLine();
        System.out.println(line3);

        bufferedReader.close();
        fileReader.close();
    }
}
循环读
package new_IO;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

/**
 * @author summer
 * @create 2020-02-13 14:45
 */
public class Demo04ReadLine {
    public static void main(String[] args) throws IOException {
        FileReader fileReader = new FileReader("file04.txt");
        BufferedReader bufferedReader = new BufferedReader(fileReader);
        String line;
        while((line =bufferedReader.readLine())!=null){
            System.out.println(line);
        }
        bufferedReader.close();
        fileReader.close();
    }
}

练习: 定义一个集合用于存储多个字符串,向其中添加一些字符串,然后将集合的所有字符串内容写到文件中。要求每个字符串独占一行。

练习1
package new_IO;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @author summer
 * @create 2020-02-13 14:54
 */
public class Test1 {
    public static void main(String[] args) throws IOException {
        List<String> person = Arrays.asList("Larry", "Moe", "Curly");
//        FileWriter fileWriter = new FileWriter("test01.txt");
//        BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
        BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("test1.txt"));
        for (int i = 0; i < person.size(); i++) {
            bufferedWriter.write(person.get(i)); //写数据
//            System.out.println(person.get(i));
            bufferedWriter.newLine(); //换行
        }
        bufferedWriter.close();
//        fileWriter.close();
    }
}

将文件中的字符串读到集合中

与上一题相反,将文件中的字符串文本读取到集合当中,并且每一行文本作为集合中的一个字符串元素。

练习2
package new_IO;

import java.io.*;
import java.util.ArrayList;

/**
 * @author summer
 * @create 2020-02-13 15:09
 */
public class test2 {
    public static void main(String[] args) throws IOException {
        ArrayList<String> lists = new ArrayList<>();

        BufferedReader bufferedReader = new BufferedReader(new FileReader("test1.txt"));
        String line;
        while((line=bufferedReader.readLine()) != null){
            lists.add(line);
        }
        bufferedReader.close();
        for (String list : lists) {
            System.out.println(list);
        }
    }
}

2. IO流的原理和概念

  如何读写文件?通过流来读写文件,流是指一连串流动的字符,是以先进先出方式发。送信息的通道

输入/输出流与数据源,

  • XXX-程序--输入流

  • 程序-XXX--输出流

3. IO流的分类

                 |---输出流----OutputStream和Write作为基类
按照流向区分 ----|
                 |---输入流----InputSream和Reader作为基类

输入输出流是相对于计算机内存来说的,而不是相对于源和目标

                                       |----字节输入流InputStream基类
                         |---字节流----|
                         |             |----字节输出流OutputStream基类
按照处理数据单元划分 ----|
                         |             |----字符输入流Reader基类
                         |---字符流----|
                                       |----字符输出流Reader基类

字节流是 8 位通用字节流,字符流是 16 位 Unicode 字符流

== 功能不同 ==

  • 节点流:可以直接从数据源或目的地读写数据。
  • 处理流(包装流):不直接连接到数据源或目的地,是其他流进行封装。目 的主要是简化操作和提高性能。

== 节点流和处理流的关系 ==

  • 节点流处于io操作的第一线,所有操作必须通过他们进行
  • 处理流可以对其他流进行处理(提高效率或操作灵活性)

文件拷贝
package FileIoDemo;

import java.io.*;

/**
 * @author summer
 * @create 2020-02-07 21:25
 */
public class CopyFile {
    public static void main(String[] args) {
        File src = new File("src/abc.txt");
        File dest = new File("src/aa.txt");
        InputStream inputStream = null;
        OutputStream outputStream = null;
        try {
            inputStream = new FileInputStream(src);
            outputStream = new FileOutputStream(dest);

            //带缓冲输入输出方式
            byte[] buffer = new byte[1024];
            int length = 0;
            // 完成数据传输
            while ((length=inputStream.read(buffer))!=-1){
                outputStream.write(buffer);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                outputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

4. IO流的体系

5. 字节流和字符流

读单字符
package readerOrWrite;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;

/**
 * @author summer
 * @create 2020-02-07 21:43
 *
 *  字符流可以直接读取中文汉字,而字节流在处理的时候会出现中文乱码
 *
 */
public class ReaderDemo2 {
    public static void main(String[] args) {
        Reader reader = null;
        try {
            reader = new FileReader("src/abc.txt");
            int read = 0;
            while ((read = reader.read())!=-1){
                System.out.println((char)read);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                reader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
读取文件全部
package readerOrWrite;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;

/**
 * @author summer
 * @create 2020-02-07 21:43
 *
 *  字符流可以直接读取中文汉字,而字节流在处理的时候会出现中文乱码
 *
 */
public class ReaderDemo3 {
    public static void main(String[] args) {
        Reader reader = null;
        try {
            reader = new FileReader("src/abc.txt");
            int length = 0;
            char[] chars = new char[1024]; // 缓冲区大小1024 可以自己定义
            // 添加缓冲区
            while ((length = reader.read(chars))!=-1){
                System.out.println(new String(chars,0,length));
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                reader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
写入
package readerOrWrite;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;

/**
 * @author summer
 * @create 2020-02-07 22:00
 *
 * 什么时候需要加flush,什么时候不加flush
 *   最保险的方式,在输出流关闭之前每次都flush一下,然后再关闭
 *   当某一个输出流对象中带有缓冲区的时候,就需要进行flush,不建议大家去记住每个输出流的分
 */
public class WriteDemo {
    public static void main(String[] args) {

        File file = new File("src/writer.txt");
        Writer writer = null;
        try {
            writer = new FileWriter(file);
            writer.write("www.jd.com");
            writer.write("京东商城");
            writer.flush(); // 强制刷新到
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                writer.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
图片拷贝
package readerOrWrite;

import java.io.*;

/**
 * @author summer
 * @create 2020-02-07 22:08
 */
public class CopyPicture {
    public static void main(String[] args) {
//        FileReader reader = null;
//        FileWriter writer = null;
//        try {
//            reader = new FileReader("src/1.png");
//            writer = new FileWriter("src/2.png");
//            int length = 0;
//            char[] chars = new char[1024];
//            while ((length = reader.read(chars))!=-1){
//                writer.write(chars);
//            }
//
//        } catch (FileNotFoundException e) {
//            e.printStackTrace();
//        } catch (IOException e) {
//            e.printStackTrace();
//        }finally {
//            try {
//                writer.close();
//            } catch (IOException e) {
//                e.printStackTrace();
//            }
//            try {
//                reader.close();
//            } catch (IOException e) {
//                e.printStackTrace();
//            }
//        }

        FileInputStream fileInputStream = null;
        FileOutputStream fileOutputStream = null;
        try {
            fileInputStream = new FileInputStream("src/1.png");
            fileOutputStream = new FileOutputStream("src/2.png");
            int length = 0;
            byte[] buffer = new byte[1024];
            while ((length = fileInputStream.read(buffer))!=-1){
                fileOutputStream.write(buffer);
            }

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                fileInputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                fileOutputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
}

6. 处理流和节点流

7. 文件拷贝

知识总结


IO流是用来传输数据的技术,典型应用包括读写文件。


IO流的分类

  • 字节输入流
  • 字节输出流
  • 字符输入流:FileReader、BufferedReader
  • 字符输出流:FileWriter、BufferedWriter

FileWriter一般使用步骤:创、写、关。

  • 创:FileWriter fw = new FileWriter(“file01.txt”);
  • 写:fw.write(“Hello”);
  • 关:fw.close();

FileWriter如何才能追加写入呢?构造方法第二个参数为true即可。


如何实现换行

  • Windows当中:\r\n
  • macOS当中:\r或者\n
  • Linux当中:\n

五种write方法的重载

  • 写字符串的整体
  • 写字符串的部分
  • 写字符数组的整体
  • 写字符谁书的部分
  • 写单个字符对应的数字(参考ASCII码表或者Unicode表)

FileReader一般使用步骤:创、读、关。

  • 创:FileReader fr = new FileReader(“file01.txt”);
  • 读单个字符:
int ch; // 单个字符的ASCII值
while ((ch = fr.read()) != -1) {
    // ...
}
  • 读字符数组:
char[] buf = new char[1024];
int len; // 有效个数
while ((len = fr.read(buf)) != -1) {
    String str = new String(buf, 0, len);
}

BufferedXxx和FileXxx有什么区别?BufferedXxx有8192长度的char[]字符数组作为缓冲,所以性能更加高一些。


BufferedWriter有额外的方法:public void newLine(),根据操作系统自动选择写入换行符.


BufferedReader有额外的方法:public String readLine(),读取一行字符串,不包含换行符。


关于方法的参数和返回值类型:

  • 任何数据类型(基本类型、数组、字符串、自定义的类)都可以作为参数。
  • 任何数据类型(基本类型、数组、字符串、自定义的类)都可以作为返回值。