java.io 包下的类有哪些 + 面试题
java.io 包下的类有哪些 + 面试题
IO 介绍
IO 是 Input/Output 的缩写,它是基于流模型实现的,比如操作文件时使用输入流和输出流来写入和读取文件等。
IO 分类
传统的 IO,按照流类型我们可以分为:
- 字符流
- 字节流
其中,字符流包括 Reader、Writer;字节流包括 InputStream、OutputStream。
传统 IO 的类关系图,如下图所示:
IO 使用
了解了 IO 之间的关系,下面我们正式进入实战环节,分别来看字符流(Reader、Writer)和字节流(InputStream、OutputStream)的使用。
① Writer 使用
Writer 可用来写入文件,请参考以下代码:
// 给指定目录下的文件追加信息
Writer writer = new FileWriter("d:\\\\io.txt",true);
writer.append("老王");
writer.close();
这几行简单的代码就可以实现把信息 老王
追加到 d:\\io.txt
的文件下,参数二表示的是覆盖文字还是追加文字。
② Reader 使用
Reader 可用来读取文件,请参考以下代码:
Reader reader = new FileReader("d:\\\\io.txt");
BufferedReader bufferedReader = new BufferedReader(reader);
String str = null;
// 逐行读取信息
while (null != (str = bufferedReader.readLine())) {
System.out.println(str);
}
bufferedReader.close();
reader.close();
③ InputStream 使用
InputStream 可用来读取文件,请参考以下代码:
InputStream inputStream = new FileInputStream(new File("d:\\\\io.txt"));
byte[] bytes = new byte[inputStream.available()];
// 读取到 byte 数组
inputStream.read(bytes);
// 内容转换为字符串
String content = new String(bytes, "UTF-8");
inputStream.close();
④ OutputStream 使用
OutputStream 可用来写入文件,请参考以下代码:
OutputStream outputStream = new FileOutputStream(new File("d:\\\\io.txt"),true);
outputStream.write("老王".getBytes());
outputStream.close();
NIO 介绍
上面讲的内容都是 java.io 包下的知识点,但随着 Java 的不断发展,在 Java 1.4 时新的 IO 包出现了 java.nio,NIO(Non-Blocking IO)的出现解决了传统 IO,也就是我们经常说的 BIO(Blocking IO)同步阻塞的问题,NIO 提供了 Channel、Selector 和 Buffer 等概念,可以实现多路复用和同步非阻塞 IO 操作,从而大大提升了 IO 操作的性能。
了解了同步和阻塞的含义,下面来看 NIO 的具体使用,请参考以下代码:
int port = 6666;
new Thread(new Runnable() {
@Override
public void run() {
try (Selector selector = Selector.open();
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();) {
serverSocketChannel.bind(new InetSocketAddress(InetAddress.getLocalHost(), port));
serverSocketChannel.configureBlocking(false);
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
while (true) {
selector.select(); // 阻塞等待就绪的 Channel
Set<SelectionKey> selectionKeys = selector.selectedKeys();
Iterator<SelectionKey> iterator = selectionKeys.iterator();
while (iterator.hasNext()) {
SelectionKey key = iterator.next();
try (SocketChannel channel = ((ServerSocketChannel) key.channel()).accept()) {
channel.write(Charset.defaultCharset().encode("老王,你好~"));
}
iterator.remove();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
// Socket 客户端 1(接收信息并打印)
try (Socket cSocket = new Socket(InetAddress.getLocalHost(), port)) {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(cSocket.getInputStream()));
bufferedReader.lines().forEach(s -> System.out.println("客户端 1 打印:" + s));
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
// Socket 客户端 2(接收信息并打印)
try (Socket cSocket = new Socket(InetAddress.getLocalHost(), port)) {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(cSocket.getInputStream()));
bufferedReader.lines().forEach(s -> System.out.println("客户端 2 打印:" + s));
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
以上代码创建了两个 Socket 客户端,用于收取和打印服务器端的消息。
其中,服务器端通过 SelectionKey(选择键)获取到 SocketChannel(通道),而通道都注册到 Selector(选择器)上,所有的客户端都可以获得对应的通道,而不是所有客户端都排队堵塞等待一个服务器连接,这样就实现多路复用的效果了。多路指的是多个通道(SocketChannel),而复用指的是一个服务器端连接重复被不同的客户端使用。
AIO 介绍
AIO(Asynchronous IO)是 NIO 的升级,也叫 NIO2,实现了异步非堵塞 IO ,异步 IO 的操作基于事件和回调机制。
AIO 实现简单的 Socket 服务器,代码如下:
int port = 8888;
new Thread(new Runnable() {
@Override
public void run() {
AsynchronousChannelGroup group = null;
try {
group = AsynchronousChannelGroup.withThreadPool(Executors.newFixedThreadPool(4));
AsynchronousServerSocketChannel server = AsynchronousServerSocketChannel.open(group).bind(new InetSocketAddress(InetAddress.getLocalHost(), port));
server.accept(null, new CompletionHandler<AsynchronousSocketChannel, AsynchronousServerSocketChannel>() {
@Override
public void completed(AsynchronousSocketChannel result, AsynchronousServerSocketChannel attachment) {
server.accept(null, this); // 接收下一个请求
try {
Future<Integer> f = result.write(Charset.defaultCharset().encode("Hi, 老王"));
f.get();
System.out.println("服务端发送时间:" + DateFormat.getDateTimeInstance().format(new Date()));
result.close();
} catch (InterruptedException | ExecutionException | IOException e) {
e.printStackTrace();
}
}
@Override
public void failed(Throwable exc, AsynchronousServerSocketChannel attachment) {
}
});
group.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
}).start();
// Socket 客户端
AsynchronousSocketChannel client = AsynchronousSocketChannel.open();
Future<Void> future = client.connect(new InetSocketAddress(InetAddress.getLocalHost(), port));
future.get();
ByteBuffer buffer = ByteBuffer.allocate(100);
client.read(buffer, null, new CompletionHandler<Integer, Void>() {
@Override
public void completed(Integer result, Void attachment) {
System.out.println("客户端打印:" + new String(buffer.array()));
}
@Override
public void failed(Throwable exc, Void attachment) {
exc.printStackTrace();
try {
client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
});
Thread.sleep(10 * 1000);
相关面试题
1.使用以下哪个方法来判断一个文件是否存在?
A:createFile
B:exists
C:read
D:exist
答:B
2.以下说法错误的是?
A:同步操作不一定会阻塞
B:异步操作不一定会阻塞
C:阻塞一定是同步操作
D:同步或异步都可能会阻塞
答:C
题目解析:异步操作也可能会阻塞,比如分布式集群消息同步,采用的就是异步阻塞的方式。
3.BIO、NIO、AIO 的区别是什么?
答:它们三者的区别如下。
- BIO 就是传统的 java.io 包,它是基于流模型实现的,交互的方式是同步、阻塞方式,也就是说在读入输入流或者输出流时,在读写动作完成之前,线程会一直阻塞在那里,它们之间的调用是可靠的线性顺序。它的优点就是代码比较简单、直观;缺点就是 IO 的效率和扩展性很低,容易成为应用性能瓶颈。
- NIO 是 Java 1.4 引入的 java.nio 包,提供了 Channel、Selector、Buffer 等新的抽象,可以构建多路复用的、同步非阻塞 IO 程序,同时提供了更接近操作系统底层高性能的数据操作方式。
- AIO 是 Java 1.7 之后引入的包,是 NIO 的升级版本,提供了异步非堵塞的 IO 操作方式,因此人们叫它 AIO(Asynchronous IO),异步 IO 是基于事件和回调机制实现的,也就是应用操作之后会直接返回,不会堵塞在那里,当后台处理完成,操作系统会通知相应的线程进行后续的操作。
简单来说 BIO 就是传统 IO 包,产生的最早;NIO 是对 BIO 的改进提供了多路复用的同步非阻塞 IO,而 AIO 是 NIO 的升级,提供了异步非阻塞 IO。
4.读取和写入文件最简洁的方式是什么?
答:使用 Java 7 提供的 Files 读取和写入文件是最简洁,请参考以下代码:
// 读取文件
byte[] bytes = Files.readAllBytes(Paths.get("d:\\\\io.txt"));
// 写入文件
Files.write(Paths.get("d:\\\\io.txt"), "追加内容".getBytes(), StandardOpenOption.APPEND);
读取和写入都是一行代码搞定,可以说很简洁了。
5.Files 常用方法都有哪些?
答:Files 是 Java 1.7 提供的,使得文件和文件夹的操作更加方便,它的常用方法有以下几个:
- Files. exists():检测文件路径是否存在
- Files. createFile():创建文件
- Files. createDirectory():创建文件夹
- Files. delete():删除一个文件或目录
- Files. copy():复制文件
- Files. move():移动文件
- Files. size():查看文件个数
- Files. read():读取文件
- Files. write():写入文件
6.FileInputStream 可以实现什么功能?
答:FileInputStream 可以实现文件的读取。
题目解析:因为 FileInputStream 和 FileOutputStream 很容易被记反,FileOutputStream 才是用来写入文件的,所以也经常被面试官问到。
7.不定项选择:为了提高读写性能,可以采用什么流?
A:InputStream
B:DataInputStream
C:BufferedReader
D:BufferedInputStream
E:OutputStream
F:BufferedOutputStream
答:D、F
题目解析:BufferedInputStream 是一种带缓存区的输入流,在读取字节数据时可以从底层流中一次性读取多个字节到缓存区,而不必每次都调用系统底层;同理,BufferedOutputStream 也是一种带缓冲区的输出流,通过缓冲区输出流,应用程序先把字节写入缓冲区,缓存区满后再调用操作系统底层,从而提高系统性能,而不必每次都去调用系统底层方法。
8.FileInputStream 和 BufferedInputStream 的区别是什么?
答:FileInputStream 在小文件读写时性能较好,而在大文件操作时使用 BufferedInputStream 更有优势。
9.以下这段代码运行在 Windwos 平台,执行的结果是?
Files.createFile(Paths.get("c:\\\\pf.txt"), PosixFilePermissions.asFileAttribute(
EnumSet.of(PosixFilePermission.OWNER_READ)));
A:在指定的盘符产生了对应的文件,文件只读
B:在指定的盘符产生了对应的文件,文件只写
C:在指定的盘符产生了对应的文件,文件可读写
D:程序报错
答:D
题目解析:本题目考察的是 Files.createFile 参数传递的问题,PosixFilePermissions 不支持 Windows,因此在 Windows 执行会报错 java.lang.UnsupportedOperationException: 'posix:permissions' not supported as initial attribute。
总结
在 Java 1.4 之前只有 BIO(Blocking IO)可供使用,也就是 java.io 包下的那些类,它的缺点是同步阻塞式运行的。随后在 Java 1.4 时,提供了 NIO(Non-Blocking IO)属于 BIO 的升级,提供了同步非阻塞的 IO 操作方式,它的重要组件是 Selector(选择器)、Channel(通道)、Buffer(高效数据容器)实现了多路复用的高效 IO 操作。而 AIO(Asynchronous IO)也叫 NIO 2.0,属于 NIO 的补充和升级,提供了异步非阻塞的 IO 操作。
还有另一个重要的知识点,是 Java 7.0 时新增的 Files 类,极大地提升了文件操作的便利性,比如读、写文件 Files.write()、Files.readAllBytes() 等,都是非常简便和实用的方法。
欢迎关注我的公众号,回复关键字“Java” ,将会有大礼相送!!! 祝各位面试成功!!!
%97%E5%8F%B7%E4%BA%8C%E7%BB%B4%E7%A0%81.png)
java.io 包下的类有哪些 + 面试题的更多相关文章
- java.io包下适配和装饰模式的使用
如java.io.LineNumberInputStream(deprecated),是装饰模式(decorate)的实现: 如java.io.OutputStreamWriter,是适配器模式(ad ...
- Java 扫描包下所有类(包括jar包)
package com.MyUtils.file; [java] view plain copy import java.io.File; import java.io.FileFilter; imp ...
- java IO包的其他类
DataInputStream 与 DataOutputStream 记事本默认会查编码表,可能会显示成这样 读取 ByteArrayInputStream 与 ByteArrayOutputStre ...
- java 查找指定包下的类
package com.jason.test; import java.io.File; import java.io.IOException; import java.io.UnsupportedE ...
- java io包File类
1.java io包File类, Java.io.File(File用于管理文件或目录: 所属套件:java.io)1)File对象,你只需在代码层次创建File对象,而不必关心计算机上真正是否存在对 ...
- List,Set,Map在java.util包下都是接口 List有两个实现类:ArrayList和LinkedList Set有两个实现类:HashSet和LinkedHashSet AbstractSet实现了Set
List,Set,Map在java.util包下都是接口 List有两个实现类:ArrayList和LinkedListSet有两个实现类:HashSet和LinkedHashSetAbstractS ...
- java.io包详细解说
转自:http://hzxdark.iteye.com/blog/40133 hzxdark的博客 我不知道各位是师弟师妹们学java时是怎样的,就我的刚学java时的感觉,java.io包是最让我感 ...
- java.io包中的字节流—— FilterInputStream和FilterOutputStream
接着上篇文章,本篇继续说java.io包中的字节流.按照前篇文章所说,java.io包中的字节流中的类关系有用到GoF<设计模式>中的装饰者模式,而这正体现在FilterInputStre ...
- Java:输入输出流 java.io包的层次结构
1.什么是IO Java中I/O操作主要是指使用Java进行输入,输出操作. Java所有的I/O机制都是基于数据流进行输入输出,这些数据流表示了字符或者字节数据的流动序列.Java的I/O流提供了读 ...
随机推荐
- Spring Security入门(基于SSM环境配置)
一.前期准备 配置SSM环境 二.不使用数据库进行权限控制 配置好SSM环境以后,配置SpringSecurity环境 添加security依赖 <dependency> <gr ...
- 还看不懂同事代码?快来补一波 Java 7 语法特性
前言 Java 平台自出现到目前为止,已经 20 多个年头了,这 20 多年间 Java 也一直作为最流行的程序设计语言之一,不断面临着其他新兴编程语言的挑战与冲击.Java 语言是一种静态强类型语言 ...
- 31.用python中的serial向串口发送和接收数据(案例一)
代码功能说明:1.向串口助手发送十六进制数据:0X01,0X03,0X00,0X00,0X00,0X01,0X84,0X0A: 2.用串口助手向代码发送数据,并将发送过来的数据保存在数据库中,按数据和 ...
- 条款03:尽可能使用const
目录 1. 总结 2. const对象 3. const函数返回值和函数参数 4. const成员函数 const成员函数的重要性 bitwise constness logical constnes ...
- 小白学Java:老师!泛型我懂了!
目录 小白学Java:老师!泛型我懂了! 泛型概述 定义泛型 泛型类的定义 泛型方法的定义 类型变量的限定 原生类型与向后兼容 通配泛型 非受限通配 受限通配 下限通配 泛型的擦除和限制 类型擦除 类 ...
- 【DPDK】【Multiprocess】一个dpdk多进程场景的坑
[前言] 这是一个隐藏了近3年的问题,理论上只要用到DPDK multiprocess场景的都会遇到这个问题,具体出不出问题只能说是看运气,即使不出问题也仍然是一个风险. [场景] 我先描述一下这个问 ...
- 你的应用安全吗? ——用Xray和Synk保驾护航
一.背景 在当下软件应用的开发过程当中,自研的内部代码所占的比例逐步地减少,开源的框架和共用库已经得到了广泛的引用.如下图所示,在一个Kubernetes部署的应用当中,我们自己开发代码所占的比例可能 ...
- C#实现的对文件的重命名
如下C#实现对文件的重命名的方法需要传入三个string类型的参数,分别是源文件的文件目录.目的文件目录和重命名的文件名称,实现代码如下: public ExecutionResult FileRen ...
- 数据可视化之Matplotlib的使用
1.什么是数据可视化 数据可视化在量化分析当中是一个非常关键的辅助工具,往往我们需要通过可视化技术,对我们的数据进行更清晰的展示,这样也能帮助我们理解交易.理解数据.通过数据的可视化也可以更快速的发现 ...
- 洛谷p1137 模拟退火
题目链接:https://www.luogu.org/problem/P1337 以x为原点,将力分解成横纵方向的力,每次退火时单独对答案的横纵坐标进行判断是否更新答案 #include<ios ...