Guava库学习:学习Guava Files系列(一)

原文地址:Guava库学习:学习Guava Files系列(一)

对程序开发人员来说,文件的读写是很重要的一项技能。但是令人惊讶的是,尽管Java提供了一个丰富而健壮的I/O库,进行一些基本的文件操作却显得很繁 琐。不过在Java 7中已经发生了一些改变,但那些使用Java 6的就不那么好运了。幸运的是,Guava做了一些我们期望I/O库做的事情,提供了一系列的工具,让我们能够更方便的进行I/O操作。本篇,我们就开始来学习如何使用Guava Files进行一些I/O操作。

尽管Java 7做了一些改进,并解决了一些Guava的小的问题,但我们发现Guava提供的工具在进行I/O操作时仍然非常有用。本Guava Files系列中,我们将要学习一下内容:

  • 使用Files类来执行那些基本的任务,比如:移动或复制文件,或读取文件内容到一个字符串集合
  • Closer类,提供了一种非常干净的方式,确保Closeable实例被正确的关闭
  • ByteSource 和 CharSource类,提供了不可变的输入流(Input)和读(Reader)
  • ByteSink 和 CharSink类,提供了不可变的输出流(Output)和写(Writer)
  • CharStreams和ByteStreams类,为读Readers、写Writers、输入流InputStreams、输出流OutputStreams 提供了一些静态的实用方法
  • BaseEncoding类,提供了编码和解码字节序列和ASCII字符的方法

    文件的复制

Files类提供了一些有用的方法来操作File对象,对Java开发人员来说,复制一个文件到另一个文件是件有挑战的工作。但是在Guava里,我们来看怎样通过Files类完成同样的工作:

@Test
public void testCopyFile() throws IOException {
    File original = new File("D:\\test.txt");
    File copy = new File("D:\\test2.txt");
    Files.copy(original, copy);
}

    文件的移动/重命名

同样,Java中移动文件也和复制一样繁琐。在Guava里,则非常的简单,代码如下:

@Test
public void testMoveFile() throws IOException {
    File original = new File("D:\\test.txt");
    File newFile = new File("D:\\test2.txt");
    Files.move(original, newFile);
}

    像字符串一样处理文件

有些时候我们需要操作或使用文件的字符串表示。Files类提供了一些方法,能够将文件读取到一个字符串集合,返回文件的第一行字符串,将一个完整的文件 的内容读入一个字符串。下面的例子,会介绍通过调用Files.readLines方法将文件读取到一个string集合中:

@Test
public void readFileIntoListOfStringsTest() throws IOException {
    File file = new File("D:\\test2.txt");
    List<String> expectedLines = Lists.newArrayList("hello world", "this is realfighter", "www.xx566.com");
    List<String> readLines = Files.readLines(file,
            Charsets.UTF_8);
    assertThat(expectedLines, is(readLines));
}

上面的例子中,我们使用了一个单元测试来确认从简单文件中读取的三行内容与我们的期望相同。每行内容中的换行符被删除,但其他空白的字符则保留。Files.readLines还可以接收LineProcessor实例作为额外的附加参数。每一行内容都参数LineProcessor.processLine方法,该方法返回一个布尔值。LineProcessor实例会持续读取文件中的行,直到文件读取完毕或LineProcessor.processLine方法返回false。假设,我们有包含如下信息的一个文件,是一些书本的信息:

"Savage Tom",Being A Great Cook,Acme Publishers,ISBN- 123456,29.99,1
"Smith Jeff",Art is Fun,Acme Publishers,ISBN-456789,19.99,2
"Vandeley Art",Be an Architect,Acme Publishers,ISBN- 234567,49.99,3
"Jones Fred",History of Football,Acme Publishers,ISBN- 345678,24.99,4
"Timpton Patty",Gardening My Way,Acme Publishers,ISBN- 4567891,34.99,5

我们想要抽取出每行数据中的书本的标题。为了完成这项任务,我们需要对LineProcessor接口做如下的实现:

class ToListLineProcessor implements LineProcessor<List<String>> {
    private static final Splitter splitter = Splitter.on(",");
    private List<String> bookTitles = Lists.newArrayList();
    private static final int TITLE_INDEX = 1;
    @Override
    public boolean processLine(String line) throws IOException {
        bookTitles.add(Iterables.get(splitter.split(line), TITLE_INDEX));
        return true;
    }
    @Override
    public List<String> getResult() {
        return bookTitles;
    }
}

在这里我们将使用逗号分隔每行,获取这本书的标题,是每行中的第二项,并将标题添加到一个字符串集合中。注意,我们使用了Iterables类,使用了静态的Iterables.get方法,来获取书本的标题。processLine方法总是返回true,因为我们需要获取所有文件中的书本名,下面是对LineProcessor实例的单元测试:

@Test
public void readLinesWithProcessor() throws Exception {
    File file = new File("D:\\test2.txt");
    List<String> expectedLines = Lists.newArrayList("Being A Great Cook", "Art is Fun",
            "Be an Architect", "History of Football", "Gardening My Way");
    List<String> readLines = Files.readLines(file, Charsets.UTF_8,
            new ToListLineProcessor());
    assertThat(expectedLines, is(readLines));
}

在这个例子中,我们简单的获取了读取了所有的输入,但是我们可以很容易的通过一些条件只获取n行或过滤一些数据。

    文件的哈希值

在Java中生成文件的哈希值似乎需要很多的代码操作,但在Guava中,它变得非常简单。Files类拥有一个hash方法,使用代码如下:

@Test
public void testFilesHashing() throws Exception{
    File file = new File("D:\\test2.txt");
    HashCode hashCode = Files.hash(file, Hashing.md5());
    System.out.println(hashCode);
}

上面的例子中,为了使用Files.hash方法,我们提供了File对象和HashFuction实例,我们使用了一个实现MD5算法的hash函数,并且方法返回一个HashCode对象。Hash函数将在下一个系列中介绍,敬请期待。

    文件写

当我们使用输入/输出流时,我们经常需要编写以下几步的代码:

  1. 打开输入/输出流。
  2. 将字节读入/读出。
  3. 读取完毕,确保所有的资源都在finally代码块中关闭。

当我们不得不一遍遍的重复这个过程,就很容易出错,并会使得代码越来越不清晰和难以维护。Files类为我们提供了方便,能够很容易的 在文件的写/追加数据或读取文件内容到字节数组。大部分那些我们需要特别关注的打开或关闭资源的代码,只需要简单的一行代码。

    文件写和追加数据

一个简单的文件的写和追加数据例子,代码如下:

@Test
public void appendingWritingToFileTest() throws IOException {
    File file = new File("D:\\test2.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));
}

在这个例子中,我们使用单元测试做了如下几件事情:

  1. 创建一个测试的文件,并确保JVM中不存在同名的文件
  2. 我们使用Files.write方法向文件写入一个字符,并确保写入成功
  3. 之后我们使用了Files.append方法追加了另一个字符到文件,并同样确认文件中已经存在追加的内容
  4. 最后,我们再次使用Files.write方法去覆盖文件,并确保文件已被覆盖

虽然这是一个简单的例子,但请注意,我们三次对文件进行写,我们不曾编写任何打开或关闭资源的代码。因此,我们的代码变得简单易读,更重要的是,不容易出现错误。

时间: 2024-12-17 17:44:03

Guava库学习:学习Guava Files系列(一)的相关文章

Guava库学习:学习Guava Files系列(二)

原文地址:Guava库学习:学习Guava Files系列(二) 上一篇,Guava库学习:学习Guava Files系列(一)中,我们简单的学习了使用Files进行文件的读写等常用操作,本篇我们继续进行Guava Files系列的学习.     InputSupplier 和 OutputSupplier Guava提供了 InputSupplier 和 OutputSupplier接口,用于提供InputStreams/Readers 或OutputStreams/Writers的处理.我们

Guava库学习:Guava 零碎知识

这将是Guava库学习系列的最后一篇,但是仍然包含许多零零碎碎的知识.虽然不可能覆盖所有Guava涉及的知识,但我们会竭尽所能.本篇将会介绍一些Guava中有用的工具,并不需要再开一个系列.本篇学习的一些工具可能并不会经常使用,但当你需要时,它是必不可少的.接下来,开始本篇的学习. 本篇,我们将主要学习以下内容:Hashing.BloomFilter.Optional.Throwable. Hashing散列类包含静态实用方法获取HashFunction实例 BloomFilter数据结构,用于

Guava库学习:学习Guava EventBus(二)EventBus 事件订阅示例

原文地址:Guava库学习:学习Guava EventBus(二)EventBus 事件订阅示例 上一篇Guava库学习:学习Guava EventBus(一)EventBus,我们简单的对Guava基于事件的编程进行了介绍,学习和了解了EventBus类的使用,本篇起,我们通过一系列的示例代码深入的学习EventBus类,本篇学习Guava EventBus(二)EventBus 事件订阅示例.     订阅Subscribe 首先,我们假定定义了如下所示的TradeAccountEvent类

Guava库学习:学习Guava Cache知识汇总

原文地址:Guava库学习:学习Guava Cache知识汇总 至此,我们结束了对Guava Cache 缓存机制的学习,在学习过程中,我们学习了如何简单的通过MapMaker创建最简单的ConcurrentMap缓存,我们也了解了缓存的高级特性,以及强大的LoadingCache,我们也探索和学习了CacheBuilder.CacheLoader这些核心的API,以及CacheStats.RemovalLitener等,下面对这些文章做一些汇总,方便以后的查阅和复习.     Guava库学习

Guava库学习:学习Guava Cache(六)CacheStats

原文地址:Guava库学习:学习Guava Cache(六)CacheStats 上一篇,Guava库学习:学习Guava Cache(五)CacheLoader 中, 我们学习了CacheLoader抽象类,主要是其中的from方法,接收一个Function或Supplier,返回一个CacheLoader实 例,至此,我们已经了解了如何创建一个强大的缓存机制,接下来,我们想要收集缓存执行或使用后的一些统计信息,又该怎么做呢?现在开始本篇,Guava Cache CacheStats的学习.

Guava学习笔记: guava集合之Multiset

Guava学习笔记: guava集合之Multiset Multiset是什么? Multiset看似是一个Set,但是实质上它不是一个Set,它没有继承Set接口,它继承的是Collection<E>接口,你可以向Multiset中添加重复的元素,Multiset会对添加的元素做一个计数. 它本质上是一个Set加一个元素计数器. Multiset使用示例: package cn.outofmemory.guava.collection; import com.google.common.ba

spring boot guava cache 缓存学习

http://blog.csdn.net/hy245120020/article/details/78065676 ************************************************************ spring boot guava cache 缓存学习 自定义key 自定义全局key过期时间,缓存个数 针对单个key自定义过期时间,缓存个数 引入依赖 <dependency> <groupId>org.springframework.boo

BOOST 库中filesyatem 库的学习

/*FileSyatem 库的学习 ------------------------------------------------------------------------------------------------------------库的使用方式 嵌入源码的形式: #define BOOST_SYSTEN_NO_LIB #define BOOST_FILESYSTEM_NO_LIB #include<boost\filesystem.hpp> ----------------

Robot framework--内置库xml学习(一)

Robot framework--内置库xml学习(一) 学习XML内置库,我认为需要掌握以下几个知识点: 第一:内置库的概念?有哪些内置库,大概都有什么关键字?有区分版本吗?跟RF版本有关么?为什么内置库有些需要import,有些不需要import? 第二:XML内置库使用的是python的哪个标准库?对这个标准库需要有哪些基本的了解? 第三:内置库是怎么构建起来的?基本关键字是否能灵活的使用? 第四:有时候可能需要稍微修改下内置库,比如增加一些关键字等,该怎么修改? 1.内置库的概念 内置库