IO模块-读写
写文件操作
以字节的方式写文件
public static void write(byte[] from, File to) throws IOException {
asByteSink(to).write(from);
}
@Deprecated
public static void write(CharSequence from, File to, Charset charset) throws IOException {
asCharSink(to, charset).write(from);
}
写文件IO模块提供了2个对外的方法,后面一个方法是废弃方法。
示例
File file = new File(getFilesDir(), "test.txt");
try {
Files.write("11122".getBytes(), file);
} catch (IOException e) {
e.printStackTrace();
}
默认的方法是直接覆盖的写入方式,如果需要追加,则不能直接调用write方法。需要改成:
Files.asByteSink(file, FileWriteMode.APPEND).write("3333".getBytes());
ByteSink
字节流写入对象,写文件实际操作的类,抽象的,又实现层自己传入自己的OutputStream
对象。
public abstract class ByteSink {
... ...
public abstract OutputStream openStream() throws IOException;
public void write(byte[] bytes) throws IOException {
checkNotNull(bytes);
Closer closer = Closer.create();
try {
OutputStream out = closer.register(openStream());
out.write(bytes);
out.flush(); // https://code.google.com/p/guava-libraries/issues/detail?id=1330
} catch (Throwable e) {
throw closer.rethrow(e);
} finally {
closer.close();
}
}
... ...
}
以字符的方式写文件
public static CharSink asCharSink(File file, Charset charset, FileWriteMode... modes) {
return asByteSink(file, modes).asCharSink(charset);
}
示例
private void write() {
File file = new File(getFilesDir(), "test.txt");
try {
Files.asCharSink(file, Charset.defaultCharset(), new FileWriteMode[]{FileWriteMode.APPEND}).write("4444");
} catch (IOException e) {
e.printStackTrace();
}
}
CharSink
public abstract class CharSink {
... ...
public abstract Writer openStream() throws IOException;
public void write(CharSequence charSequence) throws IOException {
checkNotNull(charSequence);
Closer closer = Closer.create();
try {
Writer out = closer.register(openStream());
out.append(charSequence);
out.flush(); // https://code.google.com/p/guava-libraries/issues/detail?id=1330
} catch (Throwable e) {
throw closer.rethrow(e);
} finally {
closer.close();
}
}
public void writeLines(Iterable<? extends CharSequence> lines, String lineSeparator)
throws IOException {
checkNotNull(lines);
checkNotNull(lineSeparator);
Closer closer = Closer.create();
try {
Writer out = closer.register(openBufferedStream());
for (CharSequence line : lines) {
out.append(line).append(lineSeparator);
}
out.flush();
} catch (Throwable e) {
throw closer.rethrow(e);
} finally {
closer.close();
}
}
}
读文件操作
@Deprecated
public static String readFirstLine(File file, Charset charset) throws IOException {
return asCharSource(file, charset).readFirstLine();
}
public static List<String> readLines(File file, Charset charset) throws IOException {
// don't use asCharSource(file, charset).readLines() because that returns
// an immutable list, which would change the behavior of this method
return asCharSource(file, charset)
.readLines(
new LineProcessor<List<String>>() {
final List<String> result = Lists.newArrayList();
@Override
public boolean processLine(String line) {
result.add(line);
return true;
}
@Override
public List<String> getResult() {
return result;
}
});
}
public static <T> T readLines(File file, Charset charset, LineProcessor<T> callback)
throws IOException {
return asCharSource(file, charset).readLines(callback);
}
@Deprecated
@CanIgnoreReturnValue // some processors won't return a useful result
public static <T> T readBytes(File file, ByteProcessor<T> processor) throws IOException {
return asByteSource(file).read(processor);
}
其他的没啥特点,主要是介绍下LineProcessor
和ByteProcessor
。
他们各自实现了再读取过程中的回调。
ByteProcessor
public static <T> T readBytes(InputStream input, ByteProcessor<T> processor) throws IOException {
checkNotNull(input);
checkNotNull(processor);
byte[] buf = createBuffer();
int read;
do {
read = input.read(buf);
} while (read != -1 && processor.processBytes(buf, 0, read));
return processor.getResult();
}
可以看到,ByteProcessor对每次缓冲读取,都会产生一个回调。
LineProcessor
public static <T> T readLines(Readable readable, LineProcessor<T> processor) throws IOException {
checkNotNull(readable);
checkNotNull(processor);
LineReader lineReader = new LineReader(readable);
String line;
while ((line = lineReader.readLine()) != null) {
if (!processor.processLine(line)) {
break;
}
}
return processor.getResult();
}
它是如何实现按行读取的?
- 回顾历史
JDK默认也为我们提供了按行读取的对象LineNumberReader
,用起来也是比较ok的。
- guava io
guava为我们提供了LineReader
,和它配合使用的是LineBuffer
。
两种模式实现的方式差不多,都是将数据读取进来,然后按照\n、\r来拆分数据。