IO流-File,字节流,缓冲流

1.1 IO概述

回想之前写过的程序,数据都是在内存中,一旦程序运行结束,这些数据都没有了,等下次再想使用这些数据,可是已经没有了。那怎么办呢?能不能把运算完的数据都保存下来,下次程序启动的时候,再把这些数据读出来继续使用呢?其实要把数据持久化存储,就需要把内存中的数据存储到内存以外的其他持久化设备(硬盘、光盘、U盘等 ROM)上。

当需要把内存中的数据存储到持久化设备上这个动作称为输出(写)Output操作。

当把持久设备上的数据读取到内存中的这个动作称为输入(读)Input操作。

因此我们把这种输入和输出动作称为IO操作。

1.2 IO流流向分类

按照流向分输入流与输出流,每个IO流对象均要绑定一个IO资源

分类关系如下:

字节输入流 InputStream的抽象类

  FileInputStream 操作文件的字节输入流

字节输出流 OutputStream的抽象类

  FileOutputStream 操作文件的字节输出流

按照传输方式:分为字节流和字符流

    字符流  按照字符的方式读写 

    字节流  按照字节的方式读写

 

1.3 一切均为字节

 

在数据传输过程中,一切数据(文本、图像、声音等)最终存储的均为一个个字节,即二进制数字。所以数据传输过程中使用二进制数据可以完成任意数据的传递。

第1章 File

在我们操作系统中,数据都保存在文件中,而文件存放相应的文件夹中。那么Java中是如何描述这些的呢?

1.1 File类的出现

打开API,搜索File类。阅读其描述:File文件和目录路径名的抽象表示形式。即,Java中把文件或者目录(文件夹)都封装成File对象。也就是说如果我们要去操作硬盘上的文件,或者文件夹只要找到File这个类即可。那么我们就要研究研究File这个类中都有那些功能可以操作文件或者文件夹呢?

1.2 File类的构造方法

通过构造方法创建File对象,我们进行代码演示:

    public static void main(String[] args) {
        //方法1:
        String filePath = "G:\FileTest\file1.txt";
        File file = new File(filePath);
        System.out.println(file);
        // 方法2:将parent封装成file对象。
        File dir = new File("G:\FileTest");
        File file2 = new File(dir, "hello.java");
        //方法3:
        File file3 = new File("G:\FileTest", "hello.java");
    }

1.3 File类的方法

创建完了File对象之后,那么File类中都有如下常用方法

public static void main(String[] args) throws IOException {
        String dirPath = "g:\TestFiles";
        //String dirPath = "g:\TestFile";//注意java创建文件夹和文件名不要包含file,可能存在bug,创建不成功
        String filePath = "G:\TestFiles\file1.txt";
        File dir = new File("g:\TestFiles");
        boolean b1=dir.mkdir();//创建一个空的新文件夹(前提是该文件不存在)
        File file = new File(filePath);
        boolean b2=file.createNewFile();//创建一个空的新文件(前提是该文件不存在)注意,要保证该路径下所有的文件夹都已经存在或者在此之前已经创建
        // 创建文件,如果文件不存在,创建 true 如果文件存在,则不创建 false。 如果路径错误,IOException。
        String absPath=file.getAbsolutePath();//获取文件全路径
        String path=file.getPath();//获取我们构造文件的时候的路径(也就是File构造方法里面我们传递的字符串)
        String name=file.getName();//获取文件名
        String parent=file.getParent();//获取父文件夹文件名
        boolean isfile=file.isFile();//判断是不是文件(如果文件不存在返回false)
        boolean isdir=file.isDirectory();//判断是不是文件夹(如果文件夹不存在返回false)
        boolean canread=file.canRead();//判断是否可读
        boolean canwrite=file.canWrite();//判断是否可写
        long lenth=file.length();//返回文件的长度
        boolean b3=file.exists();//判断文件是否存在
        boolean b4 = file.delete();//删除文件操作--删除成功返回true,文件不存在返回false-----注意:不去回收站。慎用------
        //删除目录时,如果目录中有内容,无法直接删除返回false。只有将目录中的内容都删除后,保证该目录为空。这时这个目录才可以删除。
        boolean b5 = dir.delete();
        System.out.println("b1="+b1);
        System.out.println(absPath);
        System.out.println(path);
        System.out.println(name);
        System.out.println(parent);
        System.out.println(isfile);
        System.out.println(isdir);
        System.out.println(canread);
        System.out.println(canwrite);
        System.out.println(lenth);
        System.out.println(b3);
        System.out.println(b4);
        System.out.println(b5);
//    1.1 listFiles()list()方法介绍
     File dir0=new File("g://files");
        File dir1=new File("g://files//dir1");
        File dir2=new File("g://files//dir2");
        File f1=new File("g://files//dir2//test1.txt");
        File f2=new File("g://files//dir2//test2.txt");
        File f3=new File("g://files//dir1//test3.txt");
        if(!dir1.exists()) {
            dir1.mkdirs();
        }
        if(!dir2.exists()) {
            dir2.mkdirs();
        }
        if(!f1.exists()) {
            f1.createNewFile();
        }
        if(!f2.exists()) {
            f2.createNewFile();
        }
        if(!f3.exists()) {
            f3.createNewFile();
        }
        String arg1[]=dir0.list();//获取的是目录下的当前的文件以及文件夹的名称。
        for(String s: arg1) {
            System.out.println(s);
        }
        File f[]=dir0.listFiles();//获取目录下当前文件以及文件对象,只要拿到了文件对象,那么就可以获取其中想要的信息
        for(File ff:f) {
            System.err.println(ff);
        }

    }

第2章 字节流

既然一切数据都是字节,那么字节流如何操作呢,那么接下来我们进行字节流的学习.

2.1 字节输出流OutputStream

OutputStream此抽象类是表示输出字节流的所有类的超类。操作的数据都是字节,定义了输出字节流的基本共性功能方法。

输出流中定义都是写write方法;

  2.1.1 FileOutputStream

OutputStream有很多子类,其中子类FileOutputStream可用来写入数据到文件。

FileOutputStream,即文件输出流是用于将数据写入 File的输出流。

 

构造方法:

代码演示:

public static void main(String[] args) throws IOException {
        // TODO Auto-generated method stub
        //需求:将数据写入到文件中。
        //创建存储数据的文件。
        File f1=new File("g://files//dir2//test1.txt");
        File f2=new File("g://files//dir2//test2.txt");
        File f3=new File("g://files//dir2//test3.txt");
        //创建一个用于操作文件的字节输出流对象。一创建就必须明确数据存储目的地。
        //输出流目的是文件,会自动创建。如果文件存在,则覆盖。
        FileOutputStream fs1=new FileOutputStream(f1);
        FileOutputStream fs2=new FileOutputStream(f2,true);//第二个参数true标识不是覆盖,而是续写
        FileOutputStream fs3=new FileOutputStream(f3);
        byte b[]="123我很开心".getBytes();
        //调用父类的write方法
        fs1.write(b);//将b全部写出
        fs2.write(b,2,4);//将b里面索引在2-4的内容写出(3我很)
        fs3.write(10);//这个方法有待研究
        //刷新此输出流并强制写出所有缓冲的输出字节
        fs1.flush();
        //关闭流资源
        fs1.close();
        
        fs2.flush();
        fs2.close();
        fs3.flush();
        fs3.close();
    }

  2.2.1 FileInputStream

InputStream有很多子类,其中子类FileInputStream可用来读取文件内容。

FileInputStream 从文件系统中的某个文件中获得输入字节。

构造方法:

 

  2.2.2 FileInputStream类读取数据read方法(只读纯英文,有空介绍一下读中文问题)

在读取文件中的数据时,调用read方法,实现从文件中读取数据

代码演示:

public static void main(String[] args) throws Exception {
        File f1=new File("g://files//dir2//test1.txt");
        FileInputStream fis1=new FileInputStream(f1);
        //读取数据。使用 read();一次读一个字节。
        int n;
        while((n=fis1.read())!=-1) {
            System.out.println((char)n);
        }
        fis1.close();
    }

  2.2.3 读取数据read(byte[])方法

在读取文件中的数据时,调用read方法,每次只能读取一个,太麻烦了,于是我们可以定义数组作为临时的存储容器,这时可以调用重载的read方法,一次可以读取多个字符。

public static void main(String[] args) throws Exception {
        File f1=new File("g://files//dir2//test1.txt");
        FileInputStream fis1=new FileInputStream(f1);
        /*
         * 演示第二个读取方法, read(byte[]);
         */
        int n=0;
        byte b[]=new byte[1024];//长度可以定义成1024的整数倍。
        while((n=fis1.read(b))!=-1) {
            System.out.println(new String(b,0,n));
        }
        fis1.close();
    }

  2.3.1 复制文件

原理;读取一个已有的数据,并将这些读到的数据写入到另一个文件中。

public class CopyFileTest {
    public static void main(String[] args) throws IOException {
        //1,明确源和目的。
        File srcFile = new File("c:\YesDir	est.JPG");
        File destFile = new File("copyTest.JPG");
        
        //2,明确字节流 输入流和源相关联,输出流和目的关联。
        FileInputStream fis = new FileInputStream(srcFile);
        FileOutputStream fos = new FileOutputStream(destFile);
        
        //3, 使用输入流的读取方法读取字节,并将字节写入到目的中。
        int ch = 0;
        while((ch=fis.read())!=-1){
            fos.write(ch);
        }
        //4,关闭资源。
        fos.close();
        fis.close();
    }
}

上述代码输入流和输出流之间是通过ch这个变量进行数据交换的。

上述复制文件有个问题,每次都从源文件读取一个,然后在写到指定文件,接着再读取一个字符,然后再写一个,一直这样下去。效率极低。

  2.3.2临时数组方式复制文件

上述代码复制文件效率太低了,并且频繁的从文件读数据,和写数据,能不能一次多把文件中多个数据都读进内容中,然后在一次写出去,这样的速度一定会比前面代码速度快。

public class CopyFileByBufferTest {
    public static void main(String[] args) throws IOException {
        File srcFile = new File("c:\YesDir	est.JPG");
        File destFile = new File("copyTest.JPG");
        // 明确字节流 输入流和源相关联,输出流和目的关联。
        FileInputStream fis = new FileInputStream(srcFile);
        FileOutputStream fos = new FileOutputStream(destFile);
        //定义一个缓冲区。
        byte[] buf = new byte[1024];
        int len = 0;
        while ((len = fis.read(buf)) != -1) {
            fos.write(buf, 0, len);// 将数组中的指定长度的数据写入到输出流中。
        }
        // 关闭资源。
        fos.close();
        fis.close();
    }
}

第3章 字符

经过前面的学习,我们基本掌握的文件的读写操作,在操作过程中字节流可以操作所有数据,可是当我们操作的文件中有中文字符,并且需要对中文字符做出处理时怎么办呢?

IO开发过程中,我们传输最频繁的数据为字符,而以字节方式传输字符需要每次将字符串转换成字节再处理,而且也丧失了程序员对数据内容的判断(因为程序员只认识字符,不认识字节)。所以,为了让程序员方便对字符进行操作,Java提供了专门以字符作为操作单位的类——字符流,其底层仍然为字节流。

显然,字符流只能操作字符,无法操作其他数据,如声音、视频等。

代码示例:

    /**
     * 字符流
     * @throws IOException
     */
    public static void zifuliu() throws IOException {
        FileReader fr=new FileReader("g://files//dir2//test1.txt");
        BufferedReader br=new BufferedReader(fr);
        FileWriter fw=new FileWriter("g://files//dir2//test4.txt");
        BufferedWriter bw=new BufferedWriter(fw);
        String content="";
        while((content=br.readLine())!=null) {
            bw.write(content+"
");
        }
        fw.flush();
        fr.close();
        bw.close();
        br.close();
    }
    

第4章 缓冲流

在我们学习字节流与字符流的时候,大家都进行过读取文件中数据的操作,读取数据量大的文件时,读取的速度会很慢,很影响我们程序的效率,那么,我想提高速度,怎么办?

Java中提高了一套缓冲流,它的存在,可提高IO流的读写速度

缓冲流,根据流的分类分为字节缓冲流与字符缓冲流。

4.1 字节缓冲流

字节缓冲流根据流的方向,共有2

写入数据到流中,字节缓冲输出流 BufferedOutputStream

读取流中的数据,字节缓冲输入流 BufferedInputStream

它们的内部都包含了一个缓冲区,通过缓冲区读写,就可以提高了IO流的读写速度

  4.1.1字节缓冲输出流BufferedOutputStream

通过字节缓冲流,进行文件的读写操作 写数据到文件的操作  

l 构造方法

public BufferedOutputStream(OutputStream out)创建一个新的缓冲输出流,以将数据写入指定的底层输出流。 

public class BufferedOutputStreamDemo01 {
    public static void main(String[] args) throws IOException {
        
        //写数据到文件的方法
        write();
    }

    /*
     * 写数据到文件的方法
     * 1,创建流
     * 2,写数据
     * 3,关闭流
     */
    private static void write() throws IOException {
        //创建基本的字节输出流
        FileOutputStream fileOut = new FileOutputStream("abc.txt");
        //使用高效的流,把基本的流进行封装,实现速度的提升
        BufferedOutputStream out = new BufferedOutputStream(fileOut);
        //2,写数据
        out.write("hello".getBytes());
        //3,关闭流
        out.close();
    }
}

  4.1.2 字节缓冲输入流 BufferedInputStream

刚刚我们学习了输出流实现了向文件中写数据的操作,那么,现在我们完成读取文件中数据的操作

l 构造方法

public BufferedInputStream(InputStream in)

/*
     * 从文件中读取数据
     * 1,创建缓冲流对象
     * 2,读数据,打印
     * 3,关闭
     */
    private static void read() throws IOException {
        //1,创建缓冲流对象
        FileInputStream fileIn = new FileInputStream("abc.txt");
        //把基本的流包装成高效的流
        BufferedInputStream in = new BufferedInputStream(fileIn);
        //2,读数据
        int ch = -1;
        while ( (ch = in.read()) != -1 ) {
            //打印
            System.out.print((char)ch);
        }
        //3,关闭
        in.close();
    }

         4.3.3 复制单级文件夹

/* 
 * 数据源:e:\demo
 * 目的地:e:\test
 * 
 * 分析:
 *         A:封装目录
 *         B:获取该目录下的所有文本的File数组
 *         C:遍历该File数组,得到每一个File对象
 *         D:把该File进行复制
 */
public class CopyFolderDemo {
    public static void main(String[] args) throws IOException {
        // 封装目录
        File srcFolder = new File("e:\demo");
        // 封装目的地
        File destFolder = new File("e:\test");
        // 如果目的地文件夹不存在,就创建
        if (!destFolder.exists()) {
            destFolder.mkdir();
        }

        // 获取该目录下的所有文本的File数组
        File[] fileArray = srcFolder.listFiles();

        // 遍历该File数组,得到每一个File对象
        for (File file : fileArray) {
            // System.out.println(file);
            // 数据源:e:\demo\e.mp3
            // 目的地:e:\test\e.mp3
            String name = file.getName(); // e.mp3
            File newFile = new File(destFolder, name); // e:\test\e.mp3

            copyFile(file, newFile);
        }
    }

    private static void copyFile(File file, File newFile) throws IOException {
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
                file));
        BufferedOutputStream bos = new BufferedOutputStream(
                new FileOutputStream(newFile));

        byte[] bys = new byte[1024];
        int len = 0;
        while ((len = bis.read(bys)) != -1) {
            bos.write(bys, 0, len);
        }

        bos.close();
        bis.close();
    }
}

第5章 转换

5.1 OutputStreamWriter类

查阅OutputStreamWriterAPI介绍,OutputStreamWriter 字符流通向字节流的桥梁:可使用指定的字符编码表,将要写入流中的字符编码成字节。它的作用的就是,将字符串按照指定的编码表转成字节,再使用字节流将这些字节写出去。

    /**
     * 转换流
     * @throws Exception 
     */
    public static void zhuanhuanliu() throws Exception {
        FileOutputStream fs=new FileOutputStream("g://files//dir2//test1.txt");
        //创建可以把字符转成字节的转换流对象,并指定编码
        OutputStreamWriter osw=new OutputStreamWriter(fs,"utf-8");
        //调用转换流,把文字写出去,其实是写到转换流的高效区中
        osw.write("我是字符流转换成字节流然后写进的");//写入高效区。
        osw.flush();
        osw.close();
        fs.close();
    }

OutputStreamWriter流对象,它到底如何把字符转成字节输出的呢?

其实在OutputStreamWriter流中维护自己的高效区,当我们调用OutputStreamWriter对象的write方法时,会拿着字符到指定的码表中进行查询,把查到的字符编码值转成字节数存放到OutputStreamWriter高效区中。然后再调用刷新功能,或者关闭流,或者高效区存满后会把高效区中的字节数据使用字节流写到指定的文件中。

5.2 InputStreamReader

查阅InputStreamReaderAPI介绍,InputStreamReader 字节流通向字符流的桥梁:它使用指定的字符编码表读取字节并将其解码为字符。它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集。

    /**
     * 转换流2.
     * @throws IOException 
     */
    public static void zhuanhuanliu2() throws IOException {
        FileInputStream fs=new FileInputStream("g://files//dir2//test1.txt");
        /*    下面本注释内的代码在没有使用转换流的情况下虽然可以读取中文,但是打印出来是乱码的
         *  byte b[]=new byte[1024];
            int n=0;
            while((n=fs.read(b))!=-1) {
            System.out.println(new String(b,0,n));
        }
        */
        //下面通过转换流读取进来的汉字是正确的
        //InputStreamReader isr=new InputStreamReader(fs);//这样创建对象,会用本地默认码表读取,将会发生错误解码的错误
        InputStreamReader isr=new InputStreamReader(fs,"utf-8");
        int n=0;
        while((n=isr.read())!=-1) {
            System.out.println((char)n);
        }
        isr.close();
        fs.close();
    }

5.3 转换流和子类区别

发现有如下继承关系:

Writer 字符输出流

  |- OutputStreamWriter   转换流(字符流—>字节流)(属于字符输出流, 可以指定字符编码表,用来写入数据到文件)

    |--FileWriter 操作文件中字符输出流,采用默认的字符编码表

Reader 字符输入流

  |- InputStreamReader: 转换流(字节流à字符流)(属于字符输入流,可以指定字符编码表,用来从文件中读数据)

    |--FileReader操作文件中字符输入流,采用默认的字符编码表

父类和子类的功能有什么区别呢?

OutputStreamWriterInputStreamReader是字符和字节的桥梁:也可以称之为字符转换流。字符转换流原理:字节流+编码表

FileWriterFileReader:作为子类,仅作为操作字符文件的便捷类存在。当操作的字符文件,使用的是默认编码表时可以不用父类,而直接用子类就完成操作了,简化了代码。

InputStreamReader isr = new InputStreamReader(new FileInputStream("a.txt"));//默认字符集。

InputStreamReader isr = new InputStreamReader(new FileInputStream("a.txt"),"GBK");//指定GBK字符集。

FileReader fr = new FileReader("a.txt");

这三句代码的功能是一样的,其中第三句最为便捷。

注意:一旦要指定其他编码时,绝对不能用子类,必须使用字符转换流。什么时候用子类呢?

条件:

1、操作的是文件。2、使用默认编码。

第6章 序列化流与反序列化流

用于从流中读取对象的操作流 ObjectInputStream   称为 反序列化流

用于向流中写入对象的操作流 ObjectOutputStream   称为 序列化流

l 特点:用于操作对象。可以将对象写入到文件中,也可以从文件中读取对象。

6.1 对象序列化流ObjectOutputStream

ObjectOutputStream 将 Java 对象的基本数据类型和图形写入 OutputStream。可以使用 ObjectInputStream 读取(重构)对象。通过在流中使用文件可以实现对象的持久存储。

注意:只能将支持 java.io.Serializable 接口的对象写入流中

代码示例:

public class ObjectStreamDemo {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        /*
         * 将一个对象存储到持久化(硬盘)的设备上。
         */
        writeObj();//对象的序列化。
    }
    public static void writeObj() throws IOException {
        //1,明确存储对象的文件。
        FileOutputStream fos = new FileOutputStream("tempfile\obj.object");
        //2,给操作文件对象加入写入对象功能。
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        //3,调用了写入对象的方法。
        oos.writeObject(new Person("wangcai",20));
        //关闭资源。
        oos.close();
    }
}

person类代码:

public class Person implements Serializable {
    private String name;
    private int age;
    public Person() {
        super();
    }
    public Person(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + "]";
    }
}

6.2 对象反序列化流ObjectInputStream

ObjectInputStream 对以前使用 ObjectOutputStream 写入的基本数据和对象进行反序列化。支持 java.io.Serializable接口的对象才能从流读取。

 

代码示例:

public class ObjectStreamDemo {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        readObj();//对象的反序列化。
    }
    public static void readObj() throws IOException, ClassNotFoundException {
        
        //1,定义流对象关联存储了对象文件。
        FileInputStream fis = new FileInputStream("tempfile\obj.object");
        
        //2,建立用于读取对象的功能对象。
        ObjectInputStream ois = new ObjectInputStream(fis);
        
        Person obj = (Person)ois.readObject();
        
        System.out.println(obj.toString());
        
    }
}

6.3 序列化接口

当一个对象要能被序列化,这个对象所属的类必须实现Serializable接口。否则会发生异常NotSerializableException异常。

同时当反序列化对象时,如果对象所属的class文件在序列化之后进行的修改,那么进行反序列化也会发生异常InvalidClassException。发生这个异常的原因如下:

  l 该类的序列版本号与从流中读取的类描述符的版本号不匹配

  l 该类包含未知数据类型

  l 该类没有可访问的无参数构造方法

Serializable标记接口。该接口给需要序列化的类,提供了一个序列版本号。serialVersionUID. 该版本号的目的在于验证序列化的对象和对应类是否版本匹配。

l 代码修改如下,修改后再次写入对象,读取对象测试

public class Person implements Serializable {
    //给类显示声明一个序列版本号。
    private static final long serialVersionUID = 1L;
    private String name;
    private int age;
    public Person() {
        super();
        
    }
    public Person(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + "]";
    }
}

6.4 瞬态关键字transient

当一个类的对象需要被序列化时,某些属性不需要被序列化,这时不需要序列化的属性可以使用关键字transient修饰。只要被transient修饰了,序列化时这个属性就不会被序列化了。

同时静态修饰也不会被序列化,因为序列化是把对象数据进行持久化存储,而静态的属于类加载时的数据,不会被序列化。

l 代码修改如下,修改后再次写入对象,读取对象测试

public class Person implements Serializable {
    /*
     * 给类显示声明一个序列版本号。
     */
    private static final long serialVersionUID = 1L;
    private static String name;
    private transient/*瞬态*/ int age;
    
    public Person() {
        super();
        
    }
    
    public Person(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + "]";
    }
}

第7章 打印流

7.1 打印流的概述

打印流添加输出数据的功能,使它们能够方便地打印各种数据值表示形式.

打印流根据流的分类:

  l 字节打印流 PrintStream

  l 字符打印流 PrintWriter

l 方法:

  void print(String str): 输出任意类型的数据,

  void println(String str): 输出任意类型的数据,自动写入换行操作

代码演示

/**
     * 打印流
     * 
     * @throws Exception
     */
    public static void dayinliu() throws Exception {
        /* 
         * 需求:把指定的数据,写入到printFile.txt文件中
         * 分析:
         *     1,创建流
         *     2,写数据
         *     3,关闭流
         */
        //1, 创建流
        // PrintWriter out = new PrintWriter(new FileWriter("printFile.txt"));
        PrintWriter out = new PrintWriter("g://files//dir2//test5.txt");
        // 2,写数据
        for (int i = 0; i < 5; i++) {
            out.println("helloWorld");
        }
        // 3,关闭流
     out.flush
out.close(); }

第8章 Properties类

8.1 Properties类介绍

Properties 类表示了一个持久的属性集。Properties 可保存在流中或从流中加载。属性列表中每个键及其对应值都是一个字符串。

特点:

1Hashtable的子类,map集合中的方法都可以用。

2、该集合没有泛型。键值都是字符串。

3、它是一个可以持久化的属性集。键值可以存储到集合中,也可以存储到持久化的设备(硬盘、U盘、光盘)上。键值的来源也可以是持久化的设备。

4、有和流技术相结合的方法。

l load(InputStream)  把指定流所对应的文件中的数据,读取出来,保存到Propertie集合中

l load(Reader)  

l store(OutputStream,commonts)把集合中的数据,保存到指定的流所对应的文件中,参数commonts代表对描述信息

l Store(Writer,comments);

5.成员方法:

 * public Object setProperty(String key, String value)调用 Hashtable 的方法 put

 * public Set<String> stringPropertyNames()返回此属性列表中的键集,

 * public String getProperty(String key)用指定的键在此属性列表中搜索属性

 

代码演示:

/*
 * 
 * Properties集合,它是唯一一个能与IO流交互的集合
 * 
 * 需求:向Properties集合中添加元素,并遍历
 * 
 * 方法:
 * public Object setProperty(String key, String value)调用 Hashtable 的方法 put。
 * public Set<String> stringPropertyNames()返回此属性列表中的键集,
 * public String getProperty(String key)用指定的键在此属性列表中搜索属性
 */
public class PropertiesDemo01 {
    public static void main(String[] args) {
        //创建集合对象
        Properties prop = new Properties();
        //添加元素到集合
        //prop.put(key, value);
        prop.setProperty("周迅", "张学友");
        prop.setProperty("李小璐", "贾乃亮");
        prop.setProperty("杨幂", "刘恺威");
        
        //System.out.println(prop);//测试的使用
        //遍历集合
        Set<String> keys = prop.stringPropertyNames();
        for (String key : keys) {
            //通过键 找值
            //prop.get(key)
            String value = prop.getProperty(key);
            System.out.println(key+"==" +value);
        }
    }
}

8.2 将集合中内容存储到文件

需求:使用Properties集合,完成把集合内容存储到IO流所对应文件中的操作

分析:

1创建Properties集合

2,添加元素到集合

3,创建流

4,把集合中的数据存储到流所对应的文件中

stroe(Writer,comments)

store(OutputStream,commonts)

把集合中的数据,保存到指定的流所对应的文件中,参数commonts代表对描述信息

5,关闭流

 

代码演示:

public class PropertiesDemo02 {
    public static void main(String[] args) throws IOException {
        //1,创建Properties集合
        Properties prop = new Properties();
        //2,添加元素到集合
        prop.setProperty("周迅", "张学友");
        prop.setProperty("李小璐", "贾乃亮");
        prop.setProperty("杨幂", "刘恺威");
        
        //3,创建流
        FileWriter out = new FileWriter("prop.properties");
        //4,把集合中的数据存储到流所对应的文件中
        prop.store(out, "save data");
        //5,关闭流
        out.close();
    }
}

8.3 读取文件中的数据,并保存到集合

需求:从属性集文件prop.properties 中取出数据,保存到集合中

分析:

1,创建集合

2,创建流对象

3,把流所对应文件中的数据 读取到集合中

load(InputStream)  把指定流所对应的文件中的数据,读取出来,保存到Propertie集合中

load(Reader)  

4,关闭流

5,显示集合中的数据

代码演示:

public class PropertiesDemo03 {
    public static void main(String[] args) throws IOException {
        //1,创建集合
        Properties prop = new Properties();
        //2,创建流对象
        FileInputStream in = new FileInputStream("prop.properties");
//FileReader in = new FileReader("prop.properties");
        //3,把流所对应文件中的数据 读取到集合中
        prop.load(in);
        //4,关闭流
        in.close();
        //5,显示集合中的数据
        System.out.println(prop);
        
    }
}
原文地址:https://www.cnblogs.com/luzhanshi/p/10730972.html