jdk7 io操作小工具

时间:2022-12-24 09:14:16

参考文献:
Reading, Writing, and Creating Files
Java nio 学习笔记(一) Buffer(缓冲区)与Channel(通道)的相关知识
Java NIO系列教程(七) FileChannel
POSIX文件及目录管理

概述

通常情况下,我们会觉得使用java操作文件io比较繁琐,java7 Files类提供了一系列io小工具也许会简化一些操作,如下:

方法 适用场景
readAllBytes
readAllLines
适合小文件操作
newBufferedReader
newBufferedWriter
文本文件操作
newInputStream
newOutputStream
字节流操作,无需缓冲
newByteChannel
newFileChannel
使用通道和缓存进行底层流操作。底层特性,比如锁文件、内存映射操作

OpenOperations

写文件方法可以通过OpenOperations参数告诉系统当文件不存时候是报错还是新建、当前输出内容是追加还是覆盖等。下面是StandardOpenOptions所支持的文件操作方式:

枚举 说明
WRITE 简单的写文件,如果文件不存,会抛出异常。
TRUNCATE_EXISTING 清空已有文件的数据。一般和WRITE搭配使用。
CREATE 如果不存在就创建新文件。
CREATE_NEW 如果不存在就创建新文件,如果文件以及存在就抛出异常。
APPEND 想已有的文件中追加新数据,一般会和WRITE或者CREATE搭配使用。
DELETE_ON_CLOSE 关闭文件时候删除文件,这个一般结合临时文件使用。

小文件

Path path = Paths.get("data/ref.txt");
byte[] bytes = Files.readAllBytes(path);
List<String> list = Files.readAllLines(path, Charset.forName("utf-8"));

byte[] bytes = "测试".getBytes("utf-8");
Path path = Paths.get("data/ref2.txt");
Files.write(path, bytes, StandardOpenOption.CREATE, StandardOpenOption.APPEND);

文本文件

Path path = Paths.get("data/ref.txt");
try (BufferedReader bufferedReader = Files.newBufferedReader(path, Charset.forName("utf-8"))) {
String line = null;
while (null != (line = bufferedReader.readLine())) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}

普通I/O流

Path path = Paths.get("data/ref.txt");
// 打开文件流
try (InputStream in = Files.newInputStream(path)) {
// 如果需要缓存,可以使用BufferedInputStream再包装一层
} catch (IOException e) {
e.printStackTrace();
}

通道和字节缓冲

流I/O一次性读取一个字符(字节),通道I/O一次性读取的是一个缓冲区。ByteChannel提供了基本的读和写方法,它的子类SeekableByteChannel接口拓展了一些特性,比如读取和设置当前字节起始位置(用于随机访问)、截取文件内容(从后向前进行)、查询文件大小。FileChannel抽象类实现了该接口。

下面是读取字节位置和字节内容的例子:

// 默认是只读模式
try (SeekableByteChannel sbc = Files.newByteChannel(path)) {
ByteBuffer buf = ByteBuffer.allocate(3);
String encoding = System.getProperty("file.encoding");
System.out.println("encoding=" + encoding);
while (sbc.read(buf) > 0) {
// 当前字节起始位置
long position = sbc.position();
System.out.println("current position = " + position);
buf.rewind();
System.out.println(Charset.forName(encoding).decode(buf));
buf.flip();
}
} catch (IOException x) {
System.out.println("caught exception: " + x);
}

下面是获取文件大小和截取文件的例子:

// 默认是读取权限,如果需要截取,需要指明Operation为APPEND
try (SeekableByteChannel sbc = Files.newByteChannel(path, APPEND)) {
long size = sbc.size();
System.out.println("size of file = " + size + " bytes");
// 截取文件内容,如果要清空文件,请输入0
sbc.truncate(0);
} catch (IOException x) {
System.out.println("caught exception: " + x);
}

创建UNIX(POSIX)文件

Set<OpenOption> options = new HashSet<OpenOption>();
options.add(APPEND);
options.add(CREATE);

// 权限
Set<PosixFilePermission> perms =
PosixFilePermissions.fromString("rw-r-----");
FileAttribute<Set<PosixFilePermission>> attr =
PosixFilePermissions.asFileAttribute(perms);

String s = "Hello World! ";
byte data[] = s.getBytes();
ByteBuffer bb = ByteBuffer.wrap(data);

Path file = Paths.get("data/ref.txt");

try (SeekableByteChannel sbc =
Files.newByteChannel(file, options, attr)) {
sbc.write(bb);
} catch (IOException x) {
System.out.println("Exception thrown: " + x);
}

创建临时文件

有了createTempFile()方法,再配合DELETE_ON_CLOSE选项,轻松实现某些特定场景(比如从远程ftp读取大文件,缓存到本地磁盘,然后解释读取后删除)。

Path path = Paths.get("data");
try {
// 指定文件的目录
Path tempFile = Files.createTempFile(path, null, ".tmp");
System.out.format("The temporary file" + " has been created: %s%n", tempFile);
// 关闭后删除文件
try (InputStream in = Files.newInputStream(tempFile, DELETE_ON_CLOSE)) {

}
} catch (IOException x) {
System.err.format("IOException: %s%n", x);
}