Java IO(File、字节输入输出流、字符输入输出流、打印流)附带相关面试题

简介: 1.File类,2.字节输入输出流(InputStream Outputstream),3.Writer与Reader字符输入输出流,4.打印流



1.File类

file类专门用于管理file文件的,比如文件的创建,删除,修改名称等等

以下是File类的常用方法:

方法 描述
exists() 判断文件或目录是否存在
canRead() 判断文件是否可读
canWrite() 判断文件是否可写
isFile() 判断路径是否表示一个文件
isDirectory() 判断路径是否表示一个目录
getName() 获取文件或目录的名称
getParent() 获取文件或目录的父级路径
getPath() 获取文件或目录的路径
isAbsolute() 判断路径是否为绝对路径
lastModified() 获取文件或目录的最后修改时间
length() 获取文件的大小
mkdir() 创建目录
mkdirs() 创建目录及其父目录
createNewFile() 创建新文件
delete() 删除文件或目录
renameTo() 重命名文件或目录
list() 返回目录下的文件和目录列表
listFiles() 返回目录下的文件和目录数组
getAbsolutePath() 获取文件或目录的绝对路径

文件路径需要掌握File.separator分隔符相当于"\\",为什么要有这个东西呢?因为在不同的操作系统中路径的分隔符并不一样,由此出现File.separator,会根据自己的系统自动转换相应的分隔符

1.使用案例:在一个路径上,如果存在一个文件java.txt,则将其删除,如果不存在则创建一个文件java.txt,再将其名字改为java.html并且输出上次的修改日期

package Example1605;
import java.io.File;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
public class javaDemo {
    public static void main(String[] args)throws Exception {
        File file = new File("E:"+File.separator+"jiawa"+File.separator+"java.txt");
//        判断文件是否存在
        if (file.exists()){
            file.delete();
        }else {
//            创建文件
            file.createNewFile();
//            实现文件改名
            String newName = file.getName().substring(0,file.getName().lastIndexOf('.'))+".html";
            File newFile = new File(file.getParentFile(),newName);
            file.renameTo(newFile);
//            上次修改日期
            System.out.println(new Date(file.lastModified()));
        }
    }
}

image.gif

image.gif编辑

2.通过递归实现输出C盘所有文件内容

package Example1601;
import java.io.File;
public class javaDemo {
    public static void main(String[] args) {
        int count = 0;
       File file =  new File("C:"+ File.separator);
       list(file,count);
        System.out.println(count);
    }
    public static void list(File file,int count){
//        判断是否目录如果是则深入目录
        if (file.isDirectory()){
            File result[] = file.listFiles();
//            判断目录里面是否有内容没有就跳过,有则继续深入
            if (result!=null){
                for (int i=0;i< result.length;i++){
                    list(result[i],count++);
                }
            }
        }
    }
}

image.gif

*面试题Files的常用方法都有哪些?

exist、createFile、createDirectory、write、read、copy、size、delete、move


2.字节输入输出流(InputStream Outputstream)

字节输入输出流的最基本单位是byte字节,注意InputStream和OutputStream都是抽象类,所以实例化对象分别是其子类FileInputStream(File file)与FileOutputStream(File file)

首先介绍OutoutStream字节输出流的常用方法:

方法 描述
write(byte[] buffer) 将byte数组中的数据写入输出流
write(byte[] buffer, int off, int len) 将byte数组中指定范围的数据写入输出流
write(int b) 将单个字节写入输出流
flush() 刷新输出流,确保所有缓冲区中的数据都被写出
close() 关闭输出流,并释放相关资源

InputStream的常用方法:

方法 描述
read() 读取输入流中的下一个字节
read(byte[] buffer) 将输入流中的数据读入到byte数组中
read(byte[] buffer, int off, int len) 将输入流中的数据读入到指定范围的byte数组中
skip(long n) 跳过并丢弃输入流中的n个字节
available() 返回可以从输入流中读取(或跳过)的字节数
close() 关闭输入流,并释放相关资源

案例代码:

实现在java.txt中通过OutputStream的wirte函数实现第一次覆盖内容实现输入Hello,第二次实现追加在Hello后面加入World

package Example1603;
import java.io.*;
import java.nio.charset.StandardCharsets;
public class javaDemo {
    public static void main(String[] args)throws Exception {
//        确保路径有效可以对其进行判定此处暂略
        File file =  new File("E:"+File.separator+"jiawa"+File.separator+"java.txt");
//        正常情况下
        OutputStream out = new FileOutputStream(file);
        out.write("Hello".getBytes(StandardCharsets.UTF_8));
        out.close();
//        通过构造方法设置true实现文件内容追加
        OutputStream outer = new FileOutputStream(file,true);
        outer.write("World".getBytes(StandardCharsets.UTF_8));
        outer.close();
//        输出文件内容
        InputStream input = new FileInputStream(file);
        byte[] data = new byte[1024];
        int len =  input.read(data);
        System.out.println(new String(data,0,len));
    }
}

image.gif

image.gif编辑

注意在创建实例化对象执行完函数后都要进行close();除非使用AutoCloseable接口

案例2:在刚才基础上读取时候跳过Hello

package Example1604;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
public class javaDemo {
    public static void main(String[] args)throws Exception {
        File file =  new File("E:"+File.separator+"jiawa"+File.separator+"java.txt");
        InputStream input = new FileInputStream(file);
        byte[] data =new byte[1024];
        input.skip(5);
        int len = input.read(data);
        System.out.println(new String(data,0,len));
        input.close();
    }
}

image.gif


3.Writer与Reader字符输入输出流

1.字符输入流与字节输入流有什么区别:

    1. 数据单位:字节流以字节为单位进行输入和输出,而字符流以字符为单位进行输入和输出。字符流可以直接处理Unicode字符,而字节流需要通过字符编码和解码来处理文本数据。
    2. 编码支持:字符流默认使用平台默认的字符编码(如UTF-8),并提供了更多的字符编码支持(如UTF-16、ISO-8859-1等)。字节流不关心编码,只是原样传输字节数据。
    3. 数据处理:字符流提供了更高级别的数据处理功能,能够方便地读取和写入文本数据,包括按行读取、字符缓冲等操作。字节流主要用于二进制数据的读写,处理相对底层。
    4. 效率:由于字符流需要进行字符编码和解码,所以在处理大量数据时可能会比字节流略慢。对于文本数据的处理,字符流的效率通常比较高。

    综上所述,字符流更适合处理文本数据,提供了更多的字符编码支持和便捷的高级功能;而字节流适用于处理二进制数据,更为底层和灵活。选择使用哪种流类型取决于具体的输入/输出需求和数据类型。

    2.Writer与Reader也都是抽象类,所以实例化的时候需要向上转型为其子类,FileWriter与FileReader

    Writer的常用方法:

    方法 描述
    write(int c) 将指定字符写入输出流
    write(char[] cbuf) 将字符数组的所有字符写入输出流
    write(String str) 将字符串中的所有字符写入输出流
    write(String str, int off, int len) 将字符串中指定范围的字符写入输出流
    append(CharSequence csq) 将指定的字符序列追加到输出流
    append(CharSequence csq, int start, int end) 将指定范围的字符序列追加到输出流
    flush() 刷新输出流,将缓冲区的数据写入目标设备
    close() 关闭输出流,并释放相关资源

    Reader的常用方法:

    方法 描述
    read() 读取单个字符,返回读取的字符的ASCII码值或-1(如果已达到流的末尾)
    read(char[] cbuf) 将字符读入数组,并返回读取的字符数
    read(char[] cbuf, int off, int len) 将字符读入数组的指定范围,并返回读取的字符数
    read(CharBuffer target) 将字符读入CharBuffer对象中,并返回读取的字符数
    skip(long n) 跳过n个字符的读取
    ready() 判断是否可以读取(准备读取)
    mark(int readAheadLimit) 在当前位置设置一个标记,以供稍后的reset()方法使用
    reset() 将位置重置为最近的标记位置
    close() 关闭输入流,并释放相关资源

    案例代码1:

    package Example1606;
    import java.io.File;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.io.Writer;
    public class javaDemo {
        public static void main(String[] args)throws Exception {
            File file = new File("E:"+File.separator+"jiawa"+File.separator+"java.txt");
            try{
                if (file.exists()){
                    Writer out = new FileWriter(file);
                    out.write("大家好,我系渣渣辉");
    //                Witer的追加是通过函数apend()
                    out.append(",其实我不系了啦");
                    out.close();
                }
            }catch (IOException e){
                e.printStackTrace();
            }
        }
    }

    image.gif

    image.gif编辑

    案例代码2:

    package Example1607;
    import java.io.File;
    import java.io.FileReader;
    import java.io.IOException;
    import java.io.Reader;
    public class javaDemo {
        public static void main(String[] args) {
            File file =new File("E:"+File.separator+"jiawa"+File.separator+"java.txt");
            try {
                Reader read = new FileReader(file);
                char data[] =new char[1024];
                int len = read.read(data);
                System.out.println(new String(data,0,len));
                read.close();
            }catch (IOException e){
                e.printStackTrace();
            }
        }
    }

    image.gif

    面试题java 中 IO 流分为几种?

    (1)按流划分,可以分为输入流和输出流;

    (2)按单位划分,可以分为字节流和字符流;

    字节流:inputStream、outputStream;

    字符流:reader、writer


    4.打印流

    虽然说io中对数据的输出可以通过OutputStream与Writer,但是两者都有一定的限制,比如OutputStream只允许输出字节数据,Writer只允许输出字符数据和字符串数据,在实际的开发过程会有多种数据类型的输出就引出了PrintWriter

    下面介绍PrintWriter的常用方法:

    void print(boolean x) 将boolean值打印到输出流。
    void print(char x) 将字符打印到输出流。
    void print(int x) 将整数打印到输出流。
    void print(long x) 将长整数打印到输出流。
    void print(float x) 将浮点数打印到输出流。
    void print(double x) 将双精度浮点数打印到输出流。
    void print(char[] x) 将字符数组打印到输出流。
    void print(String x) 将字符串打印到输出流。
    void println() 打印一个换行符。
    void println(boolean x) 打印boolean值,并在结尾添加换行符。
    void println(char x) 打印字符,并在结尾添加换行符。
    void println(int x) 打印整数,并在结尾添加换行符。
    void println(long x) 打印长整数,并在结尾添加换行符。
    void println(float x) 打印浮点数,并在结尾添加换行符。
    void println(double x) 打印双精度浮点数,并在结尾添加换行符。
    void println(char[] x) 打印字符数组,并在结尾添加换行符。
    void println(String x) 打印字符串,并在结尾添加换行符。
    void format(String format, Object... args) 使用指定格式将参数写入输出流。
    void write(char[] buf, int off, int len) 将字符数组的一部分写入输出流。
    void flush() 刷新输出流,即将缓冲区的内容写入目标设备。
    void close() 关闭输出流,释放相关资源。

    1.通过打印一个print.txt内容为:

    姓名:黄小龙

    年龄15

    案例代码:

    package Example08;
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.PrintWriter;
    public class javaDemo {
        public static void main(String[] args) {
            File file =  new File("E:"+File.separator+"jiawa"+File.separator+"print.txt");
            if (!file.exists()){
                try {
                    file.createNewFile();
                    PrintWriter w = new PrintWriter(new FileOutputStream(file));
                    w.println("姓名:黄小龙");
                    w.print("年龄");
                    w.println(15);
    //                释放资源
                    w.close();
                }catch (IOException e){
                    e.printStackTrace();
                }
            }
        }
    }

    image.gif

    image.gif编辑

    构造方法PrintWriter(File file)与PrintWriter(FileOutputStream out)有什么区别:

    `PrintWriter(File file)` 和 `PrintWriter(FileOutputStream out)` 都创建了一个新的 `PrintWriter` 对象,用于写入字符流。它们的区别在于它们的构造函数参数类型不同。

    `PrintWriter(File file)` 构造函数接受一个 `File` 对象作为参数,表示要写入的文件。当您使用这个构造函数创建一个 `PrintWriter` 对象时,它将自动为您创建一个 `FileOutputStream` 对象并将其与您指定的文件关联。这意味着您可以直接向 `PrintWriter` 对象写入字符,而不必手动创建 `FileOutputStream` 对象。

    例如,以下代码使用 `PrintWriter(File file)` 构造函数创建一个新的 `PrintWriter` 对象,并将其用于向 `example.txt` 文件写入字符:

    ```java

    File file = new File("example.txt");

    PrintWriter writer = new PrintWriter(file);

    writer.println("Hello, world!");

    writer.close();

    ```

    相比之下,`PrintWriter(FileOutputStream out)` 构造函数接受一个 `FileOutputStream` 对象作为参数,表示要与该对象关联的输出流。如果您已经有一个 `FileOutputStream` 对象,并且希望将其用作 `PrintWriter` 对象的输出流,可以使用这个构造函数。

    例如,以下代码创建一个新的 `FileOutputStream` 对象,并将其用作 `PrintWriter` 对象的输出流:

    ```java

    FileOutputStream outputStream = new FileOutputStream("example.txt");

    PrintWriter writer = new PrintWriter(outputStream);

    writer.println("Hello, world!");

    writer.close();

    ```

    总之,这两种构造函数都可以用于创建一个 `PrintWriter` 对象,但是它们的参数类型不同,并且在用法上略有不同。


    目录
    相关文章
    |
    29天前
    |
    NoSQL 中间件 Java
    字节面试:聊聊 CAP 定理?哪些中间件是AP? 哪些是CP? 说说 为什么?
    45岁老架构师尼恩在其读者交流群中分享了关于CAP定理的重要面试题及其解析,包括CAP定理的基本概念、CAP三要素之间的关系,以及如何在分布式系统设计中权衡一致性和可用性。文章还详细分析了几种常见中间件(如Redis Cluster、Zookeeper、MongoDB、Cassandra、Eureka、Nacos)的CAP特性,并提供了高端面试技巧,帮助读者在面试中脱颖而出。尼恩还推荐了其团队编写的《尼恩Java面试宝典PDF》等资料,助力求职者准备面试,提升技术水平。
    |
    2月前
    |
    Arthas Kubernetes Java
    字节面试:CPU被打满了,CPU100%,如何处理?
    尼恩,一位拥有20多年经验的老架构师,针对近期读者在一线互联网企业面试中遇到的CPU 100%和红包架构等问题,进行了系统化梳理。文章详细解析了CPU 100%的三大类型问题(业务类、并发类、内存类)及其九种常见场景,提供了使用jstack和arthas两大工具定位问题的具体步骤,并分享了解决死锁问题的实战案例。尼恩还强调了面试时应先考虑回滚版本,再使用工具定位问题的重要性。此外,尼恩提供了丰富的技术资料,如《尼恩Java面试宝典》等,帮助读者提升技术水平,轻松应对面试挑战。
    字节面试:CPU被打满了,CPU100%,如何处理?
    |
    2月前
    |
    Java API 对象存储
    JVM进阶调优系列(2)字节面试:JVM内存区域怎么划分,分别有什么用?
    本文详细解析了JVM类加载过程的关键步骤,包括加载验证、准备、解析和初始化等阶段,并介绍了元数据区、程序计数器、虚拟机栈、堆内存及本地方法栈的作用。通过本文,读者可以深入了解JVM的工作原理,理解类加载器的类型及其机制,并掌握类加载过程中各阶段的具体操作。
    |
    4月前
    |
    Java
    Java——编码GBK的不可映射字符
    Java——编码GBK的不可映射字符
    54 1
    |
    4月前
    |
    存储 Java Apache
    |
    5月前
    |
    SQL Java Unix
    Android经典面试题之Java中获取时间戳的方式有哪些?有什么区别?
    在Java中获取时间戳有多种方式,包括`System.currentTimeMillis()`(毫秒级,适用于日志和计时)、`System.nanoTime()`(纳秒级,高精度计时)、`Instant.now().toEpochMilli()`(毫秒级,ISO-8601标准)和`Instant.now().getEpochSecond()`(秒级)。`Timestamp.valueOf(LocalDateTime.now()).getTime()`适用于数据库操作。选择方法取决于精度、用途和时间起点的需求。
    76 3
    |
    5月前
    |
    NoSQL Java 应用服务中间件
    Java高级面试题
    Java高级面试题
    127 1
    |
    5月前
    |
    网络协议 安全 前端开发
    java面试题
    java面试题
    |
    4月前
    |
    存储 Java
    【IO面试题 四】、介绍一下Java的序列化与反序列化
    Java的序列化与反序列化允许对象通过实现Serializable接口转换成字节序列并存储或传输,之后可以通过ObjectInputStream和ObjectOutputStream的方法将这些字节序列恢复成对象。