文件类以及IO输入输出

文件类以及IO输入输出

我们在java使用中必不可少与文件交互,由此IO流显得格外重要

绝对路径和相对路径

绝对路径:完整的路径名,不需要任何其他信息就可以定位它所表示的文件

相对路径:必须使用取自其他路径名的信息进行解释

File类

File:它是文件和目录路径名的抽象表示

  • 文件和目录是可以通过File封装成对象的
  • 对于File而言,封装的并不是真正的文件,仅仅是一个路径名而已,它可以是存在的,可以是不存在的

File类构造方法

方法如下:

方法名 说明
File(String pathname) 通过将给定的路径字符串转换为抽象路径名来创建新的File实例
File(String parent,String child) 从父路径名字符串和子路径名字符串创建新的File实例
File(File parent,String child) 从父抽象路径名和子路径名字符串创建新的File实例

下面给出代码实例:

import java.io.File;

public class Demo1 {
    public static void main(String[] args) {
        //下方示例存在D:\Test,但不存在D:\Test\java.txt;
        //但仍旧可以执行,因为File采用的是抽象路径,不需要文件地址存在

        //第一种构造:直接写入地址
        File f1 = new File("D:\\Test\\java.txt");

        System.out.println(f1);

        //第二种构造,分开写父类和子类地址
        File f2 = new File("D:\\Test","java.txt");

        System.out.println(f2);

        //第三种构造,分开写父类和子类地址,但父类是File类型,子类是String类型
        File f3 = new File("D:\\Test");
        File f4 = new File(f3,"java.txt");

        System.out.println(f4);
    }
}

File类创建功能

方法如下:

方法名 说明
public boolean createNewFile() 当具有该名称的文件不存在时,创建一个由该抽象路径名命名的新空文件
public boolean mkdir() 创建由此抽象路径名命名的目录
public boolean mkdirs() 创建由此抽象路径名命名的目录,包括任何必须但不存在的目录

下面给出示例代码:

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

public class Demo2 {
    public static void main(String[] args) throws IOException {
        //f1:创建文件createNewFile()需要抛出异常
        File f1 = new File("D:\\Test\\java.txt");
        System.out.println(f1.createNewFile());

        //f2:创建目录mkdir()创建单层目录
        File f2 = new File("D:\\Test\\javaSE");
        System.out.println(f2.mkdir());

        //f3:创建目录mkdirs()创建多层目录(注意这里使用mkdir()会报错,因为没有上一级目录,所以无法在上一级创建下一级)
        File f3 = new File("D:\\Test\\javaWEB\\HTML");
        System.out.println(f3.mkdirs());

        //以上输出,如果创建成功为true;但若已有该文件或创造失败输出false
    }
}

注意:window同一页面下不允许出现目录或文件名字一样的情况

File类删除功能

方法如下:

方法名 说明
public boolean delete() 删除由此抽象路径名表示的文件和目录

下面给出代码示例:

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

public class Demo3 {
    public static void main(String[] args) throws IOException {
        //在当前目录下创建文件java
        File f1 = new File("java.txt");
        f1.createNewFile();

        //删除文件java
        f1.delete();

        //在当前目录下创建目录javaSE
        File f2 = new File("javaSE");
        f2.mkdir();

        //删除目录javaSE
        f2.delete();

        //创建目录javaWEB以及内部文件HTML.txt
        File f3 = new File("javaWEB");
        f3.mkdir();
        File f4 = new File("javaWEB\\HTML.txt");
        f4.createNewFile();

        //删除目录javaWEB,注意删除目录前必须删除目录内所有元素
        f4.delete();
        f3.delete();
    }
}

注意:需要目录内容全部删除完毕,才可以删除该目录

File类判断和获取功能

方法如下:

方法名 说明
public boolean isDirectory() 测试此抽象路径名表示的File是否为目录
public boolean isFile() 测试此抽象路径名表示的File是否为文件
public boolean exists() 测试此抽象路径名表示的File是否存在
public String getAbsolutePath() 返回此抽象路径名的绝对路径名字符串
public String getPath() 将此抽象路径名转换为路径名字符串
public String getName() 返回此抽象路径名表示的文件或目录的名称
public String[] list() 返回此抽象路径名表示的目录中的文件和目录的名称字符串数组
public File[] listFiles() 返回此抽象路径名表示的目录中的文件和目录的File对象数组

下面给出示例代码:

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

public class Demo4 {
    public static void main(String[] args) throws IOException {
        //首先创建一个文件来实施下面的判断:
        File f1 = new File("IO流\\Demo1\\java.text");

        //定义之前定义的Test目录实施下面的判断
        File f2 = new File("D:\\Test");

        //判断1:是否为目录
        System.out.println(f1.isDirectory());

        //判断2:是否为文件
        System.out.println(f1.isFile());

        //判断3:是否存在
        System.out.println(f1.exists());

        //获取1:返回绝对路径
        System.out.println(f1.getAbsolutePath());

        //获取2:返回路径名称
        System.out.println(f1.getPath());

        //获取3:返回文件或目录名
        System.out.println(f1.getName());

        //获取4:获取当前目录下所有文件和目录名称
        String[] strArrary = f2.list();
        for(String s : strArrary){
            System.out.println(s);
        }

        //获取5:获取当前目录下所有文件和目录File对象数组
        File[] files = f2.listFiles();
        for(File file : files){
            System.out.println(file);
        }

        //获取5提升:获得当前目录下所有文件对象
        for(File file : files){
            if(file.isFile()){
                System.out.println(file);
            }
        }
    }
}

案例:遍历目录

需求:给定一个路径,请通过递归完成遍历该目录下所有内容,并把文件的绝对路径输出在控制台

import java.io.File;

public class Demo5 {
    public static void main(String[] args) {
        //定义之前定义的Test目录
        File f = new File("D:\\Test");

        //调用方法:
        getAllFile(f);
    }

    //定义方法使得不断遍历
    public static void getAllFile(File f){
        //提取出来各文件和目录
        File[] files = f.listFiles();
        //非空情况下运行
        if(files != null){
            for(File file : files){
                //如果是文件就输出;如果是目录就继续遍历
                if(file.isFile()){
                    System.out.println(file);
                }else {
                    getAllFile(file);
                }
            }
        }
    }
}

IO流

IO流概述:

  • IO:输入/输出(Input/Output)
  • 流:是一种抽象概念,是对数据传输的总称。也就是说数据在设备间的传输称为流,流的本质是数据传输
  • IO流是用来处理设备间数据传输问题的

IO流分类

  • 按数据的流向:

​ 输入流:读数据

​ 输出流:写数据

  • 按数据类型来分类:

​ 字节流

​ 字符流

一般按照数据类型来分类:

当数据通过Windows的记事本打开,可以读懂即为字节流,读不懂为字符流(可以默认使用字符流)

字节流分界线

下面介绍均为字节流

基类介绍

字节流抽象基类:

  • InputStream:这个抽象类是表示字节输入流的所有类的超类
  • OutputStream:这个抽象类是表示字节输出流的所有类的超类
  • 子类名特点:子类都是以其父类名作为子类名结尾

字节流写数据

FileOutputStream:文件输出流用于将数据写入File

FileOutputStream(String name):创建文件输出流以指定的名称写入文件
/*
* 上面语句做了三件事:
* 1.调用系统功能创建了文件
* 2.创建了字节输出流对象
* 3.让字节输出流对象指向创好的文件
*/

下面给出代码示例:

import java.io.FileOutputStream;
import java.io.IOException;

public class Demo1 {
    public static void main(String[] args) throws IOException {
        //创建字符输出流对象(注意抛出异常)
        FileOutputStream fos =new FileOutputStream("Demo2\\fos.txt");

        //字符写入:(写入的是ASCII代码转化前的数字)
        fos.write(97);

        //最后需要关闭使其释放内存
        fos.close();
    }
}

字节流写数据的三种方法

方法如下:

方法名 说明
void write(int b) 将指定的字节写入此文件输出流(一次写入一个字节数据)
void write(byte[] b) 将b.length的字节从指定字节数组写入文件输出流(一次写入一个字节数组数据)
void write(byte[] b,int off,int len) 将len字节从指定字节数组开始,从偏移量off开始写入(一次写入一个字节数组数据)

下面给出示例代码:

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

public class Demo2 {
    public static void main(String[] args) throws IOException {
        //构造方法1:
        FileOutputStream fos1 = new FileOutputStream("Demo2\\fos1.txt");

        //构造方法2:
        File f = new File("Demo2\\fos2.txt");
        FileOutputStream fos2 = new FileOutputStream(f);

        //字符流输入:
        fos1.write(97);

        //Byte[]流输入;(可以写String类型采用格式转换)
        byte[] bytes = {97,98,99,100,101};
        fos1.write(bytes);
        fos1.write("Hello".getBytes(StandardCharsets.UTF_8));

        //Byte[]流部分输入:
        fos1.write(bytes,1,3);
    }
}

字节流两个小问题

1.字节流写完数据如何换行?

  • 写完数据后,加换行符

​ windows:\r\n

​ linux:\n

​ mac:\r

2.字节流写数据如何实现追加写入?

  • public FileOutputStream(String name,boolean append)
  • 创建文件输出流以指定的名称写入文件,如果第二个参数为true,则字节将写入文件的末尾而不是开头

下面给出示例代码:

import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

public class Demo3 {
    public static void main(String[] args) throws IOException {
        FileOutputStream fos = new FileOutputStream("Demo2\\fos3.txt");

        //实现换行需要在输入结束后打印换行符:
        fos.write("Hello".getBytes(StandardCharsets.UTF_8));
        fos.write("\r\n".getBytes(StandardCharsets.UTF_8));
        fos.write("Hello".getBytes(StandardCharsets.UTF_8));

        //如果要实施追加操作,需要在定义对象时设置为可追加模式:
        FileOutputStream foss = new FileOutputStream("Demo2\\fos3.txt",true);
    }
}

字节流写数据加异常处理

finally:在异常处理时提供finally模块来执行所有清除操作(close())

特点:被finally控制的语句一定会执行,除非JVM退出

//基本格式
try{
    可能出现异常的代码;
} catch(异常类型 变量名){
    异常的处理代码;
} finally{
    执行所有清楚操作;
}

下面给出示例代码:

import java.io.FileOutputStream;
import java.io.IOException;

public class Demo4 {
    public static void main(String[] args) {
        //我们下面将采用try()来处理异常

        //因为fos在下面各个部分都使用,需要在外面定义fos且赋值null
        FileOutputStream fos = null;

        //第一层try,处理write
        try {
            fos = new FileOutputStream("Demo2\\fos.txt");
            fos.write(97);
        } catch (IOException e){
            //出现异常打印异常
            e.printStackTrace();
        } finally {
            //最后记得close(),但close也有异常,所以出现第二层try(注意要在fos存在的情况下close())
            if(fos != null){
                try {
                    fos.close();
                } catch (IOException e){
                    e.printStackTrace();
                }
            }
        }
    }
}

字节流读数据

FileInputStream:从文件系统中的文件获取输入字节

FileInputStream:通过打开与实际文件的连接来创建一个FileInputStream,该文件由文件系统中的路径名name命名

下面给出代码示例:

import java.io.FileInputStream;
import java.io.IOException;

public class Demo5 {
    public static void main(String[] args) throws IOException {
        //输入流对象
        FileInputStream fis = new FileInputStream("Demo2\\fos.txt");

        //一次读取一个字节(读取第一个字节)
        int i = fis.read();
        System.out.println(i);
        System.out.println((char)i);

        //一次读取一个字节(读取第二个字节)
        i = fis.read();
        System.out.println(i);
        System.out.println((char)i);

        //一次读取一个字节(读取第三个字节)
        //注意:当文件没有内容时,反馈-1
        i = fis.read();
        System.out.println(i);
        System.out.println((char)i);

        //输入流对象
        FileInputStream fiss = new FileInputStream("Demo2\\fos.txt");

        //所以我们可以根据没有内容反馈-1的特性来输出:
        while ((i = fiss.read()) != -1){
            System.out.print((char)i);
        }
    }
}

案例:复制文本文件

需求:把fos1的内容复制到fos中

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class Demo6 {
    public static void main(String[] args) throws IOException {
        //把fos1内容移到fos中

        //创建输入流对象
        FileInputStream fis = new FileInputStream("Demo2\\fos1");


        //闯进输出流对象
        FileOutputStream fos = new FileOutputStream("Demo2\\fos");

        //逐渐循环
        int i ;
        while ((i = fis.read()) != -1){
            fos.write(i);
        }

        //释放资源
        fis.close();
        fos.close();

    }

}

字节流读数据

需求:把文件fos.txt的内容读取出来在控制台输出

import java.io.FileInputStream;
import java.io.IOException;

public class Demo7 {
    public static void main(String[] args) throws IOException {
        //创造对象
        FileInputStream fis = new FileInputStream("Demo2\\fos.txt");

        //首先创造一个byte[],大小固定为1024或1024整数倍
        byte[] bytes = new byte[1024];

        //创造len来指定fis内容大小
        int len;

        //当内容不为null,输出内容
        while ((len = fis.read(bytes)) != -1){
            //注意只输出fos有的部分,采用String方法
            System.out.println(new String(bytes,0,len));
        }
    }
}

案例:复制图片

需求:把图片1复制到图片2

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class Demo8 {
    public static void main(String[] args) throws IOException {
        //创造输入流对象
        FileInputStream fis = new FileInputStream("D:\\test\\mn.jpg");

        //创造输出流对象
        FileOutputStream fos = new FileOutputStream("Demo2\\mmn.jpg");

        //逐一赋值
        byte[] bytes = new byte[1024];
        int len;
        while ((len = fis.read()) != -1 ){
            fos.write(bytes,0,len);
        }

        //close处理
        fis.close();
        fos.close();
    }
}

字节缓冲流

字节缓冲流提供空间来存储写入读取的字节,使IO操作不再频繁

下面给出两种字节缓冲流的概念:

  • BufferOutputSteam:该类实现缓冲输出流;通过设置这样的输出流,应用程序可以向底层输出流写入字节,而不必为写入到的每个字节导致底层的调用
  • BufferInputSteam:该类将创建一个内部缓冲区数组;当从流种读取或跳过字节时,内部缓冲区将根据需要从所包含的输入流中重新填充,一次多个字节

下面给出构造方法:

  • 字节缓冲输出流:BufferOutputSteam(OutputSteam out)
  • 字节缓冲输入流:BufferInputSteam(InputSteam in)

为什么构造方法需要的是字节流,而不是具体的文件或路径呢?

//因为字节缓冲流仅仅提供缓冲区,真正的读写仍旧由基本的字节流对象控制操作

下面给出示例代码:

import java.io.*;
import java.nio.charset.StandardCharsets;

public class Demo1 {
    public static void main(String[] args) throws IOException {
        //先创建输出流对象
        FileOutputStream fos = new FileOutputStream("Demo3\\fos.txt");

        //创建缓冲流
        BufferedOutputStream bos = new BufferedOutputStream(fos);

        //上面两步可以合成一步:BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("Demo3\\fos.txt"));

        //缓冲流可以使用输出流的方法(缓冲流只负责缓存,其他方法仍旧使用输出流对象的方法)
        bos.write(97);
        bos.write("Hello\t\n".getBytes(StandardCharsets.UTF_8));

        //清空
        bos.close();

        //创造输入流对象
        FileInputStream fis = new FileInputStream("Demo3\\fos.txt");

        //创造缓冲流
        BufferedInputStream bis = new BufferedInputStream(fis);

        //输出:
        byte[] bys = new byte[1024];
        int len;
        while ((len = bis.read(bys)) != -1){
            System.out.println(new String(bys,0,len));
        }

        //清空
        bis.close();
    }
}

案例:复制视频

需求:把D:\Test\mm.avi视频转移到Demo3\mmm.avi

下面给出代码实例:

import java.io.*;

public class Demo2 {
    public static void main(String[] args) throws IOException {
        //创造开始时间
        long setTime = System.currentTimeMillis();

        //第1种:基本字节流一次读写一个字节
        method1();

        //第2种:基本字节流一次读写一个字节数组
        method2();

        //第3种:缓存字节流一次读写一个字节
        method3();

        //第4种:缓存字节流一次读写一个字节数组
        method4();

        //创造结束时间
        long endTime = System.currentTimeMillis();
        System.out.println("一共用时:" + (endTime-setTime) +"毫秒");

        //当文件适中(速度来说):4>2>3>>1
    }

    public static void method1() throws IOException {
        FileOutputStream fos = new FileOutputStream("D:\\Test\\mm.avi");

        FileInputStream fis = new FileInputStream("Demo3\\mmm.avi");

        int i;
        while ((i = fis.read()) != -1){
            fos.write(i);
        }

        fos.close();
        fis.close();
    }

    public static void method2() throws IOException {
        FileOutputStream fos = new FileOutputStream("D:\\Test\\mm.avi");

        FileInputStream fis = new FileInputStream("Demo3\\mmm.avi");

        byte[] bys = new byte[1024];
        int i;
        while ((i = fis.read(bys)) != -1){
            fos.write(bys,0,i);
        }

        fos.close();
        fis.close();
    }

    public static void method3() throws IOException {
        FileOutputStream fos = new FileOutputStream("D:\\Test\\mm.avi");
        BufferedOutputStream bos = new BufferedOutputStream(fos);

        FileInputStream fis = new FileInputStream("Demo3\\mmm.avi");
        BufferedInputStream bis = new BufferedInputStream(fis);

        int i;
        while ((i = bis.read()) != -1){
            bos.write(i);
        }

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

    public static void method4() throws IOException {
        FileOutputStream fos = new FileOutputStream("D:\\Test\\mm.avi");
        BufferedOutputStream bos = new BufferedOutputStream(fos);

        FileInputStream fis = new FileInputStream("Demo3\\mmm.avi");
        BufferedInputStream bis = new BufferedInputStream(fis);

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

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

字符流分界线

下面介绍均为字符流

字符流基本介绍

为什么会出现字符流呢?

  • 因为字节流操作中文并不方便
  • 字符流 = 字节流 + 编码表

如何标识中文:

  • 无论哪种编码存储方式,中文的第一个字节都是负数

针对字符流:

  • GBK -> 二位数
  • UTF-8 -> 三位数

编码表

基本知识:

  • 计算机存储的信息都是用二进制存储的,我们在屏幕中看到的英文汉字都是二进制转换之后的结果
  • 编码:按照某种规则,将字符存储到计算机中
  • 解码:将存储在计算机中的二进制按照某种规则解析出来
  • 字符编码:自然语言字符与二进制之间的对应关系(A <-> 65)

字符集:

  • 是一个系统支持的所有字符的集合,包括各国家文字,标点符号,图形符号,数字等
  • 计算机要精准存储和识别各种字符集符号,就需要进行字符编码,一套字符集必然至少有一套字符编码
  • 常见字符编码:ASCII字符集,GBXXX字符集,Unicode字符集

ASCII字符集:

  • ASCII字符集:基于拉丁字母的一套电脑编码系统,主要显示现代英语,主要包括控制字符和可显示字母
  • 基本ASCII字符集,使用7位一体,共128字符。

GBXXX字符集:

  • GB2312:简体中文码表,127以内字符意义相同,但大于127字符相连标识文字,共7000多文字

  • GBK:最常用的中文码表,在GB2312上进行扩充,共21003汉字,包括繁体汉字以及日韩汉字等

  • GB18030:最新的中文码表,共70244汉字,包括少数民族,繁体,日韩等

Unicode字符集:

  • 为表达任意语言的任意字符而设计的,是业界的一种标准,称为统一码,标准万国码
  • 最多使用4个字节的数字来表达字母,符号或文字
  • 包括:UTF-8,UTF-16,UTF-32

UTF-8:

  • 用来表示Unicode标准中任意字符,优先采用编码
  • 使用一至四字节为每个字符编码
  • 128个US-ASCII字符,只需一个字符编码
  • 拉丁文等字符,需要两个字符编码
  • 大部分常用字(含中文),使用三个字符编码
  • 其他极少使用的UTF辅助字符,使用四个字符编码

字符串的编码解码问题

编码:

  • byte[] getByte():使用平台默认字符集将该String编码为一系列字节,将结果存储到新的字节数组中
  • byte[] getByte(String charsetNAme):使用指定字符集将该String编码为一系列字节,将结果存储到新的字节数组中

解码:

  • String(byte[] bytes):通过使用平台的默认字符集解码指定的字符数组来构造新的String
  • String(byte[] bytes,String charsetName):通过指定的字符集解码指定的字节数组来构造新的String

下面给出示例代码:

import java.io.UnsupportedEncodingException;
import java.util.Arrays;

public class Demo1 {
    public static void main(String[] args) throws UnsupportedEncodingException {
        //设置String
        String s ="中国";

        //编码:
        byte[] bys1 = s.getBytes("UTF-8");//这里使用UTF-8编码
        byte[] bys2 = s.getBytes("GBK");//这里采用GBK编码

        //这里采用Arrays.toString将其变成字符串输出
        System.out.println(Arrays.toString(bys1));
        System.out.println(Arrays.toString(bys2));

        //解码:
        String s1 = new String(bys1);//这里采用默认UTF-8
        String s2 = new String(bys1,"UTF-8");//这里使用UTF-8
        String s3 = new String(bys1,"GBK");//这里采用GBk解码

        //输出解码内容:
        System.out.println(s1);
        System.out.println(s2);
        System.out.println(s3);
    }
}

字符流的编码解码问题

字符流抽象基类:

  • Reader:字符输入流抽象类
  • Writer:字符输出流抽象类

字符流中的编码解码问题相关类

  • InputStreamReader
  • OutputStreamWriter

下面给出示例代码:

//下面仅对于讲解纯净版
import java.io.*;

public class Demo3 {
    public static void main(String[] args) throws IOException {
        FileOutputStream fos = new FileOutputStream("Demo4\\fos.txt");

        OutputStreamWriter osr = new OutputStreamWriter(fos);

        osr.write("中国人");

        osr.close();

        FileInputStream fis = new FileInputStream("Demo4\\fos.txt");

        InputStreamReader isr = new InputStreamReader(fis);

        int ch;
        while ((ch = isr.read()) != -1){
            System.out.println((char)ch);
        }
    }
}
//下方给出不同类型进行讲解
import java.io.*;

public class Demo2 {
    public static void main(String[] args) throws IOException {
        //创建字符流编码
        OutputStreamWriter osw1 = new OutputStreamWriter(new FileOutputStream("Demo4\\osw.txt"));//这里直接编码
        OutputStreamWriter osw2 = new OutputStreamWriter(new FileOutputStream("Demo4\\osw.txt"),"UTF-8");//这里采用UTF编码
        OutputStreamWriter osw3 = new OutputStreamWriter(new FileOutputStream("Demo4\\osw.txt"),"GBk");//这里采用GBK编码

        osw1.write("中国");//这里写入中国
        osw2.write("中国");//这里写入中国
        osw3.write("中国");//这里写入乱码,因为编译器默认解码UTF-8,这里采用GBK编码,无法正确编译

        osw1.close();
        osw2.close();
        osw3.close();

        //创建字符流解码
        InputStreamReader isr1 = new InputStreamReader(new FileInputStream("Demo4\\osw.txt"));//正常解码(UTF-8)
        InputStreamReader isr2 = new InputStreamReader(new FileInputStream("Demo4\\osw.txt"));//特殊解码(GBK)

        int ch1;
        while ((ch1 = isr1.read()) != -1){
            System.out.println((char)ch1);
        }

        int ch2;
        while ((ch2 = isr1.read()) != -1){
            System.out.println((char)ch2);
        }


    }
}

字符流基本方法

方法如下:

方法名 说明
flush() 刷新流,还可以继续写数据
close() 关闭流,释放资源,但释放资源前会刷新数据

字符流写数据

方法如下:

方法名 说明
void write(int c) 写一个字符
void write(char[] cbuf) 写一个字符数组
void write(char[] cbuf,int off,int len) 写一个字符数组的一部分
void write(String str) 写一个字符串
void write(String str,int off,int len) 写一个字符串的一部分

下面给出示例代码:

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;

public class Demo1 {
    public static void main(String[] args) throws IOException {
        //首先创建对象
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("Demo5\\osw.txt"));

        //第一种:
        osw.write(97);

        //第二种:
        char[] chars = {'a','b','c'};
        osw.write(chars);

        //第三种:
        osw.write("abcde");

        //第四种:
        osw.write("abcde",0,5);

        //第五种:
        osw.write("abcde",0,"abcde".length());

        //flush方法:
        osw.flush();//采用这种方法,使数据刷新出来

        //close()方法:
        osw.close();//关闭接口,但在关闭前会刷新数据,同时使用flush方法
    }
}

字符流读数据

方法如下:

方法名 说明
int read() 一次读一个字符数据
int read(char[] cbuf) 一次读一个字符数组数据

下面给出代码实例:

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

public class Demo2 {
    public static void main(String[] args) throws IOException {
        //创建字符流读取对象
        InputStreamReader isr = new InputStreamReader(new FileInputStream("Demo5\\osw.txt"));

        //第一种读取:(一次读一个字符)
        int ch;
        while ((ch = isr.read()) != -1){
            System.out.print((char)ch);
        }

        //第二种读取:(一次读取多个)
        char[] chars = new char[1024];
        int len;
        while ((len = isr.read(chars)) != -1){
            System.out.println(new String(chars,0,chars.length));
        }
    }
}

案例:复制java文件

需求:把该模块下的Demo5\src\Demo2.java文件复制到Demo5\src\Demo4.txt

import java.io.*;

public class Demo3 {
    public static void main(String[] args) throws IOException {
        //创建输入流对象
        InputStreamReader isr = new InputStreamReader(new FileInputStream("Demo5\\src\\Demo2.java"));

        //创建输出流对象
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("Demo5\\src\\Demo4.txt"));

        //读取数据,复制文件
        char[] ch = new char[1024];
        int len;
        while ((len = isr.read(ch)) != -1){
            osw.write(ch);
        }

        osw.close();
        isr.close();
    }
}

案例:复制java文件(改进版)

需求:把该模块下的Demo5\src\Demo2.java文件复制到Demo5\src\Demo4.txt

import java.io.*;

public class Demo4 {
    public static void main(String[] args) throws IOException {
        //创建输入流对象(简化版)
        FileReader fr = new FileReader("Demo5\\src\\Demo2.java");

        //创建输出流对象(简化版)
        FileWriter fw = new FileWriter("Demo5\\src\\Demo4.txt");

        //读取数据,复制文件
        char[] ch = new char[1024];
        int len;
        while ((len = fr.read(ch)) != -1){
            fw.write(ch);
        }

        fw.close();
        fr.close();
    }
}

这里主要是用FileReader和FileWriter子类来更换InputStreamReader和OutputStreamWriter类,减少代码冗杂

字符缓冲流

字符缓冲流关键类:

  • BufferedWriter:将文本写入字符输出流,缓冲字符,以提供单个字符,数组和字符串的高效写入,可指定缓冲区大小
  • BufferedReader:从字符输入流读取文本,缓冲字符,以提供字符,数组和行的高效读取,可以指定缓冲区大小

构造方法:

  • BufferedWriter(Writer out)
  • BufferedReader(Reader in)

下面给出示例代码:

import java.io.*;

public class Demo1 {
    public static void main(String[] args) throws IOException {
        //创建缓冲流字符输出流
        FileWriter fw = new FileWriter("Demo6\\fw.txt");
        BufferedWriter bw = new BufferedWriter(fw);

        fw.write("Hello");
        fw.write("World");

        //创建缓冲流字符输入流
        FileReader fr = new FileReader("Demo6\\fw.txt");
        BufferedReader br = new BufferedReader(fr);

        int ch;
        while ((ch = br.read()) != -1) {
            System.out.println((char)ch);
        }
        bw.close();
        br.close();
    }
}

字符缓冲流特有功能

BufferedWrier:

  • void newLine():写一行行分隔符

BufferedReader:

  • public String readLine():读一行文字,不包括终止字符;若到结尾为null

下面给出示例代码:

import java.io.*;

public class Demo2 {
    public static void main(String[] args) throws IOException {
        //创建对象
        BufferedWriter bw = new BufferedWriter(new FileWriter("Demo6\\Demo.txt"));

        for (int i = 0; i < 2; i++) {
            bw.write("Hello" + i);
            bw.newLine();//换行(各操作系统通用)
        }

        bw.close();

        //创建对象
        BufferedReader br = new BufferedReader(new FileReader("Demo6\\Demo.txt"));

        //读取第一行
        String s = br.readLine();//每次读取一行
        System.out.println(s);

        //读取第二行
        s = br.readLine();//每次读取一行
        System.out.println(s);

        //读取第三行
        s = br.readLine();//每次读取一行
        System.out.println(s);//没有内容,输出null

        //循环输出方法
        while ((s = br.readLine()) != null){
            System.out.println(s);
        }
    }
}

案例:复制java文件(字符缓冲流特有功能改进版)

需求:把该模块下的Demo6\src\Demo1.java文件复制到Demo6\src\Demo.txt

import java.io.*;

public class Demo3 {
    public static void main(String[] args) throws IOException {
        //创建对象
        BufferedReader br = new BufferedReader(new FileReader("Demo6\\src\\Demo1.java"));
        BufferedWriter bw = new BufferedWriter(new FileWriter("Demo6\\src\\Demo.txt"));

        //读取并复制:
        String s;
        while ((s = br.readLine()) != null){
            bw.write(s);
            bw.newLine();
            bw.flush();
        }

        //释放资源
        br.close();
        bw.close();
    }
}

案例:集合->文件

需求:把ArrayList集合中的字符串数据写入到文本文件中。

要求:每个字符串文件作为文件中的一行数据

代码如下:

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

public class Demo {
    public static void main(String[] args) throws IOException {
        //创建ArrayList集合
        ArrayList<String> array = new ArrayList<String>();

        //在里面加入元素
        array.add("Hello");
        array.add("World");
        array.add("java");

        //创建字符缓冲输出流对象
        BufferedWriter bw = new BufferedWriter(new FileWriter("Demo7\\src\\java.txt"));

        //遍历并写入
        for(String s : array){
            bw.write(s);
            bw.newLine();
            bw.flush();
        }

        //释放资源
        bw.close();
    }
}

案例:文件->集合

需求:把文本文件的数据读取到集合中,并遍历集合

要求:文件中每一行数据是个集合元素

代码如下:

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;

public class Demo1 {
    public static void main(String[] args) throws IOException {
        //创建字符流输入流对象
        BufferedReader br = new BufferedReader(new FileReader("Demo7\\src\\java.txt"));

        //创建ArrayList集合
        ArrayList<String> array = new ArrayList<String>();

        //逐步遍历并add
        String line;
        while ((line = br.readLine()) != null){
            array.add(line);
        }

        //释放资源
        br.close();

        //遍历验证
        for(String s : array){
            System.out.println(s);
        }
    }
}

案例:点名器

需求:我有一个文件里面存储了班级同学的名称,每个名称占一行,要求通过点名程序实现随机点名

代码如下:

刘备
关羽
张飞
诸葛亮
赵云
黄忠
司马懿
曹操
孙策
孙权
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Random;

public class Demo2 {
    public static void main(String[] args) throws IOException {
        //创建字符流输入流对象
        BufferedReader br = new BufferedReader(new FileReader("Demo7\\src\\names"));

        //创建ArrayList集合
        ArrayList<String> array = new ArrayList<String>();

        //逐步遍历并add
        String line;
        while ((line = br.readLine()) != null){
            array.add(line);
        }

        //释放资源
        br.close();

        //设立随机数
        Random r = new Random();
        int i = r.nextInt(array.size());

        //取随机数并输出
        System.out.println("幸运儿是:" + array.get(i));
    }
}

案例:集合->文件(改进版)

需求:把ArrayList集合中的Student学生对象数据写入到文本文件中。

要求:每个Student学生对象作为文件中的一行数据

代码如下:

public class Student  {
    String sid;
    String name;
    String age;

    public Student(){

    }

    public Student(String sid,String name,String age){
        this.sid = sid;
        this.name = name;
        this.age = age;
    }
}
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;

public class Demo3 {
    public static void main(String[] args) throws IOException {
        //创建字符流输出流对象
        BufferedWriter bw = new BufferedWriter(new FileWriter("Demo7\\src\\student.txt"));

        //创建ArrayList对象
        ArrayList<Student> array = new ArrayList<>();

        //创建学生对象并加入
        Student s1 = new Student("001","刘备","30");
        Student s2 = new Student("002","关羽","35");
        Student s3 = new Student("003","张飞","39");

        array.add(s1);
        array.add(s2);
        array.add(s3);

        //遍历并拼接
        for(Student s : array){
            StringBuilder sb = new StringBuilder();
            sb.append(s.sid + " " + s.name + " " + s.age);
            bw.write(String.valueOf(sb));
            bw.newLine();
            bw.flush();
        }

        //释放资源
        bw.close();
    }
}

案例:文件->集合(改进版)

需求:把文本中的数据读取到集合中,并遍历集合

要求:文本中每一行数据是一个学生对象的成员变量值(每个数据用空号隔开,每个对象占一行)

代码如下:

001 刘备 30
002 关羽 35
003 张飞 39
public class Student  {
    String sid;
    String name;
    String age;

    public Student(){

    }

    public Student(String sid,String name,String age){
        this.sid = sid;
        this.name = name;
        this.age = age;
    }
}
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;

public class Demo4 {
    public static void main(String[] args) throws IOException {
        //创建缓冲输入流对象
        BufferedReader br = new BufferedReader(new FileReader("Demo7\\src\\student.txt"));

        //创建ArrayList集合
        ArrayList<Student> array = new ArrayList<>();

        //遍历
        String line;
        while ((line = br.readLine()) != null){
            //创造String数组储存分开元素
            String[] s  = new String[3];
            s = line.split(" ");
            //元素放入Student对象
            Student student = new Student();
            student.sid = s[0];
            student.name = s[1];
            student.age = s[2];
            //将对象加入集合
            array.add(student);
        }

        //释放资源
        br.close();

        //遍历
        for(Student s : array){
            System.out.println(s.sid + s.name + s.age);
        }
    }
}

案例:复制单级文件夹

需求:把"IO流\Demo6"下的文件复制到"IO流"中(文件夹内只包含文件,不包含目录)

代码如下:

import java.io.*;

public class Demo1 {
    public static void main(String[] args) throws IOException{
        //创建数据源目录File对象
        File srcFolder = new File("IO流\\Demo6");

        //创建数据目录名File对象的名称
        String srcFolderName = srcFolder.getName();

        //创建目的地目录File对象,这里名字和源目录名一致
        File destFolder = new File("IO流",srcFolderName);

        //判断目的地目录对应的File是否存在,若不存在则创建
        if(!destFolder.exists()){
            destFolder.mkdir();
        }

        //获得数据源目录下所有文件File数组
        File[] files = srcFolder.listFiles();

        //遍历数组得到所有文件
        for(File f : files){
            //得到文件名并在目的目录创造文件
            String filename = f.getName();
            File destFile = new File(destFolder,filename);

            //将文件复制进来(我们采用方法来复制)
            copy(f,destFile);
        }
    }

    public static void copy(File srcFile, File destFile) throws IOException {
        //这里采用字节流
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcFile));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destFile));

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

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

案例:复制多级文件夹

需求:把"IO流\Demo1"下的文件复制到"IO流\Demo8"中(文件夹内既包含文件,又包含目录)

import java.io.*;

public class Demo2 {
    public static void main(String[] args) throws IOException{
        //首先创建数据源对象,这里指定Demo1
        File srcFile = new File("D:\\程序代码\\第1部分javase\\code\\IO流\\Demo1");
        //然后创建被复制位置对象,这里指定Demo8
        File destFile = new File("D:\\程序代码\\第1部分javase\\code\\IO流\\Demo8");

        //接下来我们创建方法来实现效果(方法中包含递归)
        copyFolder(srcFile,destFile);
    }

    //copyfolder复制文件夹
    public static void copyFolder(File srcFile,File destFile) throws IOException{
        //首先判断复制文件是否为文件夹:
        if(srcFile.isDirectory()){
            //这里判断成功,为文件夹
            //那么我们需要获取名字,在粘贴地点创造相同名字的文件夹
            File destFloder = new File(destFile,srcFile.getName());

            //判断是否存在,若不存在创建一个文件夹
            if(!destFloder.exists()){
                destFloder.mkdir();
            }

            //有文件夹后,将文件夹内容增添进去
            //首先获得文件夹内所有文件
            File[] files = srcFile.listFiles();
            //逐步将文件加入
            for (File file : files){
                //这里一直递归
                copyFolder(file,destFloder);
            }
        }else {
            //这里书写文件复制:
            File newFile = new File(destFile,srcFile.getName());
            copyFile(srcFile,newFile);
        }
    }

    //copyfile复制文件
    public static void copyFile(File srcFile,File destFile) throws IOException{
        //创建两个缓冲流字符流输入输出对象
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcFile));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destFile));

        //循环内容并复制
        byte[] bys = new byte[1024];
        int len;
        while ((len = bis.read(bys)) != -1){
            bos.write(bys,0,len);
        }

        //释放内存
        bis.close();
        bos.close();
    }
}

复制文件的异常处理

直接抛出异常写法:

//直接抛出异常写法
    public static void method1() throws IOException {
        FileReader fr = new FileReader("Demo1.txt");
        FileWriter fw = new FileWriter("Demo2.txt");

        char[] ch = new char[1024];
        int len;
        while ((len = fr.read(ch)) != -1){
            fw.write(ch,0,len);
        }

        fr.close();
        fw.close();
    }

try-catch-finally方法:

//try--catch--finally方法
    public static void method2() {

        FileReader fr = null;
        FileWriter fw = null;
        try {
            fr = new FileReader("Demo1.txt");
            fw = new FileWriter("Demo2.txt");

            char[] ch = new char[1024];
            int len;
            while ((len = fr.read(ch)) != -1){
                fw.write(ch,0,len);
            }

        }catch (IOException e){
            e.printStackTrace();
        }finally {
            if(fr != null){
                try {
                    fr.close();
                }catch (IOException e){
                    e.printStackTrace();
                }
            }

            if(fw != null){
                try {
                    fw.close();
                }catch (IOException e){
                    e.printStackTrace();
                }
            }
        }
    }

jdk7改进后写法:

//jdk7之后改进做法
    public static void method3() {
        try(FileReader fr = new FileReader("Demo1.txt");
            FileWriter fw = new FileWriter("Demo2.txt");) {

            char[] ch = new char[1024];
            int len;
            while ((len = fr.read(ch)) != -1){
                fw.write(ch,0,len);
            }

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

特殊操作流分界线

下面介绍均为特殊操作流

标准输入输出流

System类中有两个静态的成员变量:

  • public static final InputStream in:标准输入流(对标Scanner)
  • public static final PrintStream out:标准输出流(对标System.out.print)

下面给出代码实例:

import java.io.*;

public class Demo1 {
    public static void main(String[] args) throws IOException {
        //创建最基本的:
        InputStream is = System.in;

        int by;
        while ((by = is.read()) != -1){
            System.out.println((char)by);
        }


        //这里标准类指向Scanner
        //我们可以创建缓冲流字符流标准输出流
        //这里采用BufferedReader,InputStreamReader,InputStream共同创建
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        System.out.println("请输入一句话:");
        String s = br.readLine();
        System.out.println("你输入的是:" + s);

        System.out.println("请输入一个数字:");
        int i = Integer.parseInt(br.readLine());
        System.out.println("你输入的是:" + i);
    }
}
import java.io.PrintStream;

public class Demo2 {
    public static void main(String[] args) {
        PrintStream ps = System.out;

        //完全等同于System.out.print()
        ps.print("123");
        ps.println("hello");

    }
}

打印流

打印流分类:

  • 字节打印流:PrintStream
  • 字符打印流:PrintWriter

打印流特点:

  • 只负责输出数据,不负责读取数据
  • 有自己特有方法

字节打印流

构造方法:

方法名 说明
PrintStream(String fileName) 使用指定的文件名创建一个新的PrintWriter,而不需要自动执行刷新

特点:

  • 使用继承父类的方法写数据,查看时会转码
  • 使用自己特有方法写数据,数据直接原样输出

代码如下:

import java.io.IOException;
import java.io.PrintStream;

public class Demo3 {
    public static void main(String[] args) throws IOException {
        PrintStream ps = new PrintStream("Demo9\\src\\Demo1\\java.txt");

        //正常方法(这里采用的是ASCII码)
        ps.write(98);
        //特殊方法(这里直接输出)
        ps.println(99);
        ps.print(98);
    }
}

字符打印流

构造方法:

方法名 说明
PrintWriter(String fileName) 使用指定文件名创建一个新的PrintWriter,而不需要自动执行刷新
PrintWriter(Writer out,boolean autoFlush) 创建一个新的PrintWriter

代码如下:

import java.io.IOException;
import java.io.PrintWriter;

public class Demo4 {
    public static void main(String[] args) throws IOException {
        //两种构造方法

        //第一种,不能自动刷新flush,需要手动刷新
        PrintWriter pw1 = new PrintWriter("Demo9\\src\\Demo1\\java.txt");

        //第二种,不需要手动刷新flush
        PrintWriter pw2 = new PrintWriter(new PrintWriter("Demo9\\src\\Demo1\\java.txt"),true);

        //正常方法
        pw1.write(98);

        //特殊方法
        pw1.println("123");
        pw1.print("2");
    }
}

案例:复制java文件(打印流改进版)

需求:把模块目录下的"Demo9\src\Demo1\Demo1.java"复制到"Demo9\src\Demo1\java1.txt"

代码如下:

import java.io.*;

public class Demo5 {
    public static void main(String[] args) throws IOException {
        //输入流无法用print代替,所以正常缓冲流
        BufferedReader br = new BufferedReader(new FileReader("Demo9\\src\\Demo1\\Demo1.java"));
        //输出流采用print方法
        PrintWriter pw =  new PrintWriter(new FileWriter("Demo9\\src\\Demo1\\java1.txt"));

        //采用逐个复制
        String s;
        while ((s=br.readLine()) != null){
            pw.println(s);
        }

        //释放资源
        br.close();
        pw.close();
    }
}

对象序列化

对象序列化:把对象保存到磁盘中,或者在网络中传输对象

这种机制使用一个字节序列表示一个对象,该字节序列包含:对象的类型,对象的数据以及对象中存储的属性等信息

对象序列化流

对象序列化流:ObjectOutputStream

  • 将java对象的原始数据类型和图形写入OutputStream
  • 可以采用ObjectInputStream读取对象
  • 可以通过使用流的文件来实现对象的持久存储
  • 如果流是网络套接字流,则可以在另一个主机或进程中重构对象

构造方法:

  • ObjectOutputStream(OutputStream out):创建一个写入指定OutputStream的ObjectOutputStream

序列化对象方法:

  • void writeObject(Object obj):将指定对象写入ObjectOutputStream

注意:

  • 一个对象想要被序列化,需要该类实现继承Serializable接口
  • Serializable接口是一个标记接口,实现该接口不需要写任何方法

代码如下:

import java.io.Serializable;

//序列化类需要接口Serializable作为标识
public class Student implements Serializable {
    public String name;
    public int age;

    public Student(){

    }

    public Student(String name,int age){
        this.age = age;
        this.name = name;
    }
}
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;

public class Demo1 {
    public static void main(String[] args) throws IOException {
        //构造方法
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("Demo9\\src\\Demo2\\java.txt"));

        //创建对象
        Student student = new Student("张飞",20);

        //对象序列化流特殊方法
        oos.writeObject(student);

        //释放资源
        oos.close();
    }
}

对象反序列化

对象反序列化:ObjectInputStream

  • ObjectInputStream反序列化先使用ObjectOutputStream编写的原始数据和对象

构造方法:

  • ObjectInputStream(InputStream in):创建从指定的InputStream读取的ObjectInputStream

反序列化方法:

  • Object readObject():从ObjectInputStream读取一个对象

代码如下:

import java.io.Serializable;

//序列化类需要接口Serializable作为标识
public class Student implements Serializable {
    public String name;
    public int age;

    public Student(){

    }

    public Student(String name,int age){
        this.age = age;
        this.name = name;
    }
}
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;

public class Demo2 {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        //创造反序列化流对象
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("Demo9\\src\\Demo2\\java.txt"));

        //调用特有方法
        Object obj = ois.readObject();

        //需要向下转型
        Student s = (Student) obj;

        //输出测试
        System.out.println(s.name + " " + s.age);

        //释放资源
        ois.close();
    }
}

对象序列化三问题

  1. 用对象序列化流列化了一个对象后,假如我们修改了对象所属的类文件,读取文件是否出错?
  • 会出问题,抛出InvalidClassException异常
  1. 如果出现问题,如何解决?
  • 给对象所属的类加一个serialVersionUID
  • private static final long serialVersionUID = 42L
  1. 如果一个对象中的某个成员变量的值不想被序列化,该如何实现?
  • 给该成员变量加上transient关键词修饰,该关键词标记的成员变量不参与序列化过程

properties类

properties类概述:

  • 是一个Map体系的集合类
  • Properties可以保存到流中或者从流中加载

练习代码如下:

import java.util.Properties;
import java.util.Set;

public class Demo1 {
    public static void main(String[] args) {
        //创造类集合,这里不是正常集合,不需要<>指定类型,固定为Object类型
        Properties prop = new Properties();
        //添加元素
        prop.put("001","胡桃");
        prop.put("002","钟离");
        prop.put("003","雷神");
        //将键转移到Set集合中
        Set<Object> keySet = prop.keySet();
        //根据键得到值
        for(Object obj : keySet){
            Object value = prop.get(obj);
            System.out.println(obj + " " + value);
        }
    }
}

properties特有方法

方法如下:

方法名 说明
Object setProperty(String key,String value) 设置集合的键和值,都是String类型;底层调用Hashtable方法put
String getProperty(Strig key) 使用此属性列表中指定的键搜索属性
Set stringPropertyNames() 从该属性列表中返回一个不可修改的键集,其中键对应的是String

代码如下:

import java.util.Properties;
import java.util.Set;

public class Demo2 {
    public static void main(String[] args) {
        //创造集合
        Properties prop = new Properties();
        //设置方法(都为String类型)
        prop.setProperty("001","温迪");
        prop.setProperty("002","钟离");
        prop.setProperty("003","雷神");
        //得到所有键(返回String类型)
        Set<String> names = prop.stringPropertyNames();
        //循环输出
        for(String key : names){
            //通过key得到value
            String value = prop.getProperty(key);
            //输出检验
            System.out.println(key + " " + value);
        }
    }
}

Properities和IO结合方法

方法如下:

方法名 说明
void load(InputStream inStream) 从输入字节流读取属性列表(键和元素对)
void load(Reader reader) 从输入字符流读取属性列表(键和元素对)
void store(OutputStream out,String comments) 将此属性列表(键和元素对)写入此Properties表中,以适合使用load(InputStream)方法的格式写入输出字符流
void store(Writer writer,String comments) 将此属性列表(键和元素对)写入此Properties表中,以适合使用load(Reader)方法的格式写入输出字符流

代码如下:

import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Properties;

public class Demo3 {
    public static void main(String[] args) throws IOException {
        //调用方法1
        myStore();
        //调用方法2
        myLoad();
    }

    //myLoad方法
    private static void myLoad() throws IOException{
        Properties prop = new Properties();

        //采用方法把文件集合写入类对象中
        FileReader fr = new FileReader("D:\\程序代码\\第1部分javase\\code\\IO流\\Demo10\\src\\Demo1\\java.txt");

        prop.load(fr);

        System.out.println(prop);
    }

    //myStore方法
    public static void myStore() throws IOException {
        Properties prop = new Properties();

        prop.setProperty("001","温迪");
        prop.setProperty("002","钟离");
        prop.setProperty("003","雷神");

        //采用方法把类数据写到文件中:
        FileWriter fw = new FileWriter("D:\\程序代码\\第1部分javase\\code\\IO流\\Demo10\\src\\Demo1\\java.txt");
        prop.store(fw,null);
        fw.close();
    }
}

案例:游戏次数

需求:请写程序实现猜数字小游戏,只能试玩三次,如果超过三次不能再游玩

在同目录下创造一个count.txt文档用来记录次数

#Fri Jun 24 15:55:49 CST 2022
count=0

代码如下:

import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Properties;

public class Demo1 {
    public static void main(String[] args) throws IOException {
        //创造集合对象
        Properties prop = new Properties();

        //读取count.txt
        FileReader fr = new FileReader("D:\\程序代码\\第1部分javase\\code\\IO流\\Demo10\\src\\Demo2\\count.txt");
        prop.load(fr);

        //判断是否达到3次
        int count = Integer.parseInt(prop.getProperty("count"));
        if(count >= 3){
            //大于3次不能继续游玩
            System.out.println("sorry,you can not play!");
        }else {
            //未到3次,玩游戏,count+1,并再次写入文件
            playGame();
            count++;
            prop.setProperty("count",String.valueOf(count));
            FileWriter fw = new FileWriter("D:\\程序代码\\第1部分javase\\code\\IO流\\Demo10\\src\\Demo2\\count.txt");
            prop.store(fw,null);
            fw.close();
        }

        fr.close();
    }

    //游戏内容未书写
    private static void playGame() {

    }
}

结束语

好的,关于IO操作我们讲到这里

posted @ 2022-07-06 15:29  秋落雨微凉  阅读(82)  评论(0编辑  收藏  举报