1

总是记不住java的IO流用法?用N个问题教你掌握java IO流

 3 years ago
source link: https://my.oschina.net/u/4526289/blog/5029067
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

摘要:Java IO 体系看起来类很多,感觉很复杂,但其实是 IO 涉及的因素太多了。在设计 IO 相关的类时,编写者也不是从同一个方面考虑的,所以会给人一种很乱的感觉,并且还有设计模式的使用,更加难以使用这些 IO 类,所以特地对 Java 的 IO 做一个总结。

本文分享自华为云社区《总是记不住java的IO流用法?用N个问题教你掌握java IO流》,原文作者:breakDraw 。

Java IO 体系看起来类很多,感觉很复杂,但其实是 IO 涉及的因素太多了。在设计 IO 相关的类时,编写者也不是从同一个方面考虑的,所以会给人一种很乱的感觉,并且还有设计模式的使用,更加难以使用这些 IO 类,所以特地对 Java 的 IO 做一个总结。

文件API

Q: File类可以用来做目录操作吗?

A:可以。

File对象本身可以是目录。调用file.mkdirs()即可创建目录。

Q:直接调用file.delete()可以删除目录吗?

A:如果是文件或者空目录,可以直接删除。

但如果目录中有文件或者子目录,则必须递归删除。

    private static boolean deleteDir(File dir) {
        if (dir.isDirectory()) {
            String[] children = dir.list();
       //递归删除目录中的子目录下
            for (int i=0; i<children.length; i++) {
                boolean success = deleteDir(new File(dir, children[i]));
                if (!success) {
                    return false;
                }
            }
        }
        // 目录此时为空,可以删除
        return dir.delete();
    }

Q: 有哪些方法判断给定路径下文件是否存在?

1.File类的exists方法: file.exist(string)

File testFile = new File(testFilePath);
if(!testFile .exists()) {...}

2.File类的静态exist方法, File.exist(Path path)

Path filePath = Paths.get(testFilePath);
if (Files.exists(filePath) {...}

注意静态方法和非静态方法的区别

字节输入流InputStream

说一下以下这些特点对应哪些Input Stream类

  • 字节数组char[] 作为输入源的Input Stream类是——ByteArrayInputStream
  • 用文件作为输入源的Input Stream类是?——FileInputStream
  • 用字符串作为输入源的是?——StringBufferInputStream
  • 用于多线程之间管道通信的输入源是——PipeInputStream

Q: FilterInputStream是什么?

A: 用于装饰上面这些输入流的,可以叠加,每装饰一层就相当于增加了1个功能。

InputStream inputStream = new FilterInputStream(InputStream)

以下这些特点分别对应哪些FilterInputStream?

  • 装饰后,不仅可读字符串,还可读取例如int、long等java基本类型的是————DataInputStream
    DataInputStream里面会支持readInt、readLong等方法。
  • 装饰后,支持分批缓冲读取读取的是————BufferedInputStream
    创建BufferedInputStream时,我们会通过它的构造函数指定某个输入流为参数。BufferedInputStream会将该输入流数据分批读取,每次读取一部分到缓冲中;操作完缓冲中的这部分数据之后,再从输入流中读取下一部分的数据。
  • 其他:
    PushbackInputStream: 具有1个能回退上一个字节的缓冲区
    ObjectInputStream : 一般用于反序列化读入
    LineNumberInputStream: 可跟踪输入流中的行号

字节输出流OutputStream

OutputStream包含
ByteArrayOutputStream 输出到缓冲区
FileOutputStream 写到文件
PipedOutputStream 写入管道
FilterOutputStream

而FilterOutputStream 包含

  • DataOutputStream (可以out.writexxx各种类型的数据,writeDouble, writeUTF, reader也一样,可以读想要的数据类型)、
  • PringtStream (输出到文件用这个, 该类.println(str)即可写入文件)
  • BufferOutputString

FileOutputStream相关
Q:new FileOutputStream(name, true),这个构造里的true参数是做什么用的?

A:是否支持在文件末追加的意思。

v2-98ac51a771200bb735d7cad93791ed0e_720w.jpg

默认是false,指的是覆盖整个文本。

如果设置成true,会在要写入的文件后面追加本次写入的内容。

BufferOutputStream相关概念(其实是考缓冲区是否需要刷新之类的问题)

  • BufferOutputStream里的flush()方法是做什么的?
  • BufferOutputStream调用close后,会触发flush()来刷新缓冲区吗?
  • BufferOutputStream调用close可能会丢数据吗?
  • BufferOutputStream多次调用close会报错吗?
  • flush把缓冲区里的数据写入文件,并刷新缓冲区

v2-fed0b63312649259bbf2565a6dd51b7e_720w.jpg

  • close关闭此输出流并释放与此相关联的任何系统资源, 会调用flush,除了flushBuffer,还会调用父类的flush。
  • 不会丢数据,因为上面这条原因。
  • 多次调用不会报错。

v2-0aaf871c25f99d68d403dc0d239ce4ab_720w.jpg

Reader和Writer

Q: Reader/Writer和InputStream/OutputStream的区别?
A:

  • InputStream是表示 字节输入流 的所有类的超类
    Reader是用于读取 字符流 的抽象类
    InputStream提供的是字节流的读取,而非文本读取,这是和Reader类的根本区别。
    即用Reader读取出来的是char数组或者String ,使用InputStream读取出来的是byte数组。
  • Reader/Writer提供兼容Unicode、面向字符的IO功能,为了国际化
  • 用reader读取标准输入:
    BufferedReader bufr = new BufferedReader(new InputStreamReader(http://System.in));
  • 用Writer进行标准输出:
    BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));

设置编码:

InputStreamReader isr = new InputStreamReader(new FileInputStream(file), "UTF-8");  
BufferedReader read = new BufferedReader(isr);  

序列化问题

Q: 对某对象进行序列化时, 如何让里面某个敏感成员不被序列化?
A:

  • 方法一:可使用transient关键字处理那个敏感成员
  • 方法二:可以通过覆盖Serializable接口的writeObject和readObject来实现序列化, 但是方法签名必须是private void writeObject(ObjetOutputStream stream) throw IOException;
  • 方法三: 实现Externalizable接口,可自定义实现writeExternal以及readExternal方法

Q: Externalizable和Serializable哪个快?
A: Externalizable更快。

Q: Externalizable需要产生序列化ID吗?

A: 采用Externalizable无需产生序列化ID(serialVersionUID)~而Serializable接口则需要

https://blog.csdn.net/qq_26222859/article/details/50994113
https://blog.csdn.net/weixin_44117272/article/details/90767074

点击关注,第一时间了解华为云新鲜技术~


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK