除了java之外的其他几种jvm语言,例如kotlin,groovy,scala,在自带的库里,已经对文件以及io操作有了非常大的增强,而相比之下java的一些io方法相当原始,所以我们只能求助于类库。虽然自己写一些工具类并不费什么事,但是guava提供的io方法不仅效率高,而且抽象度也高,所以非常易学。
Files
files是一个工具类,估计很多人都写过类似的,但是guava是一个被无数人使用过的库,它的一些数值的考虑都是经过长期检验,相对来说对所有任务都比较高效的。
//复制文件
File original = new File("path/to/original");
File copy = new File("path/to/copy");
Files.copy(original, copy);
//移动文件
File original = new File("src/main/resources/copy.txt");
File newFile = new File("src/main/resources/newFile.txt");
try{
Files.move(original, newFile);
}catch (IOException e){
e.printStackTrace();
}
//快速读进io的每行 事实证明这个任务相当常见,以至于kotlin和groovy的标准库里都添加了这个方法
File file = new File("src/main/resources/lines.txt");
List<String> readLines = Files.readLines(file,Charsets.UTF_8);
//之后可以用java8的stream或者rxjava来进行字符串处理
//各种操作
File file = new File("src/test/resources/quote.txt");
file.deleteOnExit();
String hamletQuoteStart = "To be, or not to be";
Files.write(hamletQuoteStart,file, Charsets.UTF_8);
assertThat(Files.toString(file,Charsets.UTF_8),is(hamletQuoteStart));
String hamletQuoteEnd = ",that is the question";
Files.append(hamletQuoteEnd,file,Charsets.UTF_8);
assertThat(Files.toString(file, Charsets.UTF_8),
is(hamletQuoteStart + hamletQuoteEnd));
String overwrite = "Overwriting the file";
Files.write(overwrite, file, Charsets.UTF_8);
assertThat(Files.toString(file, Charsets.UTF_8),
is(overwrite));
Sources and Sinks
source sink基本上就是inputstream,outputstream,reader,writer的再包装,提供了更多实用的方法
//读字节
File f1 = new File("src/main/resources/sample.pdf");
byteSource = Files.asByteSource(f1);
//用bytesource一次读进所有byte
byte[] readBytes = byteSource.read();
assertThat(readBytes,is(Files.toByteArray(f1)));
//写字节
File dest = new File("src/test/resources/byteSink.pdf");
dest.deleteOnExit();
byteSink = Files.asByteSink(dest);
File file = new File("src/main/resources/sample.pdf");
byteSink.write(Files.toByteArray(file));
assertThat(Files.toByteArray(dest),is(Files.
toByteArray(file)));
//结合起来 拷贝文件
File dest = new
File("src/test/resources/sampleCompany.pdf");
dest.deleteOnExit();
File source = new File("src/main/resources/sample.pdf");
ByteSource byteSource = Files.asByteSource(source);
ByteSink byteSink = Files.asByteSink(dest);
byteSource.copyTo(byteSink);
assertThat(Files.toByteArray(dest),
is(Files.toByteArray(source)));
因为sink ,source代表的是抽象的流对象,所以不仅仅可以用于文件io,任何java里io覆盖到的地方都可以用guava的io对象代替
// 直接读进一个文件存为list,每行为一个元素
ImmutableList<String> lines = Files.asCharSource(file, Charsets.UTF_8)
.readLines();
// 记录不同单词在文件中的出现次数
Multiset<String> wordOccurrences = HashMultiset.create(
Splitter.on(CharMatcher.whitespace())
.trimResults()
.omitEmptyStrings()
.split(Files.asCharSource(file, Charsets.UTF_8).read()));
// 从网络流直接拷贝数据到文件中
Resources.asByteSource(url).copyTo(Files.asByteSink(file));
guava的这些方法是很方便,但是有时候使用一个工具类还是显得不太直观(没有面向对象的感觉,一直用静态方法,让我想起用c的时候),所以我推荐使用其他支持扩展方法的jvm语言,直接把这些方法集成进去,用起来更加方便。
使用guava IO对一个小项目进行重构。(这个项目本来是kotlin的,所以提升可能没有重构java项目那么大)
//首先这里是一段使用自己写的工具类将整个文件读进来的代码
val file = File(Config.CONFIGUE)
if (file.exists()) {
val result = FileTool.readFile(file)
val jsonObject = JSONObject(result)
_parseJson(jsonObject)
}
else
{
throw RuntimeException("can't find file")
}
//重构后 直接删除整个自己的工具类,转而用guava代替
val file = File(Config.CONFIGUE)
if (file.exists()) {
val result = Files.asCharSource(file,Charsets.UTF_8).read()
val jsonObject = JSONObject(result)
_parseJson(jsonObject)
}
else
{
throw RuntimeException("can't find file")
}
//使用kotlin的扩展方法再次重构
val file = File(Config.CONFIGUE)
if (file.exists()) {
val json=file.readString(Charsets.UTF_8).toJSON()
_parseJson(json)
}
else
{
throw RuntimeException("can't find file")
}
//如果用上guava 的Preconditions还可以更清爽
checkState(File(Config.CONFIGUE).exists(),"can't find configure file")
val json= File(Config.CONFIGUE).readString(Charsets.UTF_8).toJSON()
_parseJson(json)
//这里插一句题外话,我觉得大部分if条件不中就报错的代码形式,都可以改成前置的Preconditions,然后之后的代码就默认条件为真,这样看起来更加清爽
//像这种使用json 保存和读取配置文件的,还可以使用gson
第二个地方也一样
private fun _outputJson(jsonObject: JSONObject) {
FileTool.writeFile(File(Config.CONFIGUE),jsonObject.toString())
}
//重构后
private fun _outputJson(jsonObject: JSONObject) {Files.asCharSink(File(Config.CONFIGUE),Charsets.UTF_8).write(jsonObject.toString())
}
//因为是kt所以就不用null检查了
欢迎关注我的github
https://github.com/luckyCatMiao