【Java SE】I/O流、File类

写在前面

  • 关于文章
    本篇文章主要学习了JavaSE的基础进阶内容的I/O流框架、File类等。

Java IO 概述

Java的IO是实现输入和输出的基础,可以方便的实现数据的输入和输出操作。在Java中对于输入/输出操作是以的方式进行操作的。java.io包下提供了大量供我们使用操作的方法和接口,用于进行各类数据的处理和传输。

计算机的输入和输出都是通过二进制来完成的。在网络中我们要传递数据就要将数据流化,换句话说就是将文件、复杂的对象转化成能够在网络上传输的一个个的0和1。

前置概念

I/O是Input/Output的缩写, I/O技术是非常实用的技术,如读/写文件,网络通讯等等。

流(Stream)是指从源节点到目标节点的数据流动。

源节点目标节点可以是文件、网络、内存、键盘、显示器等等。

源节点的数据流称为输入流(用来读取数据)。

目标节点的数据流称为输出流(用来写入数据)。

源节点的数据流称为输入流。输入流用于从源读取数据到内存,而输出流用于从内存向目标写入数据。注意:以内存为中心

流的分类

按操作数据单位不同分为:字节流(8 bit),字符流(16 bit)在java中,字节是占1个Byte,即8位;而字符是占2个Byte,即16位。而且,需要注意的是,java的字节是有符号类型,而字符是无符号类型!

按数据流的流向不同分为:输入流,输出流

按流的角色的不同分为:节点流,处理流

1.Java的IO流共涉及40多个类,实际上非常规则,都是从如下4个抽象基类派生的。

2.由这四个类派生出来的子类名称都是以其父类名作为子类名后缀。

(抽象基类) 字节流 字符流
输入流 InputStream Reader
输出流 OutputStream Writer

Java IO框架

 

字符流

Reader

Reader是字符输入流的抽象基类,用于读取字符流的抽象类。 子类必须实现的唯一方法是read(char [],int,int)和close()。 然而,大多数子类将覆盖这里定义的一些方法,以便提供更高的效率,附加的功能或两者。

Reader的方法列表如下:

abstract void close() 关闭流并释放与之相关联的任何系统资源。
void mark(int readAheadLimit) 标记流中的当前位置。
boolean markSupported() 告诉这个流是否支持mark()操作。
int read() 读一个字符
int read(char[] cbuf) 将字符读入数组。
abstract int read(char[] cbuf, int off, int len) 将字符读入数组的一部分。
int read(CharBuffer target) 尝试将字符读入指定的字符缓冲区。
boolean ready() 告诉这个流是否准备好被读取。
void reset() 重置流。
long skip(long n) 跳过字符

FileReader

FileReader的构造方法
FileReader​(File file) 创建一个新的 FileReader ,给出 File读取。 
FileReader​(FileDescriptor fd) 创建一个新的 FileReader ,给予 FileDescriptor从中读取。 
FileReader​(String fileName) 创建一个新的 FileReader ,给定要读取的文件的名称。 
FileReader的使用示例
public class FileReader01 {
    public static void main(String[] args) {
        FileReader fr = null;

        try {
            // 创建一个文件读取流对象,和指定名称的文件相关联。
            // 要保证该文件是已经存在的,如果不存在,会发生异常FileNotFoundException
            fr = new FileReader("demo.txt");

            //调用读取流对象的read方法。
            //read():一次读一个字符。而且会自动往下读。
            int ch = 0;
            while ((ch = fr.read()) != -1) {
                System.out.print((char) ch);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fr != null){
                //关闭流
                try {
                    fr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

第二种方式:通过字符数组进行读取。

public class FileReader02 {
    public static void main(String[] args) {
        FileReader fr = null;
        try {
            fr = new FileReader("demo.txt");
            char[] chars = new char[1024];
            int len = 0;
            while ((len = fr.read(chars)) != -1){
                System.out.println(new String(chars, 0, len));
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fr != null){
                try {
                    fr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

BufferedReader

BufferedReader的构造方法
BufferedReader​(Reader in) 创建使用默认大小的输入缓冲区的缓冲字符输入流。 
BufferedReader​(Reader in, int sz) 创建使用指定大小的输入缓冲区的缓冲字符输入流。 
BufferedReader的方法列表
void close​() 关闭流并释放与之相关联的任何系统资源。 
Stream<String> lines​() 返回一个 Stream ,其元素是从这个 BufferedReader读取的行。 
void mark​(int readAheadLimit) 标记流中的当前位置。 
boolean markSupported​() 告诉这个流是否支持mark()操作。 
int read​() 读一个字符 
int read​(char[] cbuf, int off, int len) 将字符读入数组的一部分。 
String readLine​() 读一行文字。 
boolean ready​() 告诉这个流是否准备好被读取。 
void reset​() 将流重置为最近的标记。 
long skip​(long n) 跳过字符 
BufferedReader的使用示例

字符读取流缓冲区:
该缓冲区提供了一个一次读一行的方法 readLine,方便于对文本数据的获取。
当返回null时,表示读到文件末尾。
readLine方法返回的时候只返回回车符之前的数据内容。并不返回回车符。

public class BufferedReaderDemo {
    public static void main(String[] args)
    {
        BufferedReader bufr = null;
        try {
            //创建一个读取流对象和文件相关联。
            FileReader fr = new FileReader("buf.txt");

            //为了提高效率。加入缓冲技术。将字符读取流对象作为参数传递给缓冲对象的构造函数。
            bufr = new BufferedReader(fr);

            String line = null;

            while((line=bufr.readLine())!=null)
            {
                System.out.print(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (bufr != null){
                //关闭流
                try {
                    bufr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

通过缓冲区复制一个.java文件。

// 通过缓冲区复制一个.java文件到桌面。
public class CopyTextByBuf {
    private static String sourPath = "src/io/demo/BufferWriterDemo.java";
    private static String destPath = "C:\\Users\\Smile\\Desktop\\copy.txt";
    public static void main(String[] args) {

        BufferedReader br = null;
        BufferedWriter bw = null;
        try {
            FileReader fr = new FileReader(sourPath);
            FileWriter fw = new FileWriter(destPath);

            br = new BufferedReader(fr);
            bw = new BufferedWriter(fw);

            String line = null;
            int num = 1;
            while ((line = br.readLine())!= null){
                // 加上行号
                line = num++ +". " + line;
                bw.write(line);
                // 每写完一行进行换行操作
                bw.newLine();
                // 强制清空缓存
                bw.flush();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (br != null){
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (bw != null){
                try {
                    bw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

Writer

Writer是字符输出流的抽象基类,Writer的主要方法如下:

Writer append​(char c) 将指定的字符附加到此Writer
Writer append​(CharSequence csq) 将指定的字符序列附加到此Writer
Writer append​(CharSequence csq, int start, int end) 将指定字符序列的子序列附加到此Writer
abstract void close​() 关闭流,先刷新
abstract void flush​() 刷新流 
void write​(char[] cbuf) 写入一个字符数组。 
abstract void write​(char[] cbuf, int off, int len) 写入字符数组的一部分 
void write​(int c) 写一个字符 
void write​(String str) 写一个字符串 
void write​(String str, int off, int len) 写一个字符串的一部分

FileWriter

FileWriter的构造方法
FileWriter(File file) 给一个File对象构造一个FileWriter对象。
FileWriter(File file, boolean append) 给一个File对象构造一个FileWriter对象。
FileWriter(FileDescriptor fd) 构造与文件描述符关联的FileWriter对象。
FileWriter(String fileName) 构造一个给定文件名的FileWriter对象。
FileWriter(String fileName, boolean append) 构造一个FileWriter对象,给出一个带有布尔值的文件名,表示是否附加写入的数据。
FileWriter的方法列表
Writer append​(CharSequence csq) 将指定的字符序列附加到此Writer。 
Writer append​(CharSequence csq, int start, int end) 将指定字符序列的子序列附加到此Writer。 
void close​() 关闭流,先刷新。 
void flush​() 刷新流。 
String getEncoding​() 返回此流使用的字符编码的名称。 
void write​(char[] cbuf, int off, int len) 写入字符数组的一部分。 
void write​(int c) 写一个字符 
void write​(String str, int off, int len) 写一个字符串的一部分。 
FileWriter使用示例

例1:创建一个文件demo.txt,然后向里面写入字符串abcde

public class FileWriter01 {
    public static void main(String[] args) {
        FileWriter fw = null;
        try {
            // 创建一个FileWriter对象。该对象一被初始化就必须要明确被操作的文件。
            // 而且该文件会被创建到指定目录下。如果该目录下已有同名文件,将被覆盖。
            // 其实该步就是在明确数据要存放的目的地。
            fw = new FileWriter("demo.txt");

            //调用write方法,将字符串写入到流中。
            fw.write("abcde");

            // 刷新流对象中的缓冲中的数据。
            // 将数据刷到目的地中。
            // fw.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fw != null){
                try {
                    // 关闭流资源,但是关闭之前会刷新一次内部的缓冲中的数据。将数据刷到目的地中。
                    // 和flush区别:flush刷新后,流可以继续使用,close刷新后,会将流关闭。
                    fw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }
}

例2:上面的那种方式写入文件时,会将之前的文件覆盖了,之前文件中写的内容不存在了,那么如何在已有的文件后面添加内容

public class FileWriter02 {
    // 演示对已有文件的数据续写。
    public static void main(String[] args) {
        // 传递一个true参数,代表不覆盖已有的文件。并在已有文件的末尾处进行数据续写。
        FileWriter fw = null;
        try {
            fw = new FileWriter("demo.txt", true);
            fw.write("我是追加的内容");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fw != null){
                try {
                    fw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

BufferedWriter

BufferedWriter 是缓冲字符输出流。它继承于Writer。
BufferedWriter 的作用是为其他字符输出流添加一些缓冲功能,使用BufferedWriter可以提高我们写入文件的效率。

BufferedWriter的构造方法
BufferedWriter(Writer out) 创建使用默认大小的输出缓冲区的缓冲字符输出流。 
BufferedWriter(Writer out, int sz) 创建一个新的缓冲字符输出流,使用给定大小的输出缓冲区。
BufferedWriter的方法列表
void close​() 关闭流,先刷新。 
void flush​() 刷新流。 
void newLine​() 写一行行分隔符。 
void write​(char[] cbuf, int off, int len) 写入字符数组的一部分。 
void write​(int c) 写一个字符 
void write​(String s, int off, int len) 写一个字符串的一部分。 
BufferedWriter使用示例
public class BufferWriterDemo {
    public static void main(String[] args) {
        BufferedWriter bw= null;
        try {
            //创建一个字符写入流对象。
            FileWriter fw = new FileWriter("buf.txt");
            //为了提高字符写入流效率。加入了缓冲技术。
            //只要将需要被提高效率的流对象作为参数传递给缓冲区的构造函数即可。
            bw = new BufferedWriter(fw);
            char[] c={'a','b','c','d','e'};
            bw.write(c,0,4);
            //换行
            bw.newLine();
            //再次写入
            bw.write(c,2,2);
            //刷新流
            bw.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (bw != null){
                //其实关闭缓冲区,就是在关闭缓冲区中的流对象。
                try {
                    bw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }
    }
}

CharArrayReader

CharArrayReader 用于写入字符,它继承于Writer。操作的数据是以字符为单位

CharArrayReader的构造方法
CharArrayWriter() 创建一个新的CharArrayWriter。 
CharArrayWriter(int initialSize) 用指定的初始大小创建一个新的CharArrayWriter。 
CharArrayReader的方法列表
CharArrayWriter append​(char c) 将指定的字符附加到此Writer。 
CharArrayWriter append​(CharSequence csq) 将指定的字符序列附加到此Writer。 
CharArrayWriter append​(CharSequence csq, int start, int end) 将指定字符序列的子序列附加到此Writer。 
void close​() 关闭流。 
void flush​() 冲洗流。 
void reset​() 重置缓冲区,以便您可以再次使用它,而不会丢弃已经分配的缓冲区。 
int size​() 返回缓冲区的当前大小。 
char[] toCharArray​() 返回输入数据的副本。 
String toString​() 将输入数据转换为字符串。 
void write​(char[] c, int off, int len) 将字符写入缓冲区。 
void write​(int c) 将一个字符写入缓冲区。 
void write​(String str, int off, int len) 将一部分字符串写入缓冲区。 
void writeTo​(Writer out) 将缓冲区的内容写入另一个字符流。 

FilterWriter

FilterWriter是字符类型的过滤输出流

FilterWriter的构造方法
protected  FilterWriter​(Writer out) 创建一个新的过滤的Writer。 
FilterWriter的方法列表
void close​() 关闭流,先刷新。 
void flush​() 刷新流。 
void write​(char[] cbuf, int off, int len) 写入字符数组的一部分。 
void write​(int c) 写一个字符 
void write​(String str, int off, int len) 写一个字符串的一部分。 

PrintWriter

PrintWriter 是字符类型的打印输出流,它继承于Writer。

PrintWriter 的构造方法
PrintWriter​(File file) 使用指定的文件创建一个新的PrintWriter,而不需要自动的线路刷新。 
PrintWriter​(File file, String csn) 使用指定的文件和字符集创建一个新的PrintWriter,而不需要自动进行线条刷新。 
PrintWriter​(OutputStream out) 从现有的OutputStream创建一个新的PrintWriter,而不需要自动线路刷新。 
PrintWriter​(OutputStream out, boolean autoFlush) 从现有的OutputStream创建一个新的PrintWriter。 
PrintWriter​(Writer out) 创建一个新的PrintWriter,没有自动线冲洗。 
PrintWriter​(Writer out, boolean autoFlush) 创建一个新的PrintWriter。 
PrintWriter​(String fileName) 使用指定的文件名创建一个新的PrintWriter,而不需要自动执行行刷新。 
PrintWriter​(String fileName, String csn) 使用指定的文件名和字符集创建一个新的PrintWriter,而不需要自动线路刷新。 
PrintWriter 的方法列表
PrintWriter append​(char c) 将指定的字符附加到此Writer。 
PrintWriter append​(CharSequence csq) 将指定的字符序列附加到此Writer。 
PrintWriter append​(CharSequence csq, int start, int end) 将指定字符序列的子序列附加到此Writer。 
boolean checkError​() 如果流未关闭,请刷新流并检查其错误状态。 
protected void clearError​() 清除此流的错误状态。 
void close​() 关闭流并释放与之相关联的任何系统资源。 
void flush​() 刷新流。 
PrintWriter format​(String format, Object... args) 使用指定的格式字符串和参数将格式化的字符串写入此写入程序。 
PrintWriter format​(Locale l, String format, Object... args) 使用指定的格式字符串和参数将格式化的字符串写入此写入程序。 
void print​(boolean b) 打印布尔值。 
void print​(char c) 打印一个字符 
void print​(char[] s) 打印字符数组。 
void print​(double d) 打印双精度浮点数。 
void print​(float f) 打印浮点数。 
void print​(int i) 打印一个整数。 
void print​(long l) 打印一个长整数。 
void print​(Object obj) 打印一个对象。 
void print​(String s) 打印字符串。 
PrintWriter printf​(String format, Object... args) 使用指定的格式字符串和参数将格式化的字符串写入该writer的方便方法。 
PrintWriter printf​(Locale l, String format, Object... args) 使用指定的格式字符串和参数将格式化的字符串写入该writer的方便方法。 
void println​() 通过写入行分隔符字符串来终止当前行。 
void println​(boolean x) 打印一个布尔值,然后终止该行。 
void println​(char x) 打印一个字符,然后终止该行。 
void println​(char[] x) 打印字符数组,然后终止行。 
void println​(double x) 打印双精度浮点数,然后终止行。 
void println​(float x) 打印一个浮点数,然后终止该行。 
void println​(int x) 打印一个整数,然后终止该行。 
void println​(long x) 打印一个长整型,然后终止行。 
void println​(Object x) 打印一个对象,然后终止该行。 
void println​(String x) 打印一个字符串,然后终止行。 
protected void setError​() 表示发生错误。 
void write​(char[] buf) 写入一个字符数组。 
void write​(char[] buf, int off, int len) 写一个字符数组的一部分。 
void write​(int c) 写一个字符 
void write​(String s) 写一个字符串 
void write​(String s, int off, int len) 写一个字符串的一部分。 

字节流

字节流的基本操作和字符流类相同,但它不仅可以操作字符,还可以操作其他媒体文件

InputStream

InputStream类是字节输入流的抽象类,是所有字节输入流的父类。

InputStream的常用方法:

int available​() 从下一次调用此输入流的方法返回可从该输入流读取(或跳过)的字节数,而不会阻塞。 
void close​() 关闭此输入流并释放与流相关联的任何系统资源。 
void mark​(int readlimit) 标记此输入流中的当前位置。 
boolean markSupported​() 测试此输入流是否支持 mark和 reset方法。 
abstract int read​() 从输入流读取数据的下一个字节。 
int read​(byte[] b) 从输入流中读取一些字节数,并将它们存储到缓冲器阵列 b 。 
int read​(byte[] b, int off, int len) 从输入流读取最多 len个字节的数据到字节数组。 
byte[] readAllBytes​() 从输入流读取所有剩余字节。 
int readNBytes​(byte[] b, int off, int len) 将所请求的字节数从输入流读入给定的字节数组。 
void reset​() 将此流重新定位到最后在此输入流上调用 mark方法时的位置。 
long skip​(long n) 跳过并丢弃来自此输入流的 n字节的数据。 
long transferTo​(OutputStream out) 从该输入流中读取所有字节,并按读取的顺序将字节写入给定的输出流。 

FileInputStream

FileInputStream的构造方法
FileInputStream​(File file) 通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的 File对象 file命名。 
FileInputStream​(FileDescriptor fdObj) 通过使用文件描述符 fdObj创建 FileInputStream ,该文件描述符表示与文件系统中的实际文件的现有连接。 
FileInputStream​(String name) 通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的路径名 name命名。 
FileInputStream的方法列表
int available​() 返回从此输入流中可以读取(或跳过)的剩余字节数的估计值,而不会被下一次调用此输入流的方法阻塞。 
void close​() 关闭此文件输入流并释放与流相关联的任何系统资源。 
protected void finalize​() 已过时。
finalize方法已被弃用。 为了执行清理而覆盖finalize子类应该修改为使用替代清理机制,并删除覆盖的finalize方法。 当覆盖finalize方法时,其实现必须明确确保按照super.finalize()所述调用super.finalize() 。 有关迁移选项的更多信息,请参阅Object.finalize()的规范。 
FileChannel getChannel​() 返回与此文件输入流相关联的唯一的FileChannel对象。 
FileDescriptor getFD​() 返回表示与此 FileInputStream正在使用的文件系统中的实际文件的连接的 FileDescriptor对象。 
int read​() 从该输入流读取一个字节的数据。 
int read​(byte[] b) 从该输入流读取最多 b.length个字节的数据到一个字节数组。 
int read​(byte[] b, int off, int len) 从该输入流读取最多 len个字节的数据到字节数组。 
long skip​(long n) 跳过并从输入流中丢弃 n字节的数据。 
FileInputStream的使用示例
// 练习字节输入流
public class InputStreamTest {
    public static void main(String[] args) {
        // demo1();  // 汉字乱码
        // demo2();  // 汉字不乱码
        demo3();   // 汉字不乱码
    }


    //打开文件,一次读取刚刚好内容的字节
    private static void demo3() {
        FileInputStream fis = null;
        try {
            fis = new FileInputStream("D:\\Japroject\\Javabasic\\src\\test.txt");
            //available()返回从此输入流中可以读取(或跳过)的剩余字节数的估计值,而不会被下一次调用此输入流的方法阻塞。
            byte[] bytes = new byte[fis.available()]; // 定义一个刚刚好的缓冲区。不用在循环了。
            fis.read(bytes);
            System.out.print(new String(bytes));
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fis != null){
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    // 打开文件,一次读取一个字节
    private static void demo1(){
        InputStream is = null;
        try {
            is = new FileInputStream("D:\\Japroject\\Javabasic\\src\\test.txt");
            int ch = 0;
            while ((ch = is.read()) != -1){
                System.out.print((char)ch);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (is != null){
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }

    // 打开文件,一次读取多个字节
    private static void demo2(){
        InputStream is = null;
        try {
            is = new FileInputStream("D:\\Japroject\\Javabasic\\src\\test.txt");
            byte[] bytes = new byte[1024];
            int len = 0;
            while ((len = is.read(bytes)) != -1){
                System.out.print(new String(bytes, 0, len));
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (is != null){
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }
}

OutputStream

OutputStream字节输出流的方法:

void close​() 关闭此输出流并释放与此流相关联的任何系统资源。 
void flush​() 刷新此输出流并强制任何缓冲的输出字节被写出。 
void write​(byte[] b) 将 b.length字节从指定的字节数组写入此输出流。 
void write​(byte[] b, int off, int len) 从指定的字节数组写入 len字节,从偏移量 off开始输出到此输出流。 
abstract void write​(int b) 将指定的字节写入此输出流。 

FileOutputStream

OutputStream的构造方法
FileOutputStream​(File file) 创建文件输出流以写入由指定的 File对象表示的文件。 
FileOutputStream​(FileDescriptor fdObj) 创建文件输出流以写入指定的文件描述符,表示与文件系统中实际文件的现有连接。 
FileOutputStream​(File file, boolean append) 创建文件输出流以写入由指定的 File对象表示的文件。 
FileOutputStream​(String name) 创建文件输出流以指定的名称写入文件。 
FileOutputStream​(String name, boolean append) 创建文件输出流以指定的名称写入文件。 
OutputStream的方法列表
void close​() 关闭此文件输出流并释放与此流相关联的任何系统资源。 
protected void finalize​() 已过时。
finalize方法已被弃用。 为了执行清理,覆盖finalize子类应被修改为使用替代的清理机制,并删除覆盖的finalize方法。 当覆盖finalize方法时,其实现必须明确确保按照super.finalize()中所述调用super.finalize() 。 有关迁移选项的更多信息,请参阅Object.finalize()的规范。 
FileChannel getChannel​() 返回与此文件输出流相关联的唯一的FileChannel对象。 
FileDescriptor getFD​() 返回与此流相关联的文件描述符。 
void write​(byte[] b) 将 b.length字节从指定的字节数组写入此文件输出流。 
void write​(byte[] b, int off, int len) 将 len字节从指定的字节数组开始,从偏移量 off开始写入此文件输出流。 
void write​(int b) 将指定的字节写入此文件输出流。 
OutputStream的使用示例
// 练习字节输出流
public class OutputStreamTest {
    private static String FileName = "test1.txt";
    public static void main(String[] args) {
        demo();
    }

    private static void demo(){
        FileOutputStream fileOut1 = null;
        FileOutputStream fileOut2 = null;
        try {
            // 创建文件“file.txt”对应File对象
            File file = new File(FileName);
            // 创建文件“file.txt”对应的FileOutputStream对象,默认是关闭“追加模式”
            fileOut1 = new FileOutputStream(file);
            // 向“文件中”写入26个字母
            String str = "abcdefghijklmnopqrstuvwxyz";
            fileOut1.write(str.getBytes());

            // 创建文件“file.txt”对应的FileOutputStream对象,打开“追加模式”
            fileOut2 = new FileOutputStream(file, true);
            // 向“文件中”写入"0123456789"+换行符
            String num = "0123456789";
            fileOut2.write(num.getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fileOut1 != null){
                try {
                    fileOut1.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fileOut2 != null){
                try {
                    fileOut2.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }
    }
}

File类

在 Java 中,File 类java.io 包中唯一代表磁盘文件本身的对象。File 类定义了一些与平台无关的方法来操作文件,File类主要用来获取或处理与磁盘文件相关的信息,像文件名、 文件路径、访问权限和修改日期等,还可以浏览子目录层次结构。

File 类表示处理文件和文件系统的相关信息。也就是说,File 类不具有从文件读取信息和向文件写入信息的功能,它仅描述文件本身的属性。

File 是“文件”和“目录路径名”的抽象表示形式。
File 直接继承于Object,实现了Serializable接口和Comparable接口。实现Serializable接口,意味着File对象支持序列化操作。而实现Comparable接口,意味着File对象之间可以比较大小;File能直接被存储在有序集合(如TreeSet、TreeMap中)。

File类的构造方法

构造器 描述
File(String pathname) 通过将给定路径名字符串来创建一个新 File 实例
File(String parent,String child) 根据指定的父路径和文件路径创建一个新File对象实例
File(File parent,String child) 根据指定的父路径对象和文件路径创建一个新的File对象实例

其实很简单的,其实这个意思:

File file = new File("D:\\code\\a.txt");
File file = new File("D:\\code\\","a.txt");
File file = new File("D:\\code");
File child = new File(file,"a.txt");

File类创建和删除功能

boolean createNewFile() 指定路径不存在该文件时创建文件,返回true 否则false
boolean mkdir() 当指定的单击文件夹不存在时创建文件夹并返回true 否则false
boolean mkdirs() 当指定的多级文件夹在某一级文件夹不存在时,创建多级文件夹并返回true 否则false
boolean delete() 删除文件或者删除单级文件夹

File类的判断功能

boolean exists() 判断指定路径的文件或文件夹是否为空
boolean isAbsolute() 判断当前路径是否是绝对路径
boolean isDirectory() 判断当前的目录是否存在
boolean isFile() 判断当前的目录是否是一个文件
boolean isHidden() 判断当前路径是否是一隐藏文件

File类的获取功能和修改名字功能

File getAbsoluteFile() 获取文件的绝对路径,返回File对象
String getAbsolutePath() 获取文件的绝对路径,返回路径的字符串
String getParent() 获取当前路径的父级路径,以字符串形式返回该父级路径
String getName() 获取文件或文件夹的名称
String getPath() 获取File对象中封装的路径
long lastModified() 以毫秒值返回最后修改时间
long length() 返回文件的字节数
boolean renameTo(File dest) 将当前File对象所指向的路径修改为指定File所指向的路径

文件夹列表操作

返回值 方法 描述
String list() 得到这个文件夹下的所有文件,返回路径数组
String[] list(FilenameFilter filter) 通过过滤器过滤文件,过滤通过文件名过滤,返回路径数组
File[] listFiles() 得到这个文件夹下的所有文件,返回文件数组
File[] listFiles(FileFilter filter) 通过过滤器过滤文件,过滤通过文件过滤,返回文件数组
File[] listFiles(FilenameFilter filter) 通过过滤器过滤文件,过滤通过文件名过滤,返回文件数组

File类的常用API

访问文件名:
getName()
getPath()
getAbsoluteFile()
getAbsolutePath()
getParent()
renameTo(File newName)
    
文件检测
exists()
canWrite()
canRead()
isFile()
isDirectory()
    
获取常规文件信息
lastModified()
length()

文件操作相关
createNewFile()
delete()

目录操作相关
mkDir()
mkDirs()
list()
listFiles()

对象的序列化

字节流也可以实现包装和链接,并且可以因此带来更为强大的功能,例如读写基本类型数据、读写对象等。

对象流

用于存储和读取基本数据类型数据或对象的处理流。它的强大之处就是可以把Java中的对象写入到数据源中,也能把对象从数据源中还原回来。

ObjectInputStream

序列化用ObjectOutputStream类保存基本类型数据或对象的机制

OjbectOutputSteam

反序列化用ObjectInputStream类读取基本类型数据或对象的机制

ObjectOutputStream和ObjectInputStream不能序列化static和transient修饰的成员变量

对象的序列化

对象序列化机制允许把内存中的Java对象转换成平台无关的二进制流,从而允许把这种二进制流持久地保存在磁盘上,或通过网络将这种二进制流传输到另一个网络节点。当其它程序获取了这种二进制流,就可以恢复成原来的Java对象。

序列化的好处在于可将任何实现了Serializable接口的对象转化为字节数据,使其在保存和传输时可被还原。

序列化是 RMI(Remote Method Invoke – 远程方法调用)过程的参数和返回值都必须实现的机制,而 RMI 是 JavaEE 的基础。因此序列化机制是 JavaEE 平台的基础

如果需要让某个对象支持序列化机制,则必须让其类是可序列化的,为了让某个类是可序列化的,该类必须实现如下两个接口之一:

Serializable

Externalizable

凡是实现Serializable接口的类都有一个表示序列化版本标识符的静态变量:

private static final long serialVersionUID

serialVersionUID用来表明类的不同版本间的兼容性

如果类没有显示定义这个静态变量,它的值是Java运行时环境根据类的内部细节自动生成的。若类的源代码作了修改,serialVersionUID 可能发生变化。故建议,显示声明。

显示定义serialVersionUID的用途

  • 希望类的不同版本对序列化兼容,因此需确保类的不同版本具有相同的serialVersionUID
  • 不希望类的不同版本对序列化兼容,因此需确保类的不同版本具有不同的serialVersionUID

使用对象流序列化对象

若某个类实现了 Serializable 接口,该类的对象就是可序列化的,准备一个User类并实现Serializable 接口

public class User implements Serializable {
    private static final long serialVersionUID = 12313465664L;
    private String name;
    private Integer age;
    private Character sex;

    public User() {
    }

    public User(String name, Integer age, Character sex) {
        this.name = name;
        this.age = age;
        this.sex = sex;
    }
    // geter... seter....
}

创建一个ObjectOutputStream

调用ObjectOutputStream 对象的writeObject(对象)方法输出可序列化对象。注意写出一次,操作flush()

public class OjbectOutputSteamTest {
    public static void main(String[] args) {
        User user1 = new User("张三", 18, '男');
        User user2 = new User("李四", 22, '女');
        User user3 = new User("王五", 20, '男');

        ObjectOutputStream oos = null;
        try {
            FileOutputStream fis = new FileOutputStream("./data.dat");
            oos = new ObjectOutputStream(fis);

            oos.writeObject(user1);
            oos.flush();
            oos.writeObject(user2);
            oos.flush();
            oos.writeObject(user3);
            oos.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (oos != null){
                try {
                    oos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

创建一个 ObjectInputStream

调用readObject方法读取流中的对象

public class ObjectInputStreamTest {
    public static void main(String[] args) {
        Object o1 = null;
        Object o2 = null;
        Object o3 = null;
        ObjectInputStream ois = null;
        try {
            FileInputStream fis = new FileInputStream("./data.dat");
            ois = new ObjectInputStream(fis);

            o1 = ois.readObject();
            o2 = ois.readObject();
            o3 = ois.readObject();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            if (ois != null){
                try {
                    ois.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        System.out.println(o1);
        System.out.println(o2);
        System.out.println(o3);
    }
}

强调:如果某个类的字段不是基本数据类型或 String 类型,而是另一个引用类型,那么这个引用类型必须是可序列化的,否则拥有该类型的 Field 的类也不能序列化

微信关注

WeChat

 

本站为非盈利性站点,所有资源、文章等仅供学习参考,并不贩卖软件且不存在任何商业目的及用途,如果您访问和下载某文件,表示您同意只将此文件用于参考、学习而非其他用途。
本站所发布的一切软件资源、文章内容、页面内容可能整理来自于互联网,在此郑重声明本站仅限用于学习和研究目的;并告知用户不得将上述内容用于商业或者非法用途,否则一切后果请用户自负。
如果本站相关内容有侵犯到您的合法权益,请仔细阅读本站公布的投诉指引页相关内容联系我,依法依规进行处理!
作者:理想
链接:https://www.imyjs.cn/archives/652
THE END
二维码
【Java SE】I/O流、File类
写在前面 关于文章本篇文章主要学习了JavaSE的基础……
<<上一篇
下一篇>>
文章目录
关闭
目 录