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);
  }

其他的没啥特点,主要是介绍下LineProcessorByteProcessor

他们各自实现了再读取过程中的回调。

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();
  }

它是如何实现按行读取的?

  1. 回顾历史

JDK默认也为我们提供了按行读取的对象LineNumberReader,用起来也是比较ok的。

  1. guava io

guava为我们提供了LineReader,和它配合使用的是LineBuffer

两种模式实现的方式差不多,都是将数据读取进来,然后按照\n、\r来拆分数据。

results matching ""

    No results matching ""