【学习笔记】Java笔记8:IO流

157 阅读4分钟

1. File类

  该类的一个对象代表一个文件或目录(文件夹)

1.1 创建File类实例

构造器说明
File(String pathname)1、使用相对路径创建时,对于IDEA是相对于当前工程下的
2、使用绝对路径时,Windows和DOS系统使用"\"来隔开,为了区别转义符,Java代码层面则使用"\\";UNIX和URL使用"/"来隔开;也可以用常量File.separator
File(String parent, String child)根据parent路径名字符串和child路径名字符串创建一个新File实例
File(File parent, String child)根据parent抽象路径名和child路径名字符串创建一个新File实例

(注:File对象只是内存层面上的,与实际硬盘上是否存在无关)

1.2 需要注意的方法

方法说明
File[] listFiles()获取当前目录下所有的文件或目录,得到File数组
String[] list()获取当前目录下所有的文件或目录,得到String数组
boolean renameTo(File dest)1、重新命名此抽象路径名表示的文件
2、要想 file1.renameTo(file2) 返回true,则file1要在硬盘中存在,file2不存在
boolean createNewFile()创建文件;若硬盘中已存在,则不创建返回false
boolean mkdir()创建目录;若上层目录不存在,则不会创建
boolean mkdirs()创建目录;即使上层目录不存在,也会一并创建

2. IO流

  四个抽象基类如下

(抽象基类)字节流字符流
输入流InputStreamReader
输出流OutputStreamWriter

  IO流体系如下

字节输入流字节输出流字符输入流字符输出流
抽象基类InputStreamOutputStreamReaderWriter
访问文件FileInputStreamFileOutputStreamFileReaderFileWriter
访问数组ByteArrayInputStreamByteArrayOutputStreamCharArrayReaderCharArrayWriter
访问管道PipedInputStreamPipedOutputStreamPipedReaderPipedWriter
访问字符串StringReaderStringWriter
缓冲流BufferedInputStreamBufferedOutputStreamBufferedReaderBufferedWriter
转换流InputStreamReaderOutputStreamWriter
对象流ObjectInputStreamObjectOutputStream
FilterInputStreamFilterOutputStreamFilterReaderFilterWriter
打印流PrintStreamPrintWriter
推回输入流PushbackInputStreamPushbackReader
特殊流DataInputStreamDataOutputStream

2.1 FileReader

  用于处理文本文件(.txt,.java,.c,.cpp等)的输入流

// 使用read()方法
@Test
public void testFileReader() {
    FileReader fr = null;
    // 为了保证流可以关闭,需要使用try/catch来处理异常
    try {
        File file = new File("E:\\JavaTest\\hello.txt");
        fr = new FileReader(file);
        int data;
        while (-1 != (data = fr.read())) {
            System.out.print((char) data);
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            if (null != fr)
                fr.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

// 使用read(char[] cbuf)方法
@Test
public void testFileReader2() {
    File file = new File("E:\\JavaTest\\hello.txt");
    char[] buff = new char[5];
    FileReader fr = null;
    try {
        fr = new FileReader(file);
        int len;
        while (-1 != (len = fr.read(buff))) {
            // 这里循环的上限不能是buff.length,因为每调用read()就会把内容填进char数组中,
            // 使用buff.length可能会在最后一次输出上一次的内容
            for (int i = 0; i < len; i++) {
                System.out.print(buff[i]);
            }
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            if (null != fr)
                fr.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

2.2 FileWriter

  用于处理文本文件的输出流

@Test
public void testFileWriter() {
    FileWriter fw = null;
    try {
        File file = new File("E:\\JavaTest\\hello.txt");
        // 第二个参数表示以追加形式写数据,默认是覆盖
        fw = new FileWriter(file, true);
        fw.write("How are you\n");
        fw.write("I'm fine\n");
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            if (null != fw)
                fw.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

2.3 复制文本文件

// 复制文本文件
@Test
public void testCopy() {
    File scr = new File("E:\\JavaTest\\src.txt");
    File dest = new File("E:\\JavaTest\\dest.txt");
    FileReader fr = null;
    FileWriter fw = null;
    try {
        fr = new FileReader(scr);
        fw = new FileWriter(dest);
        char[] buff = new char[10];
        int len;
        while (-1 != (len = fr.read(buff))) {
            // 每次写len个字符
            fw.write(buff, 0, len);
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            if (null != fw)
                fw.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            if (null != fr)
                fr.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

2.4 FileInputStream/FileOutputStream

  字节流,可处理任意文件,输出文本文件到控制台时可能会出现乱码

@Test
public void testFileInputOutputStream() {
    File src = new File("E:\\JavaTest\\src.jpg");
    File dest = new File("E:\\JavaTest\\dest.jpg");
    FileInputStream fis = null;
    FileOutputStream fos = null;
    try {
        fis = new FileInputStream(src);
        fos = new FileOutputStream(dest);
        byte[] buff = new byte[1024];
        int len;
        while (-1 != (len = fis.read(buff))) {
            fos.write(buff, 0, len);
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (null != fis) {
            try {
                fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (null != fos) {
            try {
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

2.5 缓冲流

@Test
public void testBufferedInputOutputStream() {
    File src = new File("E:\\JavaTest\\src.jpg");
    File dest = new File("E:\\JavaTest\\dest.jpg");
    BufferedInputStream bis = null;
    BufferedOutputStream bos = null;
    try {
        FileInputStream fis = new FileInputStream(src);
        FileOutputStream fos = new FileOutputStream(dest);
        bis = new BufferedInputStream(fis);
        bos = new BufferedOutputStream(fos);
        byte[] buff = new byte[1024];
        int len;
        while (-1 != (len = bis.read(buff))) {
            bos.write(buff, 0, len);
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (null != bis) {
            try {
                bis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (null != bos) {
            try {
                bos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

2.6 转换流

  • InputStreamReader:字节输入流 --> 字符输入流,解码
  • OutputStreamWriter:字符输出流 --> 字节输出流,编码
@Test
public void test() {
    File src = new File("E:\\JavaTest\\src.txt");
    File dest = new File("E:\\JavaTest\\dest.txt");

    InputStreamReader isr = null;
    OutputStreamWriter osw = null;
    try {
        FileInputStream fis = new FileInputStream(src);
        FileOutputStream fos = new FileOutputStream(dest);

        isr = new InputStreamReader(fis, "UTF-8");
        osw = new OutputStreamWriter(fos, "UTF-8");

        char[] buff = new char[1024];
        int len;
        while (-1 != (len = isr.read(buff))) {
            osw.write(buff, 0 , len);
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (null != isr) {
            try {
                isr.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (null != osw) {
            try {
                osw.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

2.7 数据流

  DataInputStream和DataOutputStream,用于读写基本数据类型变量和String字符串

@Test
public void testDataStream() throws Exception {
    DataOutputStream dos = new DataOutputStream(new FileOutputStream("E:\\JavaTest\\test.dat"));
    dos.writeUTF("学海无涯");
    dos.flush();
    dos.writeInt(123);
    dos.flush();
    dos.writeBoolean(false);
    dos.flush();
    dos.close();

    DataInputStream dis = new DataInputStream(new FileInputStream("E:\\JavaTest\\test.dat"));
    // 读的顺序要与写的顺序一致
    System.out.println(dis.readUTF());
    System.out.println(dis.readInt());
    System.out.println(dis.readBoolean());
    dis.close();
}

2.8 对象流

  ObjectInputStream和ObjecOutputStream,用于读写基本数据类型变量和对象,使用方法与上文的数据流基本相似

  • 序列化:保存基本类型数据或对象

    自定义的对象要想实现序列化,对应类得满足以下条件

    1、实现Serializable接口

    2、为该类提供全局变量serialVersionUID,类型是static final long

    3、该类的内部属性必须是可序列化的

    4、不能序列化static或transient修饰的内部属性

  • 反序列化:读取基本类型数据或对象

3. RandomAccessFile

3.1 相关说明

  • 该类直接继承于Object类,实现了DataInput和DataOutput接口。可用于修改文本文件

  • 既可以作为输入流,也可以作为输出流

    作为输出流时,如果文件不存在,则会自动创建;如果存在,则会覆盖原文件,但不是全部覆盖,是从头覆盖,能覆盖多少算多少

3.2 例题

  需求:以追加的形式修改文本文件内容,从"123456789"修改为"123abc456789"

@Test
public void test2() throws Exception {
    // 原文件内容为"123456789"
    RandomAccessFile raf = new RandomAccessFile(new File("E:\\JavaTest\\hello.txt"), "rw");

    // 把指针移到下标为3的位置
    raf.seek(3);
    // 保存下标3后面的字符
    StringBuilder sb = new StringBuilder((int) new File("E:\\JavaTest\\hello.txt").length());
    byte[] buff = new byte[20];
    int len;
    while (-1 != (len = raf.read(buff))) {
        sb.append(new String(buff, 0, len));
    }

    // 追加"abc"
    raf.seek(3);
    raf.write("abc".getBytes());

    // 再添加原来的字符
    raf.write(sb.toString().getBytes());
    raf.close();
}

4. 相关链接