Appearance
Java IO流面试题
1. IO流的基本概念
问题:什么是IO流?Java中的IO流有哪些分类?
答案:
- IO流:输入输出流,用于处理数据的输入和输出操作。
- 分类:
- 按流向:输入流和输出流。
- 按数据类型:字节流和字符流。
- 按功能:节点流和处理流。
2. 字节流和字符流的区别
问题:字节流和字符流有什么区别?
答案:
| 特性 | 字节流 | 字符流 |
|---|---|---|
| 处理单位 | 字节(8位) | 字符(16位) |
| 基类 | InputStream、OutputStream | Reader、Writer |
| 适用场景 | 二进制数据、图片、视频等 | 文本数据 |
| 缓冲区 | 无缓冲 | 有缓冲 |
3. 常见的IO流类
问题:Java中有哪些常见的IO流类?
答案:
- 字节流:
- InputStream:FileInputStream、ByteArrayInputStream、BufferedInputStream等。
- OutputStream:FileOutputStream、ByteArrayOutputStream、BufferedOutputStream等。
- 字符流:
- Reader:FileReader、StringReader、BufferedReader等。
- Writer:FileWriter、StringWriter、BufferedWriter等。
4. 文件操作
问题:如何进行文件操作?
答案:
java
// 创建文件
File file = new File("test.txt");
if (!file.exists()) {
file.createNewFile();
}
// 写入文件
try (FileWriter writer = new FileWriter(file)) {
writer.write("Hello, World!");
}
// 读取文件
try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
}
// 删除文件
file.delete();5. NIO
问题:什么是NIO?NIO和IO有什么区别?
答案:
- NIO(New IO):Java 1.4引入的新IO API,提供了非阻塞IO操作。
- 区别:
- IO是面向流的,NIO是面向缓冲区的。
- IO是阻塞的,NIO是非阻塞的。
- NIO提供了选择器(Selector)机制,可以管理多个通道。
6. NIO的核心组件
问题:NIO的核心组件有哪些?
答案:
- Buffer(缓冲区):用于存储数据的容器。
- Channel(通道):用于数据的传输通道。
- Selector(选择器):用于管理多个通道的选择器。
7. Buffer的使用
问题:如何使用Buffer?
答案:
java
// 创建Buffer
ByteBuffer buffer = ByteBuffer.allocate(1024);
// 写入数据
buffer.put("Hello, World!".getBytes());
// 切换到读模式
buffer.flip();
// 读取数据
while (buffer.hasRemaining()) {
byte b = buffer.get();
System.out.print((char) b);
}
// 清空Buffer
buffer.clear();8. Channel的使用
问题:如何使用Channel?
答案:
java
// 创建Channel
FileChannel channel = new FileInputStream("test.txt").getChannel();
// 创建Buffer
ByteBuffer buffer = ByteBuffer.allocate(1024);
// 读取数据
channel.read(buffer);
// 切换到读模式
buffer.flip();
// 读取数据
while (buffer.hasRemaining()) {
byte b = buffer.get();
System.out.print((char) b);
}
// 关闭Channel
channel.close();9. 序列化和反序列化
问题:什么是序列化和反序列化?如何实现?
答案:
- 序列化:将对象转换为字节序列的过程。
- 反序列化:将字节序列转换为对象的过程。
- 实现方式:
java
// 实现Serializable接口
public class Person implements Serializable {
private String name;
private int age;
// getters and setters
}
// 序列化
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("person.ser"))) {
Person person = new Person();
person.setName("John");
person.setAge(30);
oos.writeObject(person);
}
// 反序列化
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person.ser"))) {
Person person = (Person) ois.readObject();
System.out.println(person.getName()); // John
System.out.println(person.getAge()); // 30
}10. transient关键字
问题:transient关键字有什么作用?
答案: transient关键字用于标记不需要序列化的字段。
示例:
java
public class Person implements Serializable {
private String name;
private transient int age; // 不会被序列化
// getters and setters
}11. try-with-resources
问题:什么是try-with-resources?有什么作用?
答案:
- try-with-resources:Java 7引入的语法糖,用于自动关闭资源。
- 作用:简化资源管理,避免资源泄漏。
示例:
java
// 传统方式
FileInputStream fis = null;
try {
fis = new FileInputStream("test.txt");
// 使用资源
} finally {
if (fis != null) {
fis.close();
}
}
// try-with-resources方式
try (FileInputStream fis = new FileInputStream("test.txt")) {
// 使用资源
}12. Files类
问题:Files类提供了哪些常用方法?
答案:
- 文件操作:
Files.createFile(Path path):创建文件。Files.delete(Path path):删除文件。Files.copy(Path source, Path target):复制文件。Files.move(Path source, Path target):移动文件。
- 目录操作:
Files.createDirectory(Path dir):创建目录。Files.createDirectories(Path dir):创建多级目录。Files.list(Path dir):列出目录内容。Files.walk(Path start):遍历目录树。
13. Path类
问题:Path类提供了哪些常用方法?
答案:
Path getFileName():获取文件名。Path getParent():获取父路径。Path getRoot():获取根路径。int getNameCount():获取名称数量。Path getName(int index):获取指定索引的名称。Path normalize():规范化路径。Path toAbsolutePath():转换为绝对路径。Path resolve(Path other):解析路径。
14. 文件过滤器
问题:如何过滤文件?
答案:
java
// 使用FilenameFilter
File dir = new File(".");
String[] files = dir.list(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return name.endsWith(".txt");
}
});
// 使用FileFilter
File[] files = dir.listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
return pathname.isFile() && pathname.getName().endsWith(".txt");
}
});
// 使用Lambda表达式
String[] files = dir.list((dir, name) -> name.endsWith(".txt"));15. 文件监听
问题:如何监听文件变化?
答案:
java
// 创建WatchService
WatchService watchService = FileSystems.getDefault().newWatchService();
// 注册监听目录
Path dir = Paths.get(".");
dir.register(watchService, StandardWatchEventKinds.ENTRY_CREATE,
StandardWatchEventKinds.ENTRY_DELETE,
StandardWatchEventKinds.ENTRY_MODIFY);
// 监听事件
while (true) {
WatchKey key = watchService.take();
for (WatchEvent<?> event : key.pollEvents()) {
System.out.println(event.kind() + ": " + event.context());
}
key.reset();
}16. 内存映射文件
问题:什么是内存映射文件?如何使用?
答案:
- 内存映射文件:将文件映射到内存中,通过内存操作文件。
- 使用方式:
java
// 创建RandomAccessFile
RandomAccessFile file = new RandomAccessFile("test.txt", "rw");
// 创建MappedByteBuffer
MappedByteBuffer buffer = file.getChannel().map(FileChannel.MapMode.READ_WRITE, 0, file.length());
// 读写数据
buffer.put(0, (byte) 'H');
byte b = buffer.get(0);
// 关闭文件
file.close();17. 管道流
问题:什么是管道流?如何使用?
答案:
- 管道流:用于线程间通信的流。
- 使用方式:
java
// 创建管道流
PipedInputStream pis = new PipedInputStream();
PipedOutputStream pos = new PipedOutputStream(pis);
// 写入线程
new Thread(() -> {
try {
pos.write("Hello, World!".getBytes());
pos.close();
} catch (IOException e) {
e.printStackTrace();
}
}).start();
// 读取线程
new Thread(() -> {
try {
byte[] buffer = new byte[1024];
int len = pis.read(buffer);
System.out.println(new String(buffer, 0, len));
pis.close();
} catch (IOException e) {
e.printStackTrace();
}
}).start();18. 压缩流
问题:如何使用压缩流?
答案:
java
// 压缩文件
try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream("test.zip"))) {
ZipEntry entry = new ZipEntry("test.txt");
zos.putNextEntry(entry);
zos.write("Hello, World!".getBytes());
zos.closeEntry();
}
// 解压文件
try (ZipInputStream zis = new ZipInputStream(new FileInputStream("test.zip"))) {
ZipEntry entry;
while ((entry = zis.getNextEntry()) != null) {
System.out.println(entry.getName());
byte[] buffer = new byte[1024];
int len;
while ((len = zis.read(buffer)) > 0) {
System.out.write(buffer, 0, len);
}
zis.closeEntry();
}
}19. 字符编码
问题:什么是字符编码?常见的字符编码有哪些?
答案:
- 字符编码:将字符转换为字节的方式。
- 常见编码:
- ASCII:美国信息交换标准码,7位编码。
- ISO-8859-1:西欧字符编码,8位编码。
- GBK:中文字符编码,双字节编码。
- UTF-8:可变长度编码,支持所有Unicode字符。
- UTF-16:固定长度编码,支持所有Unicode字符。
20. 字符集
问题:Java中如何处理字符集?
答案:
java
// 获取默认字符集
Charset defaultCharset = Charset.defaultCharset();
System.out.println(defaultCharset); // UTF-8
// 获取指定字符集
Charset charset = Charset.forName("UTF-8");
// 编码
String str = "Hello, 世界";
byte[] bytes = str.getBytes(charset);
// 解码
String decoded = new String(bytes, charset);21. 缓冲流
问题:什么是缓冲流?有什么作用?
答案:
- 缓冲流:在内存中创建缓冲区,减少IO操作次数。
- 作用:提高IO性能。
示例:
java
// 不使用缓冲流
try (FileInputStream fis = new FileInputStream("test.txt")) {
int b;
while ((b = fis.read()) != -1) {
System.out.print((char) b);
}
}
// 使用缓冲流
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream("test.txt"))) {
int b;
while ((b = bis.read()) != -1) {
System.out.print((char) b);
}
}22. 数据流
问题:什么是数据流?如何使用?
答案:
- 数据流:用于读写基本数据类型的流。
- 使用方式:
java
// 写入数据
try (DataOutputStream dos = new DataOutputStream(new FileOutputStream("data.dat"))) {
dos.writeInt(123);
dos.writeDouble(3.14);
dos.writeUTF("Hello");
}
// 读取数据
try (DataInputStream dis = new DataInputStream(new FileInputStream("data.dat"))) {
int i = dis.readInt();
double d = dis.readDouble();
String s = dis.readUTF();
System.out.println(i); // 123
System.out.println(d); // 3.14
System.out.println(s); // Hello
}23. 对象流
问题:什么是对象流?如何使用?
答案:
- 对象流:用于读写对象的流。
- 使用方式:
java
// 写入对象
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("objects.dat"))) {
oos.writeObject("Hello");
oos.writeObject(123);
oos.writeObject(3.14);
}
// 读取对象
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("objects.dat"))) {
String s = (String) ois.readObject();
Integer i = (Integer) ois.readObject();
Double d = (Double) ois.readObject();
System.out.println(s); // Hello
System.out.println(i); // 123
System.out.println(d); // 3.14
}24. PrintStream和PrintWriter
问题:PrintStream和PrintWriter有什么区别?
答案:
- PrintStream:字节流,用于打印字节。
- PrintWriter:字符流,用于打印字符。
- 共同点:都提供了方便的打印方法。
示例:
java
// PrintStream
PrintStream ps = new PrintStream("output.txt");
ps.println("Hello, World!");
ps.close();
// PrintWriter
PrintWriter pw = new PrintWriter("output.txt");
pw.println("Hello, World!");
pw.close();25. 标准输入输出
问题:Java中的标准输入输出是什么?
答案:
- System.in:标准输入流,对应键盘输入。
- System.out:标准输出流,对应屏幕输出。
- System.err:标准错误流,对应屏幕输出。
示例:
java
// 读取标准输入
Scanner scanner = new Scanner(System.in);
System.out.print("请输入:");
String input = scanner.nextLine();
System.out.println("输入:" + input);
// 输出到标准输出
System.out.println("Hello, World!");
// 输出到标准错误
System.err.println("Error!");