teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

1

コメントに対する回答を追加

2020/10/02 14:39

投稿

kazuma-s
kazuma-s

スコア8222

answer CHANGED
@@ -22,4 +22,58 @@
22
22
  }
23
23
  - sc.close();
24
24
  }
25
- ```
25
+ ```
26
+ **追記**
27
+ > close(); を一度使うと二度と Scanner を使えなくなるという認識で正しいでしょうか。
28
+
29
+ System.in に関してはそうです。
30
+ 他のファイルや文字列に対しては、Scanner は何度でも使えます。
31
+
32
+ System.in に関しても close() しなければ何度でも使えますが、
33
+ new するたびにバッファが確保され、リソースが無駄になります。
34
+
35
+ まず、次のコードを試してみてください。
36
+ ```Java
37
+ import java.util.Scanner;
38
+
39
+ class Test {
40
+ public static void main(String[] args) {
41
+ Scanner sc = new Scanner(System.in);
42
+ if (!sc.hasNextLine()) {
43
+ System.out.println("1. no line");
44
+ return;
45
+ }
46
+ String line = sc.nextLine();
47
+ System.out.println(line);
48
+ sc.close();
49
+
50
+ sc = new Scanner(System.in);
51
+ if (!sc.hasNextLine()) {
52
+ System.out.println("2. no line");
53
+ return;
54
+ }
55
+ line = sc.nextLine();
56
+ System.out.println(line);
57
+ sc.close();
58
+ }
59
+ }
60
+ ```
61
+ 2回目の new Scanner(System.in); はエラーになります。
62
+
63
+ では、最初の sc.close(); を実行しなければどうなるか?
64
+ キーボード入力で 2行読めます。
65
+
66
+ ところが、java Test <file.txt のように標準入力をファイルに切り替えると
67
+ 2行目の読み込みができません。
68
+
69
+ なぜかというと、Scanner は内部にバッファ(多分 8KB)を用意します。
70
+
71
+ 入力がキーボードだと、1回の read で、1行しかバッファに読み込まないため、
72
+ 新しい Scanner でも次の行が読めます。
73
+
74
+ でも、入力がファイルだと、最初の Scanner がファイルを読み込めるだけ全部
75
+ バッファに読み込んでしまいます。
76
+ 次の Scanner はもう読み込むものがありません。
77
+ ファイルのサイズが 8KB 以上だったら、続きが読めます。
78
+ でも、2行目は最初の Scanner で読み込まれているので、
79
+ ずっと後の行の途中からしか読み込めません。