7

とても便利なので、Scannerクラスを使ってファイルを読み取ることがよくあります。

      String inputFileName;
      Scanner fileScanner;

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

私の質問は、上記のステートメントはファイル全体を一度にメモリにロードしますか?または、fileScannerで次のような後続の呼び出しを行います

      fileScanner.nextLine();

ファイルから(つまり、メモリからではなく外部ストレージから)読み取りますか?ファイルが大きすぎて一度にメモリに読み込めない場合にどうなるか心配なので、質問します。ありがとう。

4

4 に答える 4

16

ソースコードを読めば、自分で質問に答えることができます。

問題のScannerコンストラクターの実装は次のことを示しているようです。

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

したがって、スキャナーはファイル全体を一度に読み取らないようです。

于 2012-04-26T15:32:57.597 に答える
2

コードを読むと、デフォルトで一度に1KBをロードしているように見えます。長いテキスト行の場合、バッファのサイズが大きくなる可能性があります。(テキストの最長行のサイズに)

于 2012-04-26T15:32:26.933 に答える
1

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

forを使用してStringTokenizer、必要な行の任意の部分をキャッチできます。

Scanner大きなファイルに使用すると、エラーが発生します。10000行のファイルから100行を読み取ってください!

スキャナーは、Readableインターフェースを実装する任意のオブジェクトからテキストを読み取ることができます。基になるreadableのReadable.read(java.nio.CharBuffer)メソッドの呼び出しがIOExceptionをスローした場合、スキャナーは入力の終わりに到達したと見なします。基になる読み取り可能オブジェクトによってスローされた最新のIOExceptionは、ioException()メソッドを介して取得できます。

APIで通知します

幸運を!

于 2012-04-26T15:53:07.183 に答える
0

大きなファイルには、 BufferedReaderFileReaderのようなものを使用することをお勧めします。基本的な例はここにあります。

于 2012-04-26T15:26:32.447 に答える