我现在拥有的是使用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);
我想知道如何在guava库中使用ByteStreams来实现相同的结果。
非常感谢!
答案 0 :(得分:3)
以下是你如何用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,那么这么多)。
答案 1 :(得分: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());
}
答案 2 :(得分: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
来节省一些GC时间。