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

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

新規登録して質問してみよう
ただいま回答率
85.35%
ファイル

ファイルとは、文字列に基づいた名前又はパスからアクセスすることができる、任意の情報のブロック又は情報を格納するためのリソースです。

Java

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

オブジェクト

オブジェクト指向において、データとメソッドの集合をオブジェクト(Object)と呼びます。

Q&A

解決済

2回答

1295閲覧

CUIの初回起動時のみの処理と2回目以降の処理をそれぞれ表示したい

taka0145

総合スコア7

ファイル

ファイルとは、文字列に基づいた名前又はパスからアクセスすることができる、任意の情報のブロック又は情報を格納するためのリソースです。

Java

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

オブジェクト

オブジェクト指向において、データとメソッドの集合をオブジェクト(Object)と呼びます。

0グッド

0クリップ

投稿2021/10/31 17:16

前提・実現したいこと

CUIの初回起動では、情報入力を行い、それ以降は情報表示のみを行いたいです。

入力されたデータはpersonに格納し、ファイルに保存しています。
そして、情報表示の際は、ファイルからPersonに入れています。

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

何回目の起動か判断する処理が分かりません。 他の方法として、オブジェクトが空かどうかで判断することは可能なのでしょうか?

該当のソースコード

java

1import java.io.Serializable; 2 3public class Employee implements Serializable { 4 private Person person; 5 private int employeeID; 6 7 public Employee(Person person, int employeeID) { 8 this.person = person; 9 this.employeeID = employeeID; 10 11 } 12 13 public int getEmployeeID() { 14 return this.employeeID; 15 } 16 17 public Person getPerson() { 18 return this.person; 19 } 20 21 public String toString() { 22 String str = person.getName() + "," + person.getAge()+ "," + employeeID; 23 return str; 24 } 25 26 public boolean equals(Object obj) { 27 if(obj instanceof Employee) { 28 Employee std = (Employee)obj; 29 if(this.employeeID == std.getEmployeeID()) { 30 return true; 31 } 32 } 33 return false; 34 } 35 36 public int hashCode() { 37 return getEmployeeID(); 38 } 39
import java.io.Serializable; class Person implements Serializable{ private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(int age) { this.age = age; } public String toString() { String a = name + "," + age; return a; } public int hashCode() { return 0; } public boolean equals(Object obj) { if(this == obj) { return true; } else if(obj == null) { return false; } else if(this.getClass() != obj.getClass()) { return false; } else { Person other = (Person)obj; if(this.name.equals(other.name) && this.age == other.age) { return true; } else { return false; } } } }
import java.io.BufferedReader; import java.io.FileInputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; import java.io.BufferedOutputStream; import java.io.ObjectInputStream; import java.io.InputStreamReader; import java.io.FileNotFoundException; class Test { public static void main(String[] args) throws IOException{ BufferedReader input = new BufferedReader(new InputStreamReader(System.in)); entry(input);//初回起動時のみの処理 display(); //2回目以降の起動の処理 } public static File file = new File("Data.txt"); public static void entry(BufferedReader input)throws IOException{ String name; int age; int employeeID; System.out.println("データを入力"); System.out.print("名前>"); name = input.readLine(); System.out.print("年齢>"); age = Integer.parseInt(input.readLine()); System.out.print("従業員ID>"); employeeID = Integer.parseInt(input.readLine()); Employee e1 = new Employee(new Person(name,age),employeeID); try(ObjectOutputStream data = new ObjectOutputStream(new FileOutputStream(file))) { data.writeObject(e1); } catch(IOException e) { e.printStackTrace(); } } public static void display(){ try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file))) { Employee e1 = (Employee) ois.readObject(); System.out.println(e1); }catch(IOException | ClassNotFoundException e) { e.printStackTrace(); } } }

試したこと

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

ここにより詳細な情報を記載してください。

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

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

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

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

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

jimbe

2021/10/31 18:59

> 何回目の起動か判断する処理が分かりません。 その「何回目」の基準は何ですか。
taka0145

2021/10/31 23:49

CUIの1回目を起動し、そこで情報を入力させ、それ以降は情報表示のみを行うということです。
jimbe

2021/11/01 05:21 編集

いえ、極端に言えば、その1回目というのはこのプログラムが taka 0145 さんが「作って初めて実行」したら1回目なのか(もう2度と"1回目"にはならない)、それとも「特定のパソコン等で初めて実行」したら1回目なのか(その後プログラムを削除してもう一度インストールして実行してもそれはもう1回目では無い)、それとも「今年(or 今月、今週、今日等)初めて実行」したら1回目なのか・・・です。 また、その「 n 回目」を(プログラム内外の)任意の操作で操作できる想定なのでしょうか。 それがハッキリしていれば、実現できるのかはさておき、どうすればよいか(どうしなければならないか)は自ずと分かるのではないでしょうか。
taka0145

2021/11/01 05:16

ありがとうございます。 考え直してみます。
guest

回答2

0

ベストアンサー

何回目の起動か判断する処理が分かりません。
他の方法として、オブジェクトが空かどうかで判断することは可能なのでしょうか?

現状だと初回かそれ以降かだけを判断すればよいです。入力したデータはEmployeeクラスのオブジェクトにセットした後、シリアライズしてData.txtというファイルに保存するのですから、反対に言えばData.txtというファイルが無いか、Data.txtというファイルからEmployeeクラスにデシリアライズできるかどうかで判断できます。ファイルの有無だけを判断するとそのファイルの内容が正当かどうかは分からないので、デシリアライズ可能かどうかを判断した方がより良いと思います。

質問者さんの現状のコードをなるべくそのまま使うのであれば、Test#entry()メソッドを例えば以下のように修正すればよいでしょう。

Java

1public static void entry(BufferedReader input)throws IOException{ 2 Employee e1 = null; 3 try (ObjectInputStream data = new ObjectInputStream(new FileInputStream(file))) { 4 e1 = (Employee)data.readObject(); 5 } catch (Exception ex) { 6 System.out.println("!!!恐らく初回の入力。あるいはファイルが無かったり壊れてデシリアライズできない。"); 7 ex.printStackTrace(); 8 } 9 10 if (e1 != null) { 11 // デシリアライズできるのであれば入力済みであるということ 12 return; 13 } 14 15 try (ObjectOutputStream data = new ObjectOutputStream(new FileOutputStream(file))) { 16 String name; 17 int age; 18 int employeeID; 19 System.out.println("データを入力"); 20 System.out.print("名前>"); 21 name = input.readLine(); 22 System.out.print("年齢>"); 23 age = Integer.parseInt(input.readLine()); 24 System.out.print("従業員ID>"); 25 employeeID = Integer.parseInt(input.readLine()); 26 e1 = new Employee(new Person(name,age),employeeID); 27 28 data.writeObject(e1); 29 } catch(IOException e) { 30 e.printStackTrace(); 31 } 32}

Windowsコマンドプロンプトでの実行例です。(Java SE11)

terminal

1C>Javac Test.java 2 3C>java Test 4!!!恐らく初回の入力。あるいはファイルが無かったり壊れてデシリアライズできない。 5java.io.FileNotFoundException: Data.txt (指定されたファイルが見つかりません。) 6 at java.base/java.io.FileInputStream.open0(Native Method) 7 at java.base/java.io.FileInputStream.open(FileInputStream.java:219) 8 at java.base/java.io.FileInputStream.<init>(FileInputStream.java:157) 9 at Test.entry(Test.java:23) 10 at Test.main(Test.java:15) 11データを入力 12名前>Hoge 13年齢>30 14従業員ID>123 15Hoge,30,123 16 17C>java Test 18Hoge,30,123 19 20C>

もし、何回目の起動か判断したいのであれば、起動されるごとに+1する変数を何かのクラスのフィールドにして、それもシリアライズ/デシリアライズできるようにすればよいでしょう。

投稿2021/10/31 19:07

編集2021/10/31 19:13
dodox86

総合スコア9256

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

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

taka0145

2021/10/31 23:58

初回起動の際は、catchをつかみ、エラーを表示させ、データを入力させると思うのですが、このエラーを表示させないように書くことは、文法的によろしくないのでしょうか?
dodox86

2021/11/01 00:40 編集

> catchをつかみ、エラーを表示させ、データを入力させると思うのですが、このエラーを表示させないように書くことは、文法的によろしくないのでしょうか? エラー表示と言われているのが「!!!恐らく初回の入力。...」の部分であるなら、これは単なる例なので、どうにでも好きにして結構です。「文法的に」というのを言葉どおりに取ると、コンパイルエラーが起きなければそれは文法的に正しいということなので、問題ではありません。プログラムを"製品"ととらえ、「このケースではこの挙動をする」と決めるのは仕様のお話であり、UIの部分なので、それぞれで決めてよいこととなります。「初めて起動する」ということ自体はどんなプログラムにもあることであり、それ自体はエラーではありません。警告は親切かもしれませんし、余計なお世話かもしれません。 サンプルのコードではザックリとExceptionをcatchしてprintStatckTrace()していますが、ここは本来であればそれぞれのExceptionに応じて対応を適切に変える方が「プログラム・製品」としては良いかもしれません。いずれも質問者さん次第だと思います。
dodox86

2021/11/01 00:45

shiketaさんのご指摘で思い直しましたが、「このエラーを表示させない」とは「このエラー(例外)を発生させない」という意味でしたでしょうか。そうであれば、Data.txtファイルが存在しない場合はデシリアライズを試行するまでもないので、ファイルの存在チェックではじいてしまうのも手、です。サンプルコードでは回答中にも少し書きましたが、「ファイルがあっても正しいファイルとは限らない」ことから、あえて一緒にしています。
taka0145

2021/11/01 02:03

ファイルは存在するが、データが入力されておらず、デシリアライズできない→例外→初回の入力 このように理解しているのですが、その場合、初回の入力の際は、ファイルが存在していたとしても例外が発生するものではないのでしょうか? 理解力がなく申し訳ありません。
dodox86

2021/11/01 02:12

> その場合、初回の入力の際は、ファイルが存在していたとしても例外が発生するものではないのでしょうか? しますよ。ご自身で実際に試しましょうよ。デタラメな値が入っていたような場合、それに対応する例外がthrowされます。 C>echo detarame > Data.txt C>java Test !!!恐らく初回の入力。あるいはファイルが無かったり壊れてデシリアライズできない。 java.io.StreamCorruptedException: invalid stream header: 64657461 at java.base/java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:940) at java.base/java.io.ObjectInputStream.<init>(ObjectInputStream.java:379) at Test.entry(Test.java:23) at Test.main(Test.java:15) データを入力 名前>
taka0145

2021/11/01 02:20

はい、確かめてみました。 以下のように、デシリアライズできない場合(初回の入力)の際でも例外を発生させずに表示したいと考えています。 C>java Test データを入力 名前>
dodox86

2021/11/01 02:22

> 例外を発生させずに表示したいと考えています。 ? 例外は発生するので、catch節の中で特にエラー表示をしなければいいだけのことです。
dodox86

2021/11/01 02:26

要はこういうことです。 try (ObjectInputStream data = new ObjectInputStream(new FileInputStream(file))) { e1 = (Employee)data.readObject(); } catch (Exception ex) { ; /* 何もしない System.out.println("!!!恐らく初回の入力。あるいはファイルが無かったり壊れてデシリアライズできない。"); ex.printStackTrace(); */ }
taka0145

2021/11/01 02:26

catch節では、エラー表示を書かなければいけないものだと勘違いしておりました。 申し訳ないです。
dodox86

2021/11/01 02:31

> catch節では、エラー表示を書かなければいけないものだと勘違いしておりました。 ああ、なるほど。初心の頃は「こうしなければいけない」とつい思い込んでしまうことはありますね。
guest

0

何回目の起動か判断する処理が分かりません。
他の方法として、オブジェクトが空かどうかで判断することは可能なのでしょうか?

視点を変えて。

PreferencesFactoryPreferencesを使えばいいのでは。まずはpref.getInt("count", 0)として、0が返ってきたら一回目。処理が終わったら pref.putInt('count', pref.getInt("count", 0) + 1)とすれは、二回目以降は、起動するたびにカウントアップされる。Windowsなら値はレジストリに保存されるので、事故があっても消えることはないし。

投稿2021/11/01 01:06

shiketa

総合スコア4061

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

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

taka0145

2021/11/01 02:15

Preferencesというものを初めて拝見したので少し調べてみます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問