2012-04-26 30 views
3

我经常使用Scanner类来读取文件,因为它非常方便。Scanner类是否将整个文件一次加载到内存中?

 String inputFileName; 
     Scanner fileScanner; 

     inputFileName = "input.txt"; 
     fileScanner = new Scanner (new File(inputFileName)); 

我的问题是,它上面的语句将整个文件加载到内存中一次?或在fileScanner做后续调用就像从文件

 fileScanner.nextLine(); 

读(即从外部存储器而不是从内存)?我问,因为我担心如果文件太大而无法一次读入内存会发生什么情况。谢谢。

+1

答案是否定的,但它通过缓冲区读取文件 - 这意味着在块中。 – Alex 2015-04-15 13:25:54

回答

12

如果您阅读源代码,您可以自己回答问题。

看起来好像是有问题的扫描仪构造函数的实现表明:

public Scanner(File source) throws FileNotFoundException { 
     this((ReadableByteChannel)(new FileInputStream(source).getChannel())); 
} 

后者,这是裹成的读者:

private static Readable makeReadable(ReadableByteChannel source, CharsetDecoder dec) { 
    return Channels.newReader(source, dec, -1); 
} 

而且它使用缓冲区大小

阅读
private static final int BUFFER_SIZE = 1024; // change to 1024; 

正如您在施工链的最终构造函数中所看到的那样:

private Scanner(Readable source, Pattern pattern) { 
     assert source != null : "source should not be null"; 
     assert pattern != null : "pattern should not be null"; 
     this.source = source; 
     delimPattern = pattern; 
     buf = CharBuffer.allocate(BUFFER_SIZE); 
     buf.limit(0); 
     matcher = delimPattern.matcher(buf); 
     matcher.useTransparentBounds(true); 
     matcher.useAnchoringBounds(false); 
     useLocale(Locale.getDefault(Locale.Category.FORMAT)); 
    } 

所以,它出现在扫描仪一次不能读取整个文件。

+0

+1不知道它没有一次读取整个文件。回答编辑。但是,它仍然会遇到BufferedReader + FileReader没有的较大文件的问题。 – Aidanc 2012-04-26 15:34:46

+4

@Aidanc什么样的问题? – 2012-04-26 15:36:53

0

对于大型文件,最好用BufferedReaderFileReader。一个基本的例子可以找到here

+0

@Sheriff查看edalorzo的回答。看起来我误解了整个文件的阅读,但是我留下了我的答案,因为Buffered + FileReader可以更好地处理大文件。 – Aidanc 2012-04-26 15:37:00

+2

@Aidanc - 你为什么这么说?这当然取决于你是否需要Scanner的解析功能。当然,如果OP仅**将使用'nextLine()',则BufferedReader可能会更快一些。 (注意,OP说“后续调用fileScanner ** like **'fileScanner.nextLine()'”...) – 2012-04-26 15:42:29

+1

为什么你认为BufferedReader更好? – CodeBlue 2012-04-26 17:07:41

1

通过阅读代码,它默认一次加载1 KB。对于长文本行,缓冲区的大小可能会增加。 (以您所拥有的最长文本行的大小)

0

在ACM竞赛中,快速阅读非常重要。在Java中,我们发现发现,使用这样的事情是非常快...

FileInputStream inputStream = new FileInputStream("input.txt"); 
    InputStreamReader streamReader = new InputStreamReader(inputStream, "UTF-8"); 
    BufferedReader in = new BufferedReader(streamReader); 
    Map<String, Integer> map = new HashMap<String, Integer>(); 
    int trees = 0; 
    for (String s; (s = in.readLine()) != null; trees++) { 
     Integer n = map.get(s); 
     if (n != null) { 
      map.put(s, n + 1); 
     } else { 
      map.put(s, 1); 
     } 
    } 

该文件包含,在这种情况下,树的名字......

Red Alder 
Ash 
Aspen 
Basswood 
Ash 
Beech 
Yellow Birch 
Ash 
Cherry 
Cottonwood 

可以使用StringTokenizer渔获你想要的任何部分。

如果我们对大文件使用Scanner,我们会发生一些错误。用10000行从文件中读取100行!

扫描器可以读取它实现了可读 接口的任何对象的文本。如果调用底层可读的Readable.read(java.nio.CharBuffer)方法会引发IOException,那么 扫描器会假定已达到输入的末尾。通过ioException()方法检索到的底层可读的最近IOException可能为 。

告诉API

祝你好运!

相关问题