File与IO流

一、File类型

1.1 简介

在程序中,我们使用java.io.File这个类来描述和操作磁盘上的一个文件或文件夹(目录)。

File这个类,能新建、删除、移动,重命名文件或文件夹,也能获取或者修改文件或文件夹的信息(如大小,修改时间等),但File不能访问文件里的内容。如果需要访问文件里的内容,则需要使用输入/输出流。

1.2 绝对路径与相对路径

路径的定义:用来描述一个文件或者文件夹所存在的位置,可以分为 绝对路径相对路径

1.2.1 绝对路径

从磁盘的根目录开始,一层层的向内查找,直到找到这个文件。

在不同的操作系统中,根目录的表示方式可能略有不同。

例如:在UNIX和Linux系统中,根目录用正斜杠(/)表示,如/home/user/file.txt;                               在Windows系统中,根目录用驱动器名和冒号表示,如C:\Users\User\file.txt

1.2.2 相对路径

是相对于当前工作目录或另一个已知位置的路径。它描述的是文件或目录与当前位置之间的相对关系。相对路径通常省略了根目录部分,直接从当前目录开始描述路径。例如,假设当前工作目录是/home/user,要访问该目录下的文件file.txt,可以使用相对路径file.txt,而不需要写出完整的绝对路径。

./表示当前工作目录。 可以省略。

../表示返回到上一层目录。

例如:

当前工作空间是 /home/user/michael/

    -- 需求1:/home/user/michael/file1.txt
    -- 需求2:/home/user/michael/doc/file1.txt
    -- 需求3:/home/user/lucy/file1.txt
    -- 需求4:/home/user/lucy/doc/file1.txt

    需求1的答案 : ./file1.txt   或者file1.txt
    需求2的答案 : ./doc/file1.txt   或者doc/file1.txt
    需求3的答案 : ./../lucy/file1.txt    或者../lucy/file1.txt
    需求4的答案 : ./../lucy/doc/file1.txt    或者../lucy/doc/file1.txt

1.2.3 两者的主要区别

相对路径
完整性绝对路径提供了完整的文件或目录路径,从根目录开始,可以唯一地确定位置是相对于当前位置或已知位置的路径,它只提供了与当前位置或已知位置的相对关系。
简洁性从根开始写,路径比较长。相对路径相对于当前位置,通常比绝对路径更简洁,尤其是当文件或目录与当前位置在同一层级或子目录中时。
缺点一旦换一个文件系统,此时这个路径表示 的文件将无法找到只要两者的相对位置发生 了改变,这个文件将无法找到。

1.3 File的静态属性 

关于目录分隔符,在不同的操作系统中,不一样。在windows中,使用 \ 作为目录分隔符,但是,在 ⾮windows的操作系统中,例如: Linux、 Unix,使用 / 作为目录分隔符。

关于路径分隔符,在不同的操作系统中,不一样。在windows中,使用 ; 作为路径分隔符,但是,在 ⾮windows的操作系统中,例如: Linux、 Unix,使用 : 作为路径分隔符。

小贴士:虽然,在windows中,使用  \ 作为目录分隔符,但是大部分情况下,使用 / 也可以。

1.4 常用构造器

抽象路径应该尽量使用相对路径,并且目录的层级分隔符不要直接写/或者\,应该使用File.separator这个常量表示,以避免不同系统带来的差异。

1)File(String pathname):通过将指定字符串转换成抽象路径名来创建一个File实例。

File file = new File("D:/dir1");
File file = new File("D:"+File.separator+"dir1");

2)File(File parent,String child):从父抽象路径名和子路径名字符串创建新的File实例。

File parent = new File("D:/code");
File file2 = new File(parent,"BianLiang.java");

3)File(String parent,String child):从父路径名字符串和子路径名字符串创建新的File实例。

File file1 = new File("D:/code","BianLiang.java");

注意:构造器只负责用来接收程序员传入的路径,并不会校验这个路径是否真实存在。

1.5 文件属性的方法

以下方法都要使用File构造器来描述一个真实存在的路径。

1)String getName():返回文件或者目录(文件夹)的名称。

2)String getPath():返回路径名字符串,以构造器里面写的为准。

3)File getAbsolutePath():返回绝对路径。

4)String getParent():返回父路径,如果此路径名未指定父目录,则返回null。

5)boolean renameTo(File newName):重命名。

6)boolean exists():判断是否存在。

7)boolean canWrite():判断是不是可写文件,可写,一定可读。

8)boolean canRead():判断是不是可读文件。

9)boolean canExecute():判断是否可执行,可执行,一定可写。

10)boolean isFile():判断是不是文件。

11)boolean isDirectory():判断是不是文件夹(目录)。

12)long lastModify():返回最后一次修改时间,毫秒数。

13)long length():返回文件的长度,字节数。

1.6 文件的查询检索

1)String[] list()

返回一个字符串数组,返回指定文件夹里的子文件或者是子目录(文件夹)的名字。

File file = new File("D:/ideaProjects");
String[] lists = file.list();
//遍历
for (String list : lists) {
    System.out.println(list);
}

2)File[] listFiles()

返回指定文件夹里的子文件或者是子目录的File类型。

File file = new File("D:/ideaProjects");
File[] files = file.listFiles();
//遍历
for (File file1 : files) {
    System.out.println(file1.getName()+"   "+file1.getAbsolutePath());
}

3)String[] list(FilenameFilter filter)

返回一个字符串数组,命名由此抽象路径名表示的目录中满足指定过滤器的文件和目录。

File file = new File("D:/ideaProjects");

//定义一个过滤器对象:匿名内部类的方式
FilenameFilter filter = new FilenameFilter() {

//重写accept方法:编写过滤逻辑,name指的就是文件夹里面的每一个文件或者文件夹
//dir就是要操作的那个文件列表(文件夹)

public boolean accept(File dir, String name) {
    return name.endsWith(".java");
}
};
//遍历
String[] list = file.list(filter);
for (String s : list) {
    System.out.println(s);
}

1.7 文件的创建与删除

1.7.1 文件的创建

1)boolean creatNewFile()

当且仅当具有该名称的文件尚不存在时,创建一个由该抽象路径名命名的新的空文件。

2)boolean mkdir()

只能创建出一个空文件夹,不可以多层级创建

    public static void main(String[] args) throws IOException {
        //使用File来描述磁盘上的一个文件夹
        File dir1 = new File("D:/dir1");
        if (!dir1.exists()) {
            dir1.mkdir();
        }
        //此时,dir1一定存在了  在dir1里面创建一个叫file1.txt的文件
        File file1 = new File(dir1,"file1.txt");
        if (!file1.exists()) {
            file1.createNewFile();
        }
        //此时,file1.txt就一定存在了。
    }

3)boolean mkdirs()

创建由此抽象路径名命名的目录(文件夹),包括任何需要但不存在的父目录。 可以多层级创建

File file = new File("D:/dir11/dir22/dir33");
    if (!file.exists()) {
        file.mkdirs();
}

4)可以使用renameTo(File file)重命名的方法,达到移动文件的目的。

//这样原来在dir333文件夹里的file.txt就移动到了dir22文件夹下。
File file2 = new File("D:/dir11/dir22/dir333/file.txt");
File file3 = new File("D:/dir11/dir22/file.txt");
    if (file2.exists()){
        file2.renameTo(file3);
    }

1.7.2 文件的删除

boolean delete()

1.该方法只能删除文件或者空文件夹。

2.如果想用该方法删除非空文件夹,需要将里面的删除干净,把它变成一个空文件夹,然后才能被删除。(需要使用循环递归删除)

    public static void main(String[] args) {
        //创建一个文件类型的对象
        File file = new File("D:/dir11/dir22/file1.txt");
        if (file.exists()) {
            boolean f = file.delete();
            //false,因为文件夹里面有东西,不是空的,无法删除
            System.out.println("f:"+f);
        }
        //测试: 删除D:/dir11
        File f = new File("D:/dir11");
        //调用delete(File file)方法删除
        delete(f);
    }
    public static void delete(File file) {
        if(!file.exists()){
            System.out.println("要删除的文件或者文件夹不存在");
        }
        //if执行完,如果是文件夹,里面的内容清空了,然后自己就是空文件夹了,就可以被删除了。
        if(file.isDirectory()) {
            //获取文件夹里的内容。
            File[] lists = file.listFiles();
            //遍历每一个文件夹或者文件
            for(File f : lists) {
                //f可能是文件夹,可能是文件,再次调用该方法。
                delete(f);//调用自己
            }
        }
        //如果不是文件夹,是文件,直接删除。
        file.delete();
    }

二、IO流基础

2.1 IO流的概念

我们在编程时,除了自身定义一些数据信息外,经常还会引入外界的数据,或者是将自身的数据发送给外界。如:编程时,想读取硬盘上的某一个文件,又或者想将程序中的某些数据写入到硬盘上的一个文件里。这时,我们就要使用I/O流。

这个“外界”范围很广,包括诸如键盘、显示器、文件、磁盘、网络、另外一个程序等。
“数据”也可以是任何类型的,例如一个对象、串字符、图像、声音等。

IO流:Input Output Stream

1)Input(输入):是指数据的流入程序,通常我们读取外界数据时使用,所以输入是用来读取数据的。

2)Output(输出):是指数据从程序程序流出,通常我们需要写出数据到外界时使用,所以输出是用来写出数据的。

总结:

       1. 一个流就是一个从数据源向目的地的数据序列。

       2. I/O流类一旦被创建就会自动打开。

       3. 通过调用close方法,可以显式关闭任何一个流,如果流对象不再被引用,Java的垃圾回                 收机制也会隐式地关闭它。

       4. 不论数据从哪来,到哪去,也不论数据本身是何类型,读写数据的方法大体上都是一样的。

1.打开一个输入流

2.读信息

3.关闭流

1.打开一个输出流

2.写信息

3.关闭流

2.2 IO流的分类 

按照数据的流向分类:1. 输入流(InputStream)2. 输出流(OutputStream)

按照处理数据的单位分类:1.字节流     2.字符流

按照流的功能分类:

1. 节点流:可以从一个特定的IO设备上读/写数据的流。也称之为低级流

2. 处理流:是对一个已经存在的流的连接和封装,通过所封装的流的功能调用实现数据读/写操作。通常处理流的构造器上都会带有一个其他流的参数。也称之为高级流或者过滤流

2.3 IO流的应用场景

传统的文件File类,只能够对文件进行属性的操作,例如:创建、移动、删除、属性获取等操作。但是不能获取到文件中的内容。

如果需要对文件中的内容进行读写操作,需要使用到IO流。

使用场景:对磁盘或者网络中的文件件进行读写操作。

2.4 IO流的体系结构

 2.5 字节流

2.5.1 字节流的简介

InputStream是字节输入流的顶级父类,是抽象类。定义了基本的读取方法。

OutputStream是字节输出流的顶级父类,也是一个抽象类,定义了基本的写出方法。

1)InputStream定义的方法

1. int read() : 从输入流中读取一个字节,把它转换为0-255之间的整数,并返回这一整数,如果返回-1,说明读到文件末尾。

2. int read(byte[] b) : 从输入流中读取若干个字节,把它们保存到缓冲区b中,返回的整数表示读取的字节数,如果遇到输入流的结尾,返回-1。

3. int read(byte[] b, int off, int len) : 从输入流读取 len个字节的数据到一个字节数组。从指定下标off开始存。返回的整数表示实际读取的字节数。如果遇到输入流的结尾,返回-1。

4. void close() : 关闭输入流。

5. int available() : 返回可以从输入流中读取的字节数目。

6. long skip() : 从输入流中跳过参数n指定数目的字节。

7. boolean markSupported() : 测试这个输入流是否支持 mark和 reset方法。 

8. void mark() : 标记此输入流中的当前位置。

9. void reset() : 将此流重新定位到上次在此输入流上调用 mark方法时的位置。

2)OutputStream定义的方法

1. void write(int b) : 向输出流写出一个字节。

2. void write(byte[] b) : 将b.length个字节从指定的字节数组写入此输出流。

3. void close() : 关闭输出流。

4. void flush() :OutputStream类本身的flush方法不执行任何操作,它的一些带缓冲区的子类覆盖了flush方法,该方法强制把缓冲区内的数据写到输出流中。

2.6 常用字节流

2.6.1 文件流

1)FileOutputStream:文件输出字节流,是OutputStream的子类型,是一个低级流(节点流),用于连接文件和程序的。以字节为单位写出数据到文件。

重写模式的构造器:

1. FileOutputSteam(File file):会将文件中原有的覆盖掉。

2. FileOutputSteam(String pathname):会将文件中原有的覆盖掉。

追加模式的构造器:

1. FileOutputSteam(File file,boolean append):当append为true时,有追加效果。

2. FileOutputSteam(String pathname,boolean append):当append为true时,有追加效果。

注意:输出流不会帮助我们创建不存在的文件夹,但是如果文件不存在,则会帮助我们创建出来。

    public static void main(String[] args) {
        //向D盘的file1.txt写东西
        FileOutputStream fos =null;
        try {
            //重写模式的构造器:fos = new FileOutputStream("D:/file1.txt");
            //使用追加模式的构造器
            fos = new FileOutputStream("D:/file1.txt",true);
            //写一个A
            fos.write('A');//fos.write(65);
            //将B~Z写到文件中
            for(int i = 66;i <= 90;i++){
                fos.write(i);//注意:每写一次,都会与磁盘进行交互一次。次数越多性能越差。
            }
            //将"hello world"写入文件中。
            byte[] bytes = "hello world".getBytes("UTF-8");
            //fos.write(bytes);
            fos.write(bytes,0,7);
        }catch(IOException e) {
            e.printStackTrace();
        }finally{
            try {
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

FileInputStream:文件的字节输入流,是InputStream抽象类的子类型,是一个低级流,用于连接文件和程序,该流以字节为单位从文件中读取数据。

常用构造器:

1. FileInputStream(File file)

2. FileInputStream(String name)

    public static void main(String[] args) {
        FileInputStream fis = null;
        try {
            fis = new FileInputStream("D:/file1.txt");
            //读取一个字节
            int ch = fis.read();//65
            System.out.println((char)ch);//A
            //读取后续的10个字节
            for(int i = 0; i < 10;i++){
                ch = fis.read();//每读取一次都会与磁盘交互一次,次数越多,性能越差。
                System.out.println((char)ch);
            }
            //提前创建一个10个长度的byte数组
            byte[] bs = new byte[10];
            //将数据读到数组中了
            int length = -1;
            while((length=fis.read(bs))!=-1){ //大大减少了与磁盘的交互次数
                String str = new String(bs,0,length);
                System.out.println(str);
            }
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
运行结果:
A
B
C
D
E
F
G
H
I
J
K
LMNOPQRSTU
VWXYZhello
 w

2.6.2 缓冲流

在向硬件设备做写出操作时,增大写出次数无疑会降低写出效率,为此,我们可以使用缓冲输出流来一次性批量写出若干数据来减少写出次数来提高写出效率。

1)BufferedOutputStream:字节缓冲输出流,是一个高级流

1. 内部维护了一个字节数组作为缓冲区(缓存) : 默认值是8KB。

2. 当我们写数据时,是先写到缓存中的,并不是直接写到磁盘上。当缓存满的情况下,再一次性将数据写到磁盘,从而减少了与磁盘的交互次数,提高了写出效率。

3. 最后一次写入到缓存后,又可能没装满,我们可以调用flush方法,将其强制写到磁盘上。

4. 常用构造器:

1. BufferedOutputStream(OutputStream os)

2. BufferedOutputStream(OutputStream os,int size) : size用于自定义缓冲区的大小。

当有多个流需要关闭时,应该先关闭高级流,然后再关闭低级流。不过,可以直接关闭高级流。

    public static void main(String[] args) {
        BufferedOutputStream bos = null;
        FileOutputStream fos = null;
        try{
            fos = new FileOutputStream("D:/file2.txt", true);
            bos = new BufferedOutputStream(fos);
            //将A写入缓冲区
            bos.write('A');
            //将"helloworld"写入到缓存区
            byte[] bytes = "helloworld".getBytes("UTF-8");
            bos.write(bytes);
            bos.write(bytes,0,bytes.length);
            bos.flush();// 即使没有关闭流,也会强制冲刷缓冲区
        }catch(IOException e) {
            e.printStackTrace();
        }finally{
            try {
                /**
                 * 多个流的关闭顺序,应该先关高级流,然后再关低级流。
                 * 不过,可以直接关闭高级流。
                 */
                //bos.close();
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

2)BufferedInputStream  字节缓冲输入流,是一个高级流

1.内部维护着一个缓冲区,默认8KB。

2. 在读取文件中的数据时,一次性尽可能的读取到缓冲区大小的字节。

3. read()从缓存区中获取数据。当缓冲区的数据全部获取完,会再次从磁盘上读取数据,存入到缓冲区。

4. 常用构造器 :

1.BufferedInputStream(InputStream is)

2.BufferedInputStream(InputStream is,int size)

    public static void main(String[] args) {
        BufferedInputStream bis = null;
        try{
            bis = new BufferedInputStream(new FileInputStream("D:/file1.txt"),10);
            //读取一个字节
            int ch = bis.read();
            System.out.println((char)ch);
            //一次性读取多点字节
            byte[] bytes = new byte[10];
            int len = -1;
            //读到文件末尾,返回-1.
            while((len = bis.read(bytes))!=-1){
                String str = new String(bytes,0,len);
                System.out.println(str);
            }
        }catch(IOException e){
            e.printStackTrace();
        }finally{
            try {
                bis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

2.6.3 数据流

1)DataOutputStream  字节数据输出流。

是字节过滤流(FilterOutputStream)的子类型,其扩展了一些功能,可以直接书写基本数据类型和字符串类型。

构造器:DataOutputStream(OutputStream os)

将流的创建写到try模块的()中,当流不再使用时,会自动关闭流对象。

    public static  void main(String[] args) {
        /**
         * 将流的创建写到try模块的()中,当流不再使用时,会自动关闭流对象。
         */
        try(DataOutputStream dos = new DataOutputStream(
                new FileOutputStream("D:/file3.txt"))){
            dos.writeInt(10);//4个字节
            dos.writeDouble(3.14);//8个字节
            dos.writeBoolean(true);//1个字节
            dos.writeUTF("你是最棒的");
            //15个字节+2个字节  注意:每写一次UTF的字符串,都会使用两个字节来记录字符串的长度。
            dos.writeUTF("你是最棒的");
            dos.flush();
        }catch(IOException e){
            e.printStackTrace();
        }
    }

2)DataInputStream 字节数据输入流。

是字节过滤流(FilterOutputStream)的子类型,其扩展了一些功能,可以直接书写基本数据类型和字符串类型。

构造器:DataInputStream(InputStream is)

    public static void main(String[] args) {
        try(DataInputStream dis = new DataInputStream(
                new BufferedInputStream(new FileInputStream("D:/file3.txt")))){
            int nums = dis.readInt();
            double v = dis.readDouble();
            boolean b = dis.readBoolean();
            String s = dis.readUTF();
            System.out.println(nums);
            System.out.println(v);
            System.out.println(b);
            System.out.println(s);
        }catch(IOException e){
            e.printStackTrace();
        }
    }

2.6.4 对象流

对象是存在于内存中的,有的时候我们需要将对象保存到硬盘上,又有时我们需要将对象传输到另一台计算机上等等这些的操作。

此时,我们需要将对象转换成一个字节序列也就是字节数组,这个过程我们称之为序列化,目的是存储或传输。

相反,我们将一个字节序列(字节数组)转换成对应的对象,这个过程我们称之为反序列化 。

我们可以通过ObjectOutputStream流的方法WriteObject(Object o)实现对象序列化,通过ObjectInputStream流的方法readObject()实现对象反序列化。

常用构造器:

ObjectOutputStream(OutputStream os) : 序列化

ObjectInputStream(InputStream os) : 反序列化

1)Serializable接口

自定义的类型,如果想要将其对象进行存储或者传输,那么这个类必须要实现一个接口。这个接口就是Serializable,该接口里面什么都没有,就是一个规范,一个标识。

2)serialVersionUID:序列化版本号。

1. 在序列化时,系统会默认给该类提供一个版本号。 当反序列化时,就会检查该类的版本号与对象的版本号是否一致,如果一致,就可以反序列化,反之,反序列化失败,报异常,版本号不兼容。

注意:系统提供的版本号可能会发生变化,不同的时间点可能不同。

2. 为了避免上述情况发生,程序员应该主动为类型提供一个固定的版本号。这样序列化时和反序列化时用的都是同一个版本号,就不会报版本号不兼容的异常了。

3)transient关键字

1. 用于修饰成员变量。

2. 当序列化时,某一个属性的信息不需要保存或者传输,也就是不重要的意思。那么就可以使用transient。

知识扩展:

1. 序列化时,程序每执行一次,都会先写一个流头。如果是追加模式。那么文件中可能会有多个流头。

2. 反序列化时,也就是读取文件时,默认是只读取一次流头,剩下的内容全部认为是每个对象的信息。所以,文件中有多个流头时,可能会将除了第一个流头外,剩下的流头字节序列当成对象信息进行解析,会报异常:java.io.StreamCorruptedException:invalid type code:AC

2.7 字符流

2.7.1 字符流的简介

Reader是字符输入流的父类,抽象类;Writer是字符输出流的父类,抽象类。字符流是以字符(char)为单位读写数据的,一次处理一个unicode。字符流的底层仍然是基本的字节流。

1)Reader的常用方法

int read()  读一个字符

int read(char[] cbuf) 将字符读入数组。

abstract int read(char[] cbuf,int off,int len) 将字符读入数组的一部分,off开始,len结束。

2)Writer的常用方法

void write(char[] cbuf) 将一个字符数组写出去。

abstract void write(char[] cbuf, int off, int len) 写入字符数组的一部分,off开始,len结束。

void write(int c) 写一个字符

void write(Sting str) 写一个字符串

void write(String str, int off, int len) 写一个字符串的一部分,off开始,len结束。

2.7.2 转换流

1)OutputStreamWriter :字符转换输出流,高级流,抽象父类Writer。

书写单位,以一个char为单位。 

底层依然是字节流。

基本的字符流,我们称之为转换流,因为涉及到字符与字节之间的转换所使用的编码集。

在编写代码时的字符集,默认使用的是UTF-8,一个字母占一个字节,一个汉字占三个字节。

常用构造器:

1. OutputStreamWriter(OutputStream os)

2. OutputStreamWriter(OutputStream os,String charsetName)

常用的字符集:UTF-8  GBK GB2312 UNICODE

                         ISO8859-1: HTTP 通信时使用的

2)InputStreamReader:字符输入转换流,高级流,抽象父类Reader。

使用该流可以设置字符集,并按照指定的字符集从流中按照该编码将字节数据转换为字符并读取。

常用构造器:

1. InputStreamReader(InputStream is,String charsetName)

2. InputStreamReader(InputStreamReader is)

2.7.3 缓冲字符流

1)BufferedReader:缓冲字符输入流,高级流。

1. 内部提供了缓冲区,可以提高读取效率,尽可能一次性读取存满缓冲区。

2. 程序员调用读取方法,从缓冲区中获取数据,当获取完数据后,缓冲区再次从文件中尽可能一次性读取数据。

常用构造器:BufferedReader(Reader reader)

常用方法:该类提供了一个可以便于读取一行字符串的方法。

String readLine(): 读取一行数据,只读取到换行符,但是返回的数据不含换行符。

2) PrintWriter:缓冲字符输出流,高级流。

1. 一般使用PrintWriter这个子类,不使用BufferedWriter。

2. PrintWriter是具有自动行刷新的缓冲字符输出流,其提供了比较丰富的构造方法,通常比BufferedWriter更实用。

3. 内部也是维护了一个字符缓冲区。写的时候,先往字符缓冲区中写,当缓冲区满了,会一次性写出到文件中。不过,当使用了自动行刷新功能,每写一行,然后在行末添加个换行符,然后强制写出去。

常用构造器:

1. PrintWriter(File file)

2. PrintWriter(String filename)

3. PrintWriter(OutputStream os)

4. PrintWriter(OutputWriter os,boolean autoFlush)

5. PrintWriter(Writer writer)

6. PrintWriter(Writer writer,boolean autoFlush)

其中参数为OutputStream和Writer的构造方法提供了一个可以传入boolean的值参数,该参数用于表示PrintWriter是否具有自动行刷新,true表示有自动行刷新功能。

常用方法:除了writer方法,还提供了丰富的print和println的各种重载方法。其中println方法在于输出目标数据后自动输出一个系统支持的换行符。若该流设置了自动行刷新,那么每当通过println方法写出的内容都会被实际写出,而不是进行缓存。

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)
打印一个字符串,然后终止行。
public static void main(String[] args) {
    try(PrintWriter pw = new PrintWriter(
        new OutputStreamWriter(
            new FileOutputStream("./test07/char.txt"), "GBK"),true)){
            //写出一个字符数组
            char[] charArray = "你好中国".toCharArray();
            pw.write(charArray);
            //调用print方法,写出去 "床前明月光"
            pw.print("床前明月光");//print  不带ln的方法,是没有自动行刷新的效果
            //调用println的方法,写出去"疑是地上霜"
            //当构造器中指定了行刷新功能,也就是设置成true,此时ln的方法才会在行末添加换行符,
            并强制从缓存区中写出来。
            pw.println("疑是地上霜");
            pw.println("举头望明月");
    }catch(Exception e){
            e.printStackTrace();
    }
}

2.8 文件字符流

1)FileWriter :文件字符输出流,低级流。

相当于OutputStreamWriter和FileOutputStream合起来的功能,但是不能指定字符集。

常用构造器:

1. FileWriter(File file)
2. FileWriter(File file,boolean append)
3. FileWriter(String filepath)
4. FileWriter(String filepath,boolean append)

常用方法:继承了OutputStreamWriter等父类的方法,就是转换流的方法,内部也维护着一个缓存区,需要手动调用flush方法进行刷新。

public static void main(String[] args) {
    try(FileWriter fw = new FileWriter(new File("test07/char.txt"),true)){
        //将"中国好男儿"写出去
        fw.write("中国好男儿");
        fw.write("华夏好儿女");
        //append方法:追加到文字的后面。
        fw.append("北京上海");
    }catch(IOException e){
        e.printStackTrace();
    }
}

2)FileReader:文件字符输入流,低级流。

相当于InputStreamReader和FileInputStream合起来的功能,但是不能指定字符集。

常用构造器:

1. FileReader(File file)

2. FileReader(String filepath)

常用方法:继承了InputStreamWriter等父类的方法,就是转换流的方法,内部也维护着一个缓存区,可以提高读取效率。

public static void main(String[] args) {
    try(FileReader fr = new FileReader("test07/char.txt")){
        int ch = fr.read();
        System.out.println((char)ch);
        char[] chs = new char[100];
        int len = -1;
        while((len =fr.read(chs))!=-1){
            String str = new String(chs,0,len);
            System.out.print(str);
        }

    }catch(IOException e){
        e.printStackTrace();
    }
}

2.9 其他流

System:系统类,里面封装了一些本地方法和静态属性。

静态属性:

     - PrintStream out:标准输出流 , 默认的数据输出目的地是控制台console。

     - PrintStream err:标准错误输出流 , 默认的数据输出目的地是控制台console。

     - InputStream in:标准输入流 , 默认数据源是控制台console。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值