2013-10-25 32 views
0

我现在正在使用的FileInputStream如何使用字节流读取文件的1Mb到一个字符串

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

我不知道我怎么能实现在番石榴库使用字节流相同的结果。

非常感谢!

+0

抱歉。我的意思是那里长。我只是修改了我的代码 – puscan

+0

老实说,现在你的方式可能比你使用番石榴时短。 ByteStreams api实际上只有读取所有字节的方法,而不是从某个偏移量开始的字节。你可以读取所有的字节,只使用'offset'作为'length',但是你没有真正从切换到Guava获得任何东西。 –

回答

3

这里是你如何能与番石榴做到这一点:

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,则不是那么多)。

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

唯一的好处是,你可以节省一些时间GC当你String是避免转化为String真大。

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()); 
} 
相关问题