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

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

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

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

Q&A

解決済

1回答

1087閲覧

入力メゾットでエラーが発生してしまう

yukkuri

総合スコア624

Java

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

0グッド

0クリップ

投稿2018/12/13 13:06

編集2018/12/13 14:19

前提・実現したいこと

現在、入出力関数を作って、テストをしていました。
具体的には、ABCを入れるとABCと出て、次別関数で入力するとその値と互換のない文字列が返される、というイメージでした。

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

Exception in thread "main" java.util.NoSuchElementException at java.util.Scanner.throwFor(Scanner.java:862) at java.util.Scanner.next(Scanner.java:1371) at org.jyl.base.JylLog.inputOne(JylLog.java:166) at org.jyl.base.JylLog.inputOne(JylLog.java:148) at MethodTest.main(MethodTest.java:10)

該当のソースコード

java

1package org.jyl.base; 2 3import java.io.InputStreamReader; 4import java.io.IOException; 5import java.io.PrintStream; 6 7import java.util.Date; 8import java.util.Scanner; 9 10/** 11 * テキストの出力、入力を簡易化するクラスです。 12 * 本来は、デバッグメッセージを表示する用のクラスです。 13 */ 14public final class JylLog 15{ 16 private static PrintStream out = System.out; 17 private static Scanner sc = null; 18 19 private static boolean deb = false; 20 21 /** 22 * 未読み込みのバイトがある場合は破棄し、新しい文字入力ストリームを用意します。 23 * 24 * @return 入力されたバイト 25 * 26 * @since Jyl_Base_1.0 27 */ 28 public static String input() throws JylException 29 { 30 if( sc != null ) scanClose(); 31 32 sc = new Scanner( new InputStreamReader( System.in ) ); 33 34 String str = sc.next(); 35 if( str == null ) str = ""; 36 37 scanClose(); 38 39 return str; 40 } 41 42 /** 43 * バイト内の次のトークンを取得します。 44 * 45 * @return 入力されたバイト内の次のトークン 46 * 47 * @since Jyl_Base_1.0 48 */ 49 public static String inputNext() 50 { 51 if( sc == null ) sc = new Scanner( new InputStreamReader( System.in ) ); 52// else return ""; 間違い 53 54 String str = sc.next(); 55 if( str == null ) str = ""; 56 return str; 57 } 58 59 /** 60 * バイト内のはじめのバイトを取得します。 61 * 62 * @return 入力値のはじめのバイト 63 * 64 * @since Jyl_Base_1.0 65 * 66 * @see #inputOne( int ) 67 */ 68 public static char inputOne() 69 { 70 return inputOne( 0 ); 71 } 72 73 /** 74 * バイト内で指定した位置のバイトを取得します。 75 * 76 * @param index 読み込み後返すバイト 77 * 78 * @return 入力値内の指定されたバイト 79 * 80 * @since Jyl_Base_1.0 81 */ 82 public static char inputOne( int index ) 83 { 84 if( sc != null ) scanClose(); 85 86 sc = new Scanner( new InputStreamReader( System.in ) ); 87 88 String str = sc.next(); // ここでエラー 89 if( str == null ) return "".charAt( 0 ); 90 91 return str.charAt( index ); 92 } 93 94 /** 95 * 現在残っているバイト内の次のトークンを取得します。 96 * クローズしている場合<code>""</code>が返されます。 97 * 98 * @return 残っているバイト内の次のトークン 99 * 100 * @since Jyl_Base_1.0 101 */ 102 public static String next() 103 { 104 if( sc == null ) return ""; 105 106 String str = sc.next(); 107 if( str == null ) str = ""; 108 109 return str; 110 } 111 112 /** 113 * 指定したメッセージを改行をせず表示します。 114 * 115 * @param message 表示するメッセージ <code>null</code>の場合は<code>""</code>と同一の動作です 116 * 117 * @since Jyl_Base_1.0 118 */ 119 public static void print( String message ) 120 { 121 if( message == null ) message = ""; 122 123 out.println( message ); 124 } 125 126 /** 127 * 時刻と指定したメッセージを表示します。<br> 128 * <code>JylLog.out( "message" );</code><br>と書いた場合、<br><code>現在の時刻 message</code><br>と表示されます。 129 * 130 * @param message 表示するメッセージ <code>null</code>の場合は<code>""</code>と同一の動作です 131 * 132 * @since Jyl_Base_1.0 133 */ 134 public static void println( String message ) 135 { 136 if( message == null ) message = ""; // null チェック 137 138 out.println( new Date() + " " + message ); 139 } 140 141 /** 142 * 時刻とタグ、指定したメッセージを表示します。<br> 143 * <code>JylLog.out( "tag", "message" );</code><br>と書いた場合、<br><code>現在の時刻 [tag]message</code><br>と表示されます。 144 * 145 * @param tag メッセージの種類を示すタグ <code>null</code>の場合は<code>""</code>と同一の動作です 146 * @param message 表示するメッセージ <code>null</code>の場合は<code>""</code>と同一の動作です 147 * 148 * @since Jyl_Base_1.0 149 */ 150 public static void println( String tag, String message ) 151 { 152 if( tag == null ) tag = ""; 153 if( message == null ) message = ""; 154 155 out.println( new Date() + " [" + tag + "]" + message ); 156 } 157 158 /** 159 * 開いているバイトがある場合、閉じて初期化します。 160 * 161 * @since Jyl_Base_1.0 162 */ 163 public static void scanClose() 164 { 165// sc.close(); 回答を受けコメントアウト 166 sc = null; 167 } 168} 169

java

1package org.jyl.base; 2 3public class JylException extends Exception 4{ 5 /** 6 * 発生した例外を理由として<code>JylException</code>をスローします。 7 * 8 * @param cause 発生した例外 この例外がスローされた理由とする<br>もし理由が存在しないまたは不明な場合は<code>null</code>を指定します。 9 * 10 * @since Jyl_Base_1.0 11 */ 12 public JylException( Throwable cause ) 13 { 14 super( cause ); 15 } 16 17 /** 18 * 発生した例外を理由とし、指定したメッセージを使用して<code>JylException</code>をスローします。 19 * 20 * @param message スローされるこの例外についてのメッセージを指定します。<br><code>null</code>の場合は<code>""</code>と同じ扱いになります。 21 * @param cause 発生した例外 この例外がスローされた理由とする<br>もし理由が存在しないまたは不明な場合は<code>null</code>を指定します。 22 * 23 * @since Jyl_Base_1.0 24 */ 25 public JylException( String message, Throwable cause ) 26 { 27 super( message, cause ); 28 } 29} 30

java

1import org.jyl.base.*; 2 3class MethodTest 4{ 5 public static void main( String[] a ) throws JylException 6 { 7 String str1 = JylLog.input(); 8 JylLog.println( str1 ); 9 10 char str2 = JylLog.inputOne(); 11 char[] c = { str2 }; 12 JylLog.println( new String( c ) ); 13 JylLog.scanClose(); 14 15// String str3 = JylLog.inputNext(); 16 String str3 = JylLog.input(); 17 JylLog.println( str3 ); 18// JylLog.scanClose(); 19 20 String str4 = JylLog.next(); 21 JylLog.println( str4 ); 22 JylLog.scanClose(); 23 24 JylLog.scanClose(); 25 26 try{ 27 JylLog.println( "message" ); 28 JylLog.println( "tag", "message" ); 29 System.out.println( (Object)null ); 30 throw new java.io.IOException(); 31 }catch( Exception e ){ 32 JylLog.println( "error" ); 33 throw new JylException( null, e ); 34 } 35 } 36} 37

試したこと

Scannerの引数をSystem.in->InputStreamReaderにした
調べるとBufferedReaderを使うのが一般的らしい
->nextを使いたかったのでScanner固定にしたい

補足情報(FW/ツールのバージョンなど)

java8,linuxです。
try-with-resourceは個人的な苦手意識が高いので使ってません。

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

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

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

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

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

guest

回答1

0

ベストアンサー

標準入力のScannerインスタンスを閉じるとそのようなエラーが出ます。

JylLog.inputをScannerインスタンスを引数として受け取るようにし、
インスタンスの生成は呼び出し元に任せるとわりあい扱いやすいかと。

投稿2018/12/13 13:25

LouiS0616

総合スコア35660

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

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

yukkuri

2018/12/13 13:45

JylLog.inputをScannerインスタンスを引数として受け取るようにし、は自分のイメージしている構造とは違うんですよね...。いま、System.inのコピーを渡しましたが、だめでした。 使う人が極力インスタンスを作らなくていい、というイメージにしたいんです。標準入力でなくてもいいのですが、どうしたらいいでしょうか。
LouiS0616

2018/12/13 13:50

それならcloseしないことです。 そう考えると、そのままScannerクラスを使うのとあまり変わらなくなりますね。
yukkuri

2018/12/13 14:02

すいません closeしないことでイメージ通り動いたのですが、テストクラスで JylLog.inputNext(); を呼び出した時、必ず""が帰ってくるのですが、なぜでしょうか。
LouiS0616

2018/12/13 14:08

scがnullを取らなくなったことで、else return ""; が効いているのでは。
yukkuri

2018/12/13 14:17

すいません、上は書き間違えでした。 nextのテスト中なのですが、 input inpのように上のinput()でうっても空白です。また、その間違いに気づいたので編集します。
LouiS0616

2018/12/13 14:51 編集

実際に入力した内容があるとこちらでも試せるのですが。
yukkuri

2018/12/13 15:02

コンソール内容はこんな感じです。 input input Fri Dec 14 00:01:24 JST 2018 [info]input input Fri Dec 14 00:01:26 JST 2018 [info]i input input Fri Dec 14 00:01:31 JST 2018 [info]input Fri Dec 14 00:01:31 JST 2018 [info] Fri Dec 14 00:01:31 JST 2018 message Fri Dec 14 00:01:31 JST 2018 [tag]message null Fri Dec 14 00:01:31 JST 2018 [err]error java.io.IOException at MethodTest.main(MethodTest.java:28) Exception in thread "main" org.jyl.base.JylException at MethodTest.main(MethodTest.java:31) Caused by: java.io.IOException at MethodTest.main(MethodTest.java:28)
LouiS0616

2018/12/13 15:16

inputメソッドの最後で scanClose() して、sc = nullしてますよね。 それでnextメソッドの if( sc == null ) return ""; が実行されているだけかと思います。
LouiS0616

2018/12/13 15:19

バッファをクリアするのに、Scannerインスタンスを再生成するのも若干強引かと。 環境に依っては動かないんじゃないですかね。
yukkuri

2018/12/14 08:43

Scannerをクローズせず終了しても安全性的に問題はないのでしょうか。
LouiS0616

2018/12/14 08:55

リークするとしても、何度も開きなおさなければ影響はそこまで大きくない筈です。 もちろんきちんと片付けるに越したことは無いですが。 閉じるにしても、JylLogクラスが入力の要請の終了を感知できない以上呼び出し元が指示を出してやらねばなりません。 しかし呼び出し元でscanCloseを呼ぶのはダサいですし、ファイナライザを定義してGCに任せるのも確実では無く推奨されません。 AutoClosableなインスタンスにしてtry-with-resourceで閉じるのが簡単で確実なのでは。 こうなると生のScannerを使うのとあまり使い勝手が変わらないのですよね。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問