11Java第十一章IO

本文介绍了Java中的File类,用于表示文件和目录,详细讲解了字节流和字符流的区别以及如何进行读写操作。接着,讨论了节点流与处理流的概念,例如BufferedInputStream和BufferedReader提供的缓冲功能。还提到了Print流,主要用于程序的输出。最后,讨论了对象输入、输出流,用于对象序列化和反序列化的操作,实现对象信息的持久化保存。
摘要由CSDN通过智能技术生成

File类(表示文件)

我们要在Java程序中操作硬盘上的文件,首先需要在程序中表示一个对应的文件。

一个File类的对象表示硬盘上的一个文件或目录(文件夹)

File类只能表示文件,不能对文件内容进行读写操作。

/*
  一个file类的对象表示一个文件或目录
  new File("String类型的文件名  可以是相对的路径也可以是绝对的路径")
  File(父级,子集);
*/
File f1 = new File("D:\\ideaProjects\\javaIO/demo.txt");
System.out.println(f1.length());

String p = "D:/";
File f2 = new File(p,"demo.text");
File f3 = new File(p,"demo1.txt");

File类中常用的方法:

  • 判断功能方法

    File f1 = new File("D:\\ideaProjects\\javaIO/demo.txt");
    System.out.println(f1.canWrite()); //是否可以写
    System.out.println(f1.canRead()); //是否可以读
    System.out.println(f1.exists()); //文件是否存在
    System.out.println(f1.isFile()); //是不是文件
    System.out.println(f1.isHidden()); //是否隐藏
    System.out.println(f1.isAbsolute());  //是不是绝对路径
    System.out.println(f1.isDirectory()); //是不是文件夹
    
  • 获取功能方法

    File f = new File("D:\\ideaProjects\\javaIO/demo.txt");
    System.out.println(f.length()); //文件长度(以字节为单位的)
    System.out.println(f.lastModified()); //最后修改的时间差
    System.out.println(new Date(164456727960L));
    System.out.println(f.getParent());
    System.out.println(f.getName());
    System.out.println(f.getAbsolutePath());
    
    File f1 = new File("IO"); //相对路径
    System.out.println(f1.getAbsolutePath()); //获取文件的绝对路径
    
    File f2 = new File("D:\\ideaProjects\\javaApi"); //这表示的是一个文件夹
    //获取此目录下所有的文件和文件夹,返回的都是文件名的字符串形式
    /*String[] fs = f2.list();
    for(String fn:fs){
        System.out.println(fn);
    }*/
    //获取此目录下所有的文件和文件夹,返回的都是文件对象
    /*File[] fs = f2.listFiles();
    for(File fn:fs){
    //  fn.delete();删除
        System.out.println(fn);
    }*/
    
    //文件筛选 筛选出文件后缀名为chm的文件
    File[] fs = f2.listFiles((dir, name) -> {return name.endsWith("chm");});
    for(File fn:fs){
        System.out.println(fn);
    }
    
  • 创建、删除方法

    //创建文件
    File f1 = new File("D:\\ideaProjects\\javaIO/demo2.txt");
    //避免创建文件的位置不存在
    try {
        f1.createNewFile(); //创建一个新的文件,前提是文件不存在
    } catch (IOException e) {
        e.printStackTrace();
    }
    f1.delete(); // 删除此文件
    
    //创建文件夹
    /*        File f = new File("D:\\ideaProjects\\javaIO/a");
    f.mkdir(); //创建文件夹,只能创建一级*/
    File f = new File("D:\\ideaProjects\\javaIO/a/b");
    //        f.mkdirs(); //创建文件夹,可以创建多级目录
    f.delete(); //只会删除b delete在删除文件夹时,一次只能删除一级目录,且目录中为空
    

IO

读写文件:I(input)O(output) 输入输出

按照读写的单位分为:

  • 字节流:一次读写一个字节。 使用的多,图片、视频、音频、exe……

    • 字节输入流:从硬盘向程序中读数据 InputStream
    • 字节输出流:从程序中向硬盘上写数据 OutStream
  • 字符流:一次读写一个字符。 只读纯文本文件,txt、java、C……

    注:Word不是纯文本文件

    • 字符输入流
    • 字符输出流

字节流

public class StreamDemo1 {
    public static void main(String[] args) throws IOException {
        //需求,把D:/demo.txt ---> E: /demo.txt
        //创建一个输入流管道,为其制定输入的文件,输入流要求文件存在,否则会报错
        FileInputStream in = new FileInputStream("D:/demo.txt");
//        int b = in.read(); //从文件中读数据,一次读一个字节,文件内容读完后返回-1.
/*        int b = 0;
        while ((b = in.read())!= -1){
            System.out.println(b);
        }*/
        //创建一个输出流管道,为其制定输出的文件,输出文件可以不存在,会自动创建
        FileOutputStream out = new FileOutputStream("E:/demo.txt");
        int b = 0;
        while ((b = in.read())!= -1){
            out.write(b);
        }
        in.close(); //关闭流通道,释放文件
        out.close();
    }
}
//标准写法,引入异常机制
public class StreamDemo2 {
    public static void main(String[] args) {
        try {
            testIO();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            System.out.println("文件找不到");
        }catch (IOException ioe){
            System.out.println("读写异常");
        }
    }

    //模拟文件读写操作
    public static void testIO() throws FileNotFoundException, IOException {
        FileInputStream in = null;
        FileOutputStream out = null;
        try {
            in = new FileInputStream(new File("D:/demo.txt"));
            out = new FileOutputStream(new File("E:/demo.txt"));
            int b = 0;
            while ((b = in.read()) != -1){
                out.write(b);
            }
        }finally {
            if(in != null){
                in.close();
            }
            if(out != null){
                out.close();
            }
        }
    }
}

read() :一次只读取一个字节,并返回结果,a-97,读完返回-1,效率低。

read(byte[] b):一次读取一个byte数组个字节内容,返回数组中实际装入内容的长度,读完返回-1。

public class StreamDemo3 {
    public static void main(String[] args) throws IOException {
        //创建一个输入流管道,为其制定输入的文件,输入流要求文件存在,否则会报错
        FileInputStream in = new FileInputStream("D:/demo.txt");
        //创建一个输出流管道,为其制定输出的文件,输出文件可以不存在,会自动创建
        FileOutputStream out = new FileOutputStream("E:/demo.txt");
//        read() 一次只读取一个字节,并返回结果,a-97,读完返回-1,效率低
//        read(byte[] b) 一次读取一个byte数组个字节内容,返回数组中实际装入内容的长度,读完返回-1
        //44个字节,数组长度为10  读5次
        byte[] b = new byte[10]; //50  44
        int size = 0; //实际向数组中读到的内容长度,主要是最后一次的实际数量
        while ((size = in.read(b)) != -1){
            System.out.println(size);
//            out.write(b); //写出会有50个字节
//write(装内容的数组,数组的第0个位置开始,size实际写出的长度); 最后一次只有4个字节,向外只写4个即可
            out.write(b, 0,size);
        }
        in.close();
        out.close();
    }
}

节点流和处理流

根据封装类型的不同:

  • 节点流:流对象中流封装的是某种特定的数据源,直接用来读文件。

    FileInputStream、FileOutSteam

  • 处理流:流对象中包含的是其他流对象,可以提供一些其他操作。(即流封装的是其他流对象)提供内部缓冲区功能。

    BufferedInputStream、BufferedOutputStream、ObjectInputStream、ObjectOutputStream

public class StreamDemo4 {
    public static void main(String[] args) throws IOException {
        //需求,把D:/demo.exe ---> E: /demo.exe
        //节点流
        FileInputStream in = new FileInputStream("D:/demo1.exe");
        //处理流
        BufferedInputStream bin = new BufferedInputStream(in);
        //节点流
        FileOutputStream out = new FileOutputStream("E:/demo1.exe");
        //处理流
        BufferedOutputStream bout = new BufferedOutputStream(out);

        byte[] b = new byte[1024]; //数组大小看具体情况,并非越大越好  数组是在内存中存储
        int size = 0;
        while ((size = bin.read()) != -1){
            bout.write(b,0,size); //虽然每次调用了write方法,但是不一定每次都会真正写出
        }
        bin.close();
        bout.flush(); //刷新缓冲区
        bout.flush();
    }
}

缓冲区源代码:

//write()
public synchronized void write(byte b[], int off, int len) throws IOException {
    if (len >= buf.length) { //我们的数组长度大于等于内部的缓冲数组,直接写出
        /* If the request length exceeds the size of the output buffer,
           flush the output buffer and then write the data directly.
           In this way buffered streams will cascade harmlessly. */
        flushBuffer();
        out.write(b, off, len); //直接写出
        return;
    }
    if (len > buf.length - count) { //当缓冲区不足以放得下新读到的内容时,写出数据
        flushBuffer();
    }
    System.arraycopy(b, off, buf, count, len); //缓冲区可以放得下,发生数组复制,复制到缓冲区中
    count += len; //缓冲区总数量增加
}

//flushBuffer()
private void flushBuffer() throws IOException {
    if (count > 0) {
        out.write(buf, 0, count);
        count = 0;
    }
}

字符流

字符输入流:Reader

​ InputStreamReader转换流:把原始的字节转换为字符。将1个中文的3个字节转为一个字符编码。

​ FileReader

字符输出流:Writer

​ OutputStreamWriter

​ FileWriter

字符处理流:BufferedReader、BufferedWriter提供对数据的缓冲功能。

public class CharDemo1 {
    public static void main(String[] args) throws IOException {
        /*
          字符流可以一次直接读取到一个字符内容
          1个汉字3个字节组成,直接可以读到
        */
        FileReader reader = new FileReader(new File("D:/demo.txt"));
/*        System.out.println((char)reader.read()); 
        System.out.println((char)reader.read());
        System.out.println((char)reader.read());
        System.out.println((char)reader.read());
        System.out.println((char)reader.read());*/
        FileWriter writer = new FileWriter(new File("E:/demo.txt"));
        int c = 0;
        while ((c = reader.read()) != -1){
            writer.write(c);
        }
        reader.close();
        writer.close();
    }
}
public class CharDemo2 {
    public static void main(String[] args) throws IOException {
        /*
          字符流可以一次直接读取到一个字符内容
          1个汉字3个字节组成,直接可以读到
        */
        FileReader reader = new FileReader(new File("D:/demo.txt"));
        FileWriter writer = new FileWriter(new File("E:/demo.txt"));
        char[] c = new char[10];
        int size = 0;
        while ((size = reader.read(c)) != -1){
            writer.write(c,0,size);
        }
        reader.close();
        writer.close()
    }
}
public class CharDemo3 {
    public static void main(String[] args) throws IOException {
        /*
          字符流可以一次直接读取到一个字符内容
          1个汉字3个字节组成,直接可以读到
        */
        FileReader reader = new FileReader(new File("D:/demo.txt"));
        BufferedReader breader = new BufferedReader(reader);
        FileWriter writer = new FileWriter(new File("E:/demo.txt"));
        BufferedWriter bwriter = new BufferedWriter(writer);
//        breader.readLine(); //一次读一行数据。数据读完后,如果没有数据,则返回null

        String line = null;
        while ((line = breader.readLine()) != null){
//            System.out.println(line);
            bwriter.write(line); //一次写出衣蛾字符串
            bwriter.newLine(); //写出一个换行符
        }
        breader.close();
        bwriter.flush();
        bwriter.close();
    }
}

Print流

Print流:没有输入,只是从程序中向外输出。

  • PrintStream:打印字节流

  • PrintWriter:打印字符流

    百度搜索,输入信息,点击百度按钮,向服务器端发送搜索,将搜索到的内容响应到浏览器。

    public class PrintDemo {
        public static void main(String[] args) throws FileNotFoundException {
            /*
              打印字符流,单向从服务器端向客户端响应处理。
              JavaEE时需要使用。
            */
            PrintWriter p = new PrintWriter("D:/demo.html");
            p.println("<h1>你好世界</h1>");
            p.println("<h1>你好世界</h1>");
            p.println("<h1>你好世界</h1>");
            p.println("<h1>你好世界</h1>");
            p.close();
        }
    }
    

对象输入、输出流(对象序列化和对象反序列化)

主要作用是用于写入对象信息与读取对象信息。

对象输入、输出流:就是把程序运行时所产生的对象信息(内存中存储),输出到一个文件中(实现对象信息的持久化保存),称为对象序列化。

例如系统升级,停止服务器,可以将一些对象保存到硬盘当中,服务器启动,从文件中读取信息。

反序列化:将对象信息读取到内存中,称为反序列化(重新创建一个对象)。(也是java中创建对象的一种方式)

public class ObjectStreamDemo1 {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        //程序运行时,产生两个对象
        String s = new String("abc");
        Date date = new Date();
        //使用对象输出流,将对象的信息输出到文件中,称为对象序列化
        FileOutputStream out = new FileOutputStream(new File("E:/object.txt"));
        ObjectOutputStream objout = new ObjectOutputStream(out);
        objout.writeObject(s);
        objout.writeObject(date);

        objout.flush();
        objout.close();

        //对象输入流读取文件中的对象信息,也称为反序列化
        FileInputStream in = new FileInputStream(new File("E:/object.txt"));
        ObjectInputStream objin = new ObjectInputStream(in);
        String s = (String)objin.readObject();
        Date date = (Date)objin.readObject();
        System.out.println(s);
        System.out.println(date);
        objin.close();
    }
}
import java.io.Serializable;

public class User implements Serializable {
    //显示为类生成一个版本号
    private static final long serialVersionUID = 4172444525933987413L;
    private int no;
    private String name;

    public User(int no, String name) {
        this.no = no;
        this.name = name;
    }

    @Override
    public String toString() {
        return "User{" +
                "no=" + no +
                ", name='" + name + '\'' +
                '}';
    }
}


public class ObjectStreamDemo2 {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        User user = new User(100,"zhang");


        //程序运行时,产生两个对象
        String s = new String("abc");
        Date date = new Date();
        //使用对象输出流,将对象的信息输出到文件中,称为对象序列化
        FileOutputStream out = new FileOutputStream(new File("E:/object.txt"));
        ObjectOutputStream objout = new ObjectOutputStream(out);
        objout.writeObject(user);
        objout.flush();
        objout.close();

        //对象输入流读取文件中的对象信息,也称为反序列化
        FileInputStream in = new FileInputStream(new File("E:/object.txt"));
        ObjectInputStream objin = new ObjectInputStream(in);
        User user1 = (User)objin.readObject();
        System.out.println(user1);
        objin.close();
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值