0

我现在拥有的是使用 FileInputStream

int length = 1024*1024;
FileInputStream fs = new FileInputStream(new File("foo"));
fs.skip(offset);
byte[] buf = new byte[length];
int bufferSize = fs.read(buf, 0, length);
String s = new String(buf, 0, bufferSize);

我想知道如何通过在番石榴库中使用 ByteStreams 来实现相同的结果。

非常感谢!

4

3 回答 3

4

以下是使用 Guava 的方法:

byte[] bytes = Files.asByteSource(new File("foo"))
    .slice(offset, length)
    .read();
String s = new String(bytes, Charsets.US_ASCII);

您的代码存在一些问题(尽管它可能适用于文件,但不一定适用于任何类型的流):

fs.skip(offset);

这不一定会跳过所有offset字节。您必须检查它在返回值中跳过的字节数,直到您跳过全部数量,或者使用为您执行此操作的东西,例如ByteStreams.skipFully.

int bufferSize = fs.read(buf, 0, length);

同样,这不一定会读取所有length字节,并且它读取的字节数可以是任意数量 - 通常你不能依赖它。

String s = new String(buf, 0, bufferSize);

这隐含地使用了系统默认值Charset,这通常不是一个好主意——当您确实需要它时,最好使用Charset.defaultCharset().

另请注意,一般情况下,根据所使用的情况,某些字节可能无法转换为合法的字符序列Charset(即,如果它是 ASCII 就可以,如果是 Unicode,则不是那么多)。

于 2013-10-26T00:24:28.990 回答
1

为什么在不必要的时候尝试使用番石榴?

在这种情况下,看起来您正在寻找一个 RandomAccessFile。

File file = new File("foo");
long offset = ... ;
try (RandomAccessFile raf = new RandomAccessFile(file, "r")) {
  byte[] buffer = new byte[1014*1024];
  raf.seek(offset);
  raf.readFully(buffer);
  return new String(buffer, Charset.defaultCharset());
}
于 2013-10-25T21:39:10.810 回答
0

我不知道更优雅的解决方案:

public static void main(String[] args) throws IOException {
    final int offset = 20;
    StringBuilder to = new StringBuilder();

    CharStreams.copy(CharStreams.newReaderSupplier(new InputSupplier<InputStream>() {
        @Override
        public InputStream getInput() throws IOException {
            FileInputStream fs = new FileInputStream(new File("pom.xml"));

            ByteStreams.skipFully(fs, offset);

            return fs;
        }
    }, Charset.defaultCharset()), to);

    System.out.println(to);
}

唯一的好处是,当你String真的很大时,你可以通过避免转换为String.

于 2013-10-25T21:03:29.687 回答