JavaSE进阶 | 深入理解Java IO流(缓冲流、转换流、数据流、标准输出流)

追求适度,才能走向成功;人在顶峰,迈步就是下坡;身在低谷,抬足既是登高;弦,绷得太紧会断;人,思虑过度会疯;水至清无鱼,人至真无友,山至高无树;适度,不是中庸,而是一种明智的生活态度。

导读:本篇文章讲解 JavaSE进阶 | 深入理解Java IO流(缓冲流、转换流、数据流、标准输出流),希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

目录

🥅缓冲流

1.字符输入流BufferedReader

2.字符输出流BufferedWriter

🥅转换流

1.OutputStreamWriter

2.InputStreamReader

🥅数据流

1.DataOutputStream

2.DataInputStream

🥅标准输出流

1.PrintStream

2.日志工具类

🥅File类的理解

1.常用方法1

2.常用方法2

3.listFiles方法


🥅缓冲流

(1)带有缓冲区的字符输入流;使用这个流的时候不需要自定义char数组,或者说不需要自定义byte数组自带缓冲!

(2)读取数据时,可以一次性读取一行

(3)这里只讲解字符缓冲流: java.io.BufferedReader 和 java.io.BufferedWriter;字节缓冲流使用方法是一样的。

(4)步骤:

第一步:先创建一个字符输入流FileReader;

第二步:创建一个BufferedReader包装流,调用有参构造方法把上面的字符输入流传进去;

第三步:调用包装流的readLine方法,一次读取一行;返回的是一个字符串;

第四步:关闭流,只需要关闭最外层的流即可;里面的节点流会自动关闭。

(5)BufferedReader和BufferedWriter都是包装流!

1.字符输入流BufferedReader

package com.bjpowernode.java.io;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;

public class BufferedReaderTest01 {
    public static void main(String[] args) throws Exception {
        FileReader reader = new FileReader("file");
        // 当一个流的构造方法中需要一个流的时候,这个被传进来的流叫做:节点流。
        // 外部负责包装的这个流,叫做:包装流或者叫做:处理流。
        // FileReader就是一个节点流。BufferedReader就是包装流/处理流。
        BufferedReader br = new BufferedReader(reader); // 只能传字符流

        // 优点:一次能读一行;但不带换行符!
        // br.readLine()返回的是一个字符串
        String s = null;
        while((s = br.readLine()) != null){ 
            System.out.println(s);
        }

        // 关闭流,只需要关闭最外层流就行,里面的节点流会自动关闭。
        br.close();

    }
}

2.字符输出流BufferedWriter

(1)缓冲流本质上和文件专属流的用法是很类似的,就是文件流借助于包装流,进行包装,这样读取和写入数据就不需要借助char数组或者byte数组了,直接调用方法就可以完成对应的写入一行或者读出一行到操作!

(2)包装流BufferedWriter写入数据有一个弊端,没有换行操作,需要我们手动添加换行。

package com.bjpowernode.java.io;

import java.io.*;

public class BufferedWriterTest01 {
    public static void main(String[] args) throws IOException {
        // 创建带有缓冲区的字符输出流
        BufferedWriter writer = new BufferedWriter(new FileWriter("file"));

        // 开始写
        writer.write("hello world!");
        writer.write("\n");
        writer.write("hello kitty!");

        // 刷新
        writer.flush();
        // 关闭最外层
        writer.close();
    }
}

🥅转换流

转换流OutputStreamWriter和InputStreamReader都是包装流。

1.OutputStreamWriter

(1)OutputStreamWriter:转换流;把一个字节输出流转换成字符输出流!

(2)我们可能遇到以下场景BufferedWriter流里面传的就是对应的字符输出流FileWriter流;但是我们如果只有对应的字节输出流FileOutputStream流怎么办?此时就需要使用转换流,先把字节输出流FileOutputStream转换成对应的字符输出流FileWriter。

package com.bjpowernode.java.io;

import java.io.*;

public class BufferedWriterTest01 {
    public static void main(String[] args) throws IOException {
        // 创建带有缓冲区的字符输出流
        BufferedWriter writer = new BufferedWriter(new FileWriter("file"));

        // 如果想要使用字节输出流,还是需要OutputStreamWriter进行流的转换
        // 这样才能创建带有缓冲区的字符输出流
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("file"));
        BufferedWriter writer1 = new BufferedWriter(osw);
        
        // 合并在一起
        BufferedWriter writer1 = new BufferedWriter(new OutputStreamWriter
        (new FileOutputStream("file")));

        // 开始写
        writer.write("hello world!");
        writer.write("\n");
        writer.write("hello kitty!");

        // 刷新
        writer.flush();
        // 关闭最外层
        writer.close();
    }
}

2.InputStreamReader

package com.bjpowernode.java.io;

import java.io.*;

public class BufferedReaderTest02 {
    public static void main(String[] args) {

        FileInputStream fis = null;
        try {
            // 字节流
            fis = new FileInputStream("file");
            // 通过转换流转换(InputStreamReader将字节流转换成字符流)
            // fis是节点流。reader是包装流。
            InputStreamReader reader = new InputStreamReader(fis);
            // 把转换成字符流的字节流,传过来
            // reader是节点流。br是包装流。
            BufferedReader br = new BufferedReader(reader);

            // 上面进行合并
            BufferedReader br1 = new BufferedReader(new InputStreamReader(new FileInputStream("file")));

            // 进行打印
            String s = null;
            while((s = br1.readLine()) != null){
                System.out.println(s);
            }

            // 关闭
            br.close(); // 关闭最外层

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

🥅数据流

数据流DataOutputStream和DataStream都是包装流。

1.DataOutputStream

(1)java.io.DataOutputStream:数据专属的流;也是一个包装流!
(2)这个流可以将数据连同数据的类型一并写入文件
(3)注意:这个文件不是普通文本文档(这个文件使用记事本打不开)

(4)因为不是普通文档,所以一般是数据流是DataOutputStream和DataInputStream联合使用,先写入才能读!

package com.bjpowernode.java.io;

import java.io.DataOutputStream;
import java.io.FileOutputStream;

public class DataOutputStreamTest01 {
    public static void main(String[] args) throws Exception{
        // 创建数据专属的字节输出流(写)
        DataOutputStream dos = new DataOutputStream(new FileOutputStream("file")); //生成的这个文件,记事本打不开
        // 写数据
        byte b = 100;
        short s = 200;
        int i = 300;
        long l = 400L;
        float f = 3.0F;
        double d = 3.14;
        boolean sex = false;
        char c = 'a';
        // 写;把数据以及数据的类型一并写入到文件当中
       dos.writeByte(b);
       dos.writeShort(s);
       dos.writeInt(i);
       dos.writeLong(l);
       dos.writeFloat(f);
       dos.writeDouble(d);
       dos.writeBoolean(sex);
       dos.writeChar(c);

        // 刷新
        dos.flush();
        
        // 关闭最外层
        dos.close();
    }
}

2.DataInputStream

(1)DataInputStream:数据字节输入流。
(2)DataOutputStream写的文件,只能使用DataInputStream去读。并且读的时候你需要提前知道写入的顺序;读的顺序需要和写的顺序一致。才可以正常取出数据

package com.bjpowernode.java.io;

import java.io.DataInputStream;
import java.io.FileInputStream;

public class DataInputStreamTest01 {
    public static void main(String[] args) throws Exception {
        // 创建数据专属的字节输入流(读)
        DataInputStream dis = new DataInputStream(new FileInputStream("file"));
        // 开始读
        byte b = dis.readByte();
        short s = dis.readShort();
        int i = dis.readInt();
        long l = dis.readLong();
        float f = dis.readFloat();
        double d = dis.readDouble();
        boolean sex = dis.readBoolean();
        char c = dis.readChar();
        // 打印

        System.out.println(b);
        System.out.println(s);
        System.out.println(i);
        System.out.println(l);
        System.out.println(f);
        System.out.println(d);
        System.out.println(sex);
        System.out.println(c);

        // 关闭流
        dis.close();
    }
}

🥅标准输出流

PrintStream也是一个包装流。

1.PrintStream

(1)java.io.PrintStream:标准的字节输出流,默认输出到控制台
(2)标准输出流不需要手动close()关闭!

(3)虽然默认是输出到控制台,但是可以通过System.setOut()方法改变输出流的方向,俩面的参数传一个包装流对象!

(4)实际上前面学的System.out.println前面的System.out返回的就是PrintStream流对象。

package com.bjpowernode.java.io;

import java.io.FileOutputStream;
import java.io.PrintStream;

public class PrintStreamTest {
    public static void main(String[] args) throws Exception {
        System.out.println("hello world");
        // 实际上上述代码可以拆分成
        PrintStream ps = System.out;
        ps.println("hello world");

        // 可以改变标准输出流的输出方向;
        // 例如:标准输出流不在指向控制台,指向log文件
        PrintStream printStream = new PrintStream(new FileOutputStream("log"));
        // 修改输出方向
        System.setOut(printStream);

        // 输出
        System.out.println("Hello World"); //不会再输出到控制台,而是到log文件

    }
}

System小总结:

①System.gc 建议开启垃圾回收机制,默认会调用finalize方法。

②System.arraycopy:数组拷贝,五个参数。

③System.currentTimeMillis() 获取自1970年1月1日到系统当前时间的总毫秒数。

④System.setOut:是修改输出流的方向,参数是一个PrintStream流对象。

2.日志工具类

那么标准输出流PrintStream有什么用呢?我们不妨写一个简单的日志工具类,既然是工具类就写成静态的,使用“类名.”的方式就可以调用!

日志框架

package com.bjpowernode.java.io;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.text.SimpleDateFormat;
import java.util.Date;

// 日志工具
public class Logger {
    // 记录日志的方法
   public static void log(String msg) {
       try {
           PrintStream out = new PrintStream(new FileOutputStream("log.txt",true));
           // 改变流的方向
           System.setOut(out);
           // 获取系统当前时间
           Date nowDate = new Date();
           // 格式类型转换
           SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
           String myNowdate = sdf.format(nowDate);
           // 打印
           System.out.println(myNowdate+":"+msg);

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

   }
}

日志测试

package com.bjpowernode.java.io;

public class LoggerTest {
    public static void main(String[] args) {
        // 测试日志工具类
        Logger.log("调用了System类的gc()方法,建议启动垃圾回收");
        Logger.log("调用了UserService的doSome()方法");
        Logger.log("用户尝试进行登录,验证失败");

        // 在log.txt打印的结果
       /* 2022-07-22 08:47:49 667:调用了System类的gc()方法,建议启动垃圾回收
        2022-07-22 08:47:49 703:调用了UserService的doSome()方法
        2022-07-22 08:47:49 714:用户尝试进行登录,验证失败*/
    }
}

🥅File类的理解

java.io.File

(1)File类和四大家族没有关系,所以File类不能完成文件的读和写。
(2)File对象代表什么?文件和目录路径名的抽象表示形式。
        C:\Drivers 这是一个File对象
        C:\Drivers\Lan\Realtek\Readme.txt 也是File对象。
一个File对象有可能对应的是目录,也可能是文件;File只是一个路径名的抽象表示形式;不能通过File完成文件的读和写!

1.常用方法1

(1)exists()方法判断当前文件是否存在。

(2)creatNewFile()方法:以文件的形式创建出来。

(3)mkdir()方法:以目录的形式创建出来;创建多重目录mkdirs()方法

(4)获取当前文件的父路径

方法1:使用getParent(),返回的是一个String。
方法2:使用getParentFile(),返回的是一个File;和上面效果是一样的。

(5)getAbsolutePath()方法:获取当前文件的绝对路径!

package com.bjpowernode.java.io;

import java.io.File;

public class FileTest01 {
    public static void main(String[] args) throws Exception {
        // 创建File对象
        File f1 = new File("D:\\file");
        // 1、判断当前文件是否存在;exists()方法
        System.out.println(f1.exists()); // false

        // 2、如果D:\file不存在,则以文件的形式创建出来;createNewFile()方法
        if (!f1.exists()) {
            f1.createNewFile();
        }

        // 3、如果D:\file不存在,则以目录的形式创建出来;mkdir()方法
        if (!f1.exists()) {
            f1.mkdir();
        }

        // 4、创建多重目录;mkdirs()方法
        File f2 = new File("D:/a/b/c/d");
        if (!f2.exists()) {
            f2.mkdirs();
        }

        // 5、获取当前文件的父路径
        File f3 = new File("D:\\python学习\\PyCharm Community Edition 2021.2.2");
        // 第一种:使用getParent(),返回的是一个String
        String parentPath = f3.getParent();
        System.out.println(parentPath); // D:\python学习
        // 第二种:使用getParentFile(),返回的是一个File;效果是一样的
        File parentFile = f3.getParentFile();
        System.out.println(parentFile); // D:\python学习

        // 6、获取当前文件的绝对路径
        File f4 = new File("file");
        System.out.println(f4.getAbsolutePath()); // C:\Users\86177\IdeaProjects\JavaSe1\file

    }
}

2.常用方法2

(1)getName():获取当前文件的名字

(2)isDirectory()判断是否是一个目录

(3)isFile()判断是否是一个文件

(4)lastModified()获取文件最后一次修改时间;单位是毫秒数,返回long型

(5)length()获取文件大小,单位是字节

package com.bjpowernode.java.io;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;

public class FileTest02 {
    public static void main(String[] args) {
        File  f1 = new File("C:\\Java学习\\javaSE学习\\2.1JavaSE进阶笔记\\javase\\Copy02.java");
        // 1、获取文件名,getName()方法
        System.out.println("文件名:"+f1.getName()); // 文件名:Copy02.java

        // 2、判断是否是一个目录,isDirectory()方法
        System.out.println(f1.isDirectory()); // false

        // 3、判断是否是一个文件,isFile()方法
        System.out.println(f1.isFile()); // true

        // 4、获取文件最后一次修改时间,lastModified()方法
        // 得到的是毫秒数
        long modifytTime = f1.lastModified();
        // 将总毫秒数转换成日期
        Date date = new Date(modifytTime);
        // 格式化
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
        System.out.println(sdf.format(date)); //2020-03-11 14:35:46 154

        // 5、获取文件大小,length()方法
        System.out.println(f1.length()); //1490 字节
        
    }
}

3.listFiles方法

File中的listFiles方法:获取当前目录下所有的子文件(目录和普通文本文件)返回的是一个File[]数组

package com.bjpowernode.java.io;

import java.io.File;

public class FileTest03 {
    public static void main(String[] args) {
        File f = new File("C:\\Java学习\\javaSE学习\\2.1JavaSE进阶笔记\\javase\\chapter15\\src");
        // 调用listFiles()方法,返回的是一个File[]数组
        File[] files = f.listFiles();
        // 用增强for循环打印
        for(File file :files){
            System.out.println(file.getAbsolutePath()); // 获取所有子目录的绝对路径
            System.out.println(file.getName()); //获取所有子目录的文件名
        }

    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由半码博客整理,本文链接:https://www.bmabk.com/index.php/post/128475.html

(0)

相关推荐

发表回复

登录后才能评论
半码博客——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!