質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

1回答

4289閲覧

forループ内でのScannerクラスの使用について

退会済みユーザー

退会済みユーザー

総合スコア0

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

0クリップ

投稿2017/07/02 06:55

編集2017/07/03 14:36

###前提・実現したいこと
Apacheのアクセスログ及び抽出対象のIPを標準入力より入力し、抽出対象のIPからのアクセスを抽出、標準出力より出力するプログラムを制作しています。
Javaの学習が目的ですので、SQLなどは利用しないつもりです。

入力内容は、1行目に抽出対象のIP(オクテット部に[a-b]とあるときはaからbまでの範囲を意味します)、2行目にログの件数、3行目以降がログとなります。

最終目標はこのプログラムが意図したとおりに動作することですが、ひとまずは下記エラーの解消方法をご教示頂ければ幸いです。

###発生している問題・エラーメッセージ

Exception in thread "main" java.lang.NumberFormatException: For input string: "" at java.lang.NumberFormatException.forInputString(Unknown Source) at java.lang.Integer.parseInt(Unknown Source) at java.lang.Integer.parseInt(Unknown Source) at b004.ipSearch(b004.java:21) at b004.main(b004.java:43)

###該当のソースコード

Java

1public class logExtract{ 2 static String targetSplit[] = new String[4]; 3 public static boolean ipSearch (String[] octets){ 4 for (int i = 0; i < 4; i++){ 5 // 抽出対象の第iオクテットが"*"のとき 6 if (i >= 2 && targetSplit[i].equals("*")){ 7 if (Integer.parseInt(octets[i]) < 0 && Integer.parseInt(octets[i]) > 255){ 8 return false; 9 } 10 } 11 // 抽出対象の第iオクテットが"-"を含むとき 12 else if (i >= 2 && targetSplit[i].contains("-")){ 13 String range[] = targetSplit[i].split("-", 0); 14 if (Integer.parseInt(octets[i].substring(1, octets[i].length())) < Integer.parseInt(range[0]) && Integer.parseInt(octets[i].substring(0, octets[i].length()-1)) > Integer.parseInt(range[1])){ 15 return false; 16 } 17 } 18 // 抽出対象の第iオクテットが数値のとき 19 else if (Integer.parseInt(octets[i]) != Integer.parseInt(targetSplit[i])){ 20 return false; 21 } 22 } 23 return true; 24 } 25 public static void main(String[] args) { 26 Scanner sc = new Scanner(System.in); 27 String target = sc.next(); 28 // 抽出対象のIPを"."区切りで分割し、配列に格納 29 targetSplit = target.split("\\.", 0); 30 int n = sc.nextInt(); 31 String logs[][] = new String[n][8]; 32 String ips[][] = new String[n][4]; 33 // 各ログごとにIPが抽出対象に含まれるかチェックし、含まれる場合出力 34 for (int i = 0; i < n; i++){ 35 String log = sc.nextLine(); 36 logs[i] = log.split(" ", 8); 37 System.out.println(logs[i][0]); 38 ips[i] = logs[i][0].split("\\.", 0); 39 System.out.println(Arrays.toString(logs[i])); 40 System.out.println(Arrays.toString(ips[i])); 41 if (ipSearch(ips[i])){ 42 // IP、日時、ファイル名をスペース区切りで出力 43 System.out.println(String.join(" ", logs[i][0], logs[i][4].substring(1, logs[i][4].length()), logs[i][7])); 44 } 45 } 46 } 47}

###試したこと
メイン部分の要点のみを抽出した下記のコードで検証したところ、カウント変数i=0のときに変数lineに入力内容が代入されていないことがわかりました(i=0のときの出力内容が"[]"となっているため)。

Java

1import java.util.*; 2 3public class Test1{ 4 public static void main(String[] args){ 5 Scanner sc = new Scanner(System.in); 6 int n = sc.nextInt(); 7 for (int i = 0; i < n; i++){ 8 String line = sc.nextLine(); 9 String lineSplit[] = line.split(" ", 8); 10 System.out.println(Arrays.toString(lineSplit)); 11 } 12 } 13}

###補足情報(言語/FW/ツール等のバージョンなど)
java version "1.8.0_131"
Java(TM) SE Runtime Environment (build 1.8.0_131-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.131-b11, mixed mode)

###追記(2017/07/03)
問題の解決後、デバッグも完了し、プログラムが完成しました。
同種のプログラムを制作しようとしている方の助けになればと思い、完成品のソースコードを公開いたします。

Java

1import java.util.*; 2 3public class b004{ 4 static String targetSplit[] = new String[4]; 5 public static boolean ipSearch (int[] octets){ 6 for (int i = 0; i < 4; i++){ 7 // 抽出対象の第iオクテットが"*"のとき 8 if (i >= 2 && targetSplit[i].equals("*")){ 9 if (octets[i] < 0 && octets[i] > 255){ 10 return false; 11 } 12 } 13 // 抽出対象の第iオクテットが"-"を含むとき 14 else if (i >= 2 && targetSplit[i].contains("-")){ 15 // 第iオクテットの"[", "]"を除いたものをハイフン区切りで配列に格納 16 String range[] = targetSplit[i].substring(1, targetSplit[i].length()-1).split("-", 0); 17 int rangeInt[] = new int[2]; 18 for (int j = 0; j < 2; j++){ 19 rangeInt[j] = Integer.parseInt(range[j]); 20 } 21 if (octets[i] < rangeInt[0] || octets[i] > rangeInt[1]){ 22 return false; 23 } 24 } 25 // 抽出対象の第iオクテットが数値のとき 26 else if (octets[i] != Integer.parseInt(targetSplit[i])){ 27 return false; 28 } 29 } 30 return true; 31 } 32 public static void main(String[] args) { 33 Scanner sc = new Scanner(System.in); 34 String target = sc.nextLine(); 35 // 抽出対象のIPを"."区切りで分割し、配列に格納 36 targetSplit = target.split("\\.", 0); 37 int n = sc.nextInt(); 38 String logs[][] = new String[n][8]; 39 String ips[][] = new String[n][4]; 40 int ipsInt[][] = new int[n][4]; 41 sc.nextLine(); 42 // 各ログごとにIPが抽出対象に含まれるかチェックし、含まれる場合出力 43 for (int i = 0; i < n; i++){ 44 String log = sc.nextLine(); 45 logs[i] = log.split(" ", 8); 46 ips[i] = logs[i][0].split("\\.", 0); 47 for (int j = 0; j < 4; j++){ 48 ipsInt[i][j] = Integer.parseInt(ips[i][j]); 49 } 50 } 51 for (int i = 0; i < n; i++){ 52 if (ipSearch(ipsInt[i])){ 53 // IP、日時、ファイル名をスペース区切りで出力 54 System.out.println(String.join(" ", logs[i][0], logs[i][3].substring(1, logs[i][3].length()), logs[i][6])); 55 } 56 } 57 } 58}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

ScannerのnextLineを除くnext,nextXxx系は、読み込み終わった場所でカーソルが止まります。
行末まで読み込んだ場合、行末でカーソルが止まり、次にnextLineを読んだときに
行末から次の行頭を改行記号除いて読み込むので、空文字になってしまいます。
例えばこんな入力である場合

8 abc

nextIntを呼び出したとき"8"を取り出し、"8"のあとにカーゾルがある状態になります。

8 ^カーソル位置 abc

ここからnextLineすると取り出す文字列が空文字しかなくなります。

forに入る前に1回nextLineで読み捨てるか、数字取得をnextLineからparseIntする必要があります。

投稿2017/07/02 16:09

swordone

総合スコア20651

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2017/07/03 11:15

swordoneさん、ご回答ありがとうございます。 nextLineメソッドの初歩的なところを勘違いしていたようで、大変失礼いたしました。
swordone

2017/07/03 13:07

いえいえ、私も引っかかった道です。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問