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

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

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

JavaFXとは、Java仮想マシン上で動作するリッチインターネットアプリケーション (RIA) のGUIライブラリです。Swingとは異なり、FXMLと呼ばれる XMLとCSSを併用してデザインを記述します。

Java

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

Q&A

解決済

2回答

1663閲覧

デシリアライズで複数のオブジェクトを読み取りたい。

ryu-bamboo

総合スコア9

JavaFX

JavaFXとは、Java仮想マシン上で動作するリッチインターネットアプリケーション (RIA) のGUIライブラリです。Swingとは異なり、FXMLと呼ばれる XMLとCSSを併用してデザインを記述します。

Java

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

0グッド

0クリップ

投稿2021/05/04 13:00

質問お願いします。
自分はjavaFXでスケジュール表を作っていて、追加した予定を保存して表示するためにSerializeを使っています。

前回の質問で複数のオブジェクトを保存できるようになったのですが、今度は一つのオブジェクトしかデシリアライズできない問題が起きました。そこで調べてみると、このサイトに,Whileで無限ループしてEOFExceptionが発生したら抜け出すという方法が書いてあったのでやってみたのですが、closeしているのにIOExceptionが起きてしまい失敗してしまいました。
正規表現を使ってなんとかできるかな、とも思ったのですが、バイナリファイルですのでやり方がわからずあきらめている状況です。知恵をお貸しください、お願いします。

fxmlは文字数を超えるため書けませんでした、ご容赦ください。

ScheduleMain

1 2package application; 3 4import java.io.EOFException; 5import java.io.File; 6import java.io.FileInputStream; 7import java.io.IOException; 8import java.io.ObjectInputStream; 9import java.util.ArrayList; 10import java.util.List; 11 12import javafx.application.Application; 13import javafx.fxml.FXMLLoader; 14import javafx.scene.Scene; 15import javafx.scene.control.Label; 16import javafx.scene.layout.VBox; 17import javafx.stage.Stage; 18 19 20public class ScheduleMain extends Application { 21 22 23 public static ScheduleTableController stController; 24 25 @Override 26 public void start(Stage primaryStage) { 27 try { 28 FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("ScheduleIndividual.fxml")); 29 Scene scene = new Scene((VBox)fxmlLoader.load(),150,600); 30 scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm()); 31 stController = fxmlLoader.getController(); 32 33 List<ScheduleData> list = new ArrayList<ScheduleData>(); 34 try { 35 if(!isEmpty()) { 36 loading(list); 37 for(ScheduleData sd : list) { 38 initScheduleLabel(sd); 39 } 40 } 41 } catch (IOException e) { 42 e.printStackTrace(); 43 } 44 45 primaryStage.setScene(scene); 46 primaryStage.show(); 47 System.out.println(stController.toString()); 48 } catch(Exception e) { 49 e.printStackTrace(); 50 } 51 } 52 53 public static void main(String[] args) { 54 launch(args); 55 } 56 57 boolean isEmpty() throws IOException { 58 File file = new File("SaveDataFile.ser") ; 59 boolean empty = !file.exists() || file.length()==0; 60 return empty; 61 } 62 63 void loading(List<ScheduleData> datas) { 64 try (var in = new ObjectInputStream(new FileInputStream("SaveDataFile.ser"))){ 65 while(true) { 66 ScheduleData saveData = (ScheduleData)in.readObject(); 67 System.out.println(saveData.getDetail()); 68 datas.add(saveData); 69 in.close(); 70 } 71 }catch (EOFException e) { 72 System.out.println("デシリアライズ完了"); 73 } catch (IOException e) { 74 System.out.println("IOerror"); 75 }catch ( ClassNotFoundException e) { 76 System.out.println("CNFerror"); 77 } 78 } 79 80 @SuppressWarnings("static-access") 81 void initScheduleLabel(ScheduleData data) { 82 var sLabel = new Label(); 83 double stNum = (data.getsTime().getHour()+data.getsTime().getMinute()/60)*30+4; 84 double ftNum = (data.getfTime().getHour()+data.getfTime().getMinute()/60)*30+4; 85 double tNum = ftNum-stNum; 86 String str = data.gettitle()+"\n"+data.gettime()+"\n"+data.getDetail(); 87 sLabel.setText(str); 88 sLabel.setStyle("-fx-background-color:green;"); 89 stController.getaPane().getChildren().add(sLabel); 90 stController.getaPane().setTopAnchor(sLabel, stNum); 91 sLabel.setPrefHeight(tNum); 92 93 } 94} 95

ScheduleTableController

1/** 2 * Sample Skeleton for 'ScheduleIndividual.fxml' Controller Class 3 */ 4 5 6public class ScheduleTableController { 7 8 9 @FXML // ResourceBundle that was given to the FXMLLoader 10 private ResourceBundle resources; 11 12 @FXML // URL location of the FXML file that was given to the FXMLLoader 13 private URL location; 14 15 @FXML // fx:id="pane" 16 private VBox pane; // Value injected by FXMLLoader 17 18 @FXML // fx:id="aPane" 19 private AnchorPane aPane; // Value injected by FXMLLoader 20 21 @FXML // fx:id="aPane" 22 private VBox scheduleIndividual; // Value injected by FXMLLoader 23 24 25 //ここからScheduleSelectのid 26 27 28 29 @FXML 30 void sets(MouseEvent event) { 31 try { 32 showSecondWindow(); 33 } catch (IOException e) { 34 e.printStackTrace(); 35 } 36 } 37 38 39 40 void showSecondWindow() throws IOException { 41 42 FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("ScheduleSelect.fxml")); 43 AnchorPane root = (AnchorPane) fxmlLoader.load(); 44 Scene scene = new Scene(root); 45 Stage stage = new Stage(); 46 stage.setScene(scene); 47 stage.showAndWait(); 48 49 } 50 51 52 53 54 public AnchorPane getaPane() { 55 return aPane; 56 } 57 58 59 60 @FXML // This method is called by the FXMLLoader when initialization is complete 61 void initialize() { 62 63 64 65 assert pane != null : "fx:id=\"pane\" was not injected: check your FXML file 'ScheduleIndividual.fxml'."; 66 67 } 68 69} 70

ScheduleSelectController

1 2package application; 3 4import java.io.FileOutputStream; 5import java.io.IOException; 6import java.io.ObjectOutputStream; 7import java.time.LocalTime; 8 9import javafx.fxml.FXML; 10import javafx.scene.control.Button; 11import javafx.scene.control.ComboBox; 12import javafx.scene.control.Label; 13import javafx.scene.control.TextArea; 14import javafx.scene.control.TextField; 15import javafx.scene.input.MouseEvent; 16import javafx.scene.layout.AnchorPane; 17 18public class ScheduleSelectController { 19 20 @FXML // fx:id="scheduleName" 21 private TextField scheduleName; // Value injected by FXMLLoader 22 23 @FXML // fx:id="sHour" 24 private ComboBox<String> sHour; // Value injected by FXMLLoader 25 26 @FXML // fx:id="sakusei" 27 private Button sakusei; // Value injected by FXMLLoader 28 29 @FXML // fx:id="packageSelect" 30 private ComboBox<?> packageSelect; // Value injected by FXMLLoader 31 32 @FXML // fx:id="month" 33 private ComboBox<?> month; // Value injected by FXMLLoader 34 35 @FXML // fx:id="scheduleSelct" 36 private AnchorPane scheduleSelect; // Value injected by FXMLLoader 37 38 @FXML // fx:id="year" 39 private ComboBox<String> year; // Value injected by FXMLLoader 40 41 @FXML // fx:id="fHour" 42 private ComboBox<String> fHour; // Value injected by FXMLLoader 43 44 @FXML // fx:id="fMinute" 45 private ComboBox<String> fMinute; // Value injected by FXMLLoader 46 47 @FXML // fx:id="memo" 48 private TextArea memo; // Value injected by FXMLLoader 49 50 @FXML // fx:id="sMinute" 51 private ComboBox<String> sMinute; // Value injected by FXMLLoader 52 53 @FXML // fx:id="day" 54 private ComboBox<String> day; // Value injected by FXMLLoader 55 56 @FXML 57 void clickMemo(MouseEvent event) { 58 59 } 60 61 @FXML 62 void jikkou(MouseEvent event) { 63 addScheduleLabel(addData()); 64 save(); 65 System.out.println("追加しました。"); 66 } 67 68 ScheduleData addData() { 69 String name = scheduleName.getText(); 70 var sTime = LocalTime.of(Integer.parseInt(sHour.getValue()),Integer.parseInt(sMinute.getValue())); 71 var fTime = LocalTime.of(Integer.parseInt(fHour.getValue()),Integer.parseInt(fMinute.getValue())); 72 String detail = memo.getText(); 73 var sd = new ScheduleData(name, sTime, fTime, detail); 74 return sd; 75 } 76 77 78 @SuppressWarnings("static-access") 79 void addScheduleLabel(ScheduleData data) { 80 var sLabel = new Label(); 81 double stNum = (data.getsTime().getHour()+data.getsTime().getMinute()/60)*30+4; 82 double ftNum = (data.getfTime().getHour()+data.getfTime().getMinute()/60)*30+4; 83 double tNum = ftNum-stNum; 84 String str = data.gettitle()+"\n"+data.gettime()+"\n"+data.getDetail(); 85 sLabel.setText(str); 86 87 ScheduleTableController controller = ScheduleMain.stController; 88 controller.getaPane().getChildren().add(sLabel); 89 controller.getaPane().setTopAnchor(sLabel, stNum); 90 sLabel.setPrefHeight(tNum); 91 } 92 93 @FXML private void initialize() throws IOException { 94 95 } 96 97 98 void save() { 99 try (var out = new ObjectOutputStream(new FileOutputStream( "SaveDataFile.ser",true))){ 100 out.writeObject(addData()); 101 102 103 }catch (IOException e) { 104 e.printStackTrace(); 105 106 } 107 } 108 109}

SaveDataFile

1ャ・ sr application.ScheduleData  L detailt Ljava/lang/String;L 2finishTimet Ljava/time/LocalTime;L startTimeq ~ L timeq ~ L titleq ~ xpt hrhr4wsr 3java.time.Ser評┝"Hイ xpwxsq ~ wxt 401:02・・5:01t grsegャ・ sr application.ScheduleData  L detailt Ljava/lang/String;L 5finishTimet Ljava/time/LocalTime;L startTimeq ~ L timeq ~ L titleq ~ xpt gvseaghsr 6java.time.Ser評┝"Hイ xpwxsq ~ w砡t 701:04・・4:01t fcwea

一回目の実行
一回目
二回目の実行
二回目

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

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

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

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

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

guest

回答2

0

わざわざ調べていただきありがとうございました!新規で開くか追記で開くかで処理が変わってしまうんですね!とても参考になりました!

投稿2021/05/06 10:12

ryu-bamboo

総合スコア9

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

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

shiketa

2021/05/06 11:08 編集

> スケジュール表を作っていて、追加した予定を保存して表示するためにSerializeを使っています。 以下、老婆心ながら。 オブジェクトをシリアライズしたとき、そのオブジェクトのクラスの定義が変わると、あなたの例でいえば ScheduleDataクラスの定義を変更するとデシリアライズできなくなる、可能性があります。ScheduleDataクラスの実装については、その点も十分に配慮する必要があります。 スケジュールのように、長期に渡ってデータを蓄積し運用するモノであれば、わたしならシリアライズの機能を使ってデータを保存しようとは思いません。100%思いません。どうしてもヒトが読める形のファイルで管理したいのであれば、JSON形式やxml形式を選びます。けれどスケジュール管理なのであれば、間違いなくデータベースを選択します。
ryu-bamboo

2021/05/07 14:06

ありがとうございます!実はシリアライズが危険という話は聞いたことがあるのですが、それ以外の方法を知らなかったので、簡単なシリアライズを使おうと思っていたんです。 せっかくの機会ですのでデータベースを勉強してみたいと思います、本当にありがとうございます!
guest

0

ベストアンサー

JavaFXは、まったく関係ない部分のおはなしです。

デシリアライズで複数のオブジェクトを読み取りたい。

  1. 複数のオブジェクトを読み取りたいのであれば、まずは、複数のオブジェクトを書き出す必要がある。
  2. あなたの実装では、FileOutputStreamを追記状態で作成して、ObjectOutputStreamに渡している。
  3. https://docs.oracle.com/javase/jp/8/docs/api/java/io/ObjectOutputStream.html のサンプルでは、ファイルを追記状態ではなく新規で開いてObjectOutputStreamに渡している。

java

1 FileOutputStream fos = new FileOutputStream("t.tmp"); 2 ObjectOutputStream oos = new ObjectOutputStream(fos); 3 4 oos.writeInt(12345); 5 oos.writeObject("Today"); 6 oos.writeObject(new Date()); 7 8 oos.close();
  1. 複数のオブジェクトを読み取りたいのであれば、複数のオブジェクトをwriteXX()で書き出して、その順番通りにreadXX()すればいい。

java

1import java.io.*; 2import java.time.LocalTime; 3import java.util.UUID; 4 5public class HogeSerialize { 6 public static void main(final String[] args) throws Exception { 7 final File file = new File("/tmp/xxx"); 8 file.delete(); 9 10 try (final ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file))) { 11 for (int i = 0; i < 10; i++) { 12 switch (i % 3) { 13 case 0: 14 oos.writeObject(Long.valueOf(System.nanoTime())); 15 break; 16 case 1: 17 oos.writeObject(LocalTime.now()); 18 break; 19 case 2: 20 oos.writeObject(UUID.randomUUID()); 21 break; 22 } 23 } 24 } 25 26 try (final ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file))) { 27 while (true) { 28 final Object obj = ois.readObject(); 29 System.out.println(String.format("debug: clz=%s, obj=%s", obj.getClass(), obj)); 30 if (obj instanceof LocalTime) { 31 // ... 32 } else if (obj instanceof Long) { 33 // ... 34 } else if (obj instanceof UUID) { 35 // ... 36 } 37 } 38 } catch (EOFException e) { 39 ; // 無視する 40 } 41 } 42}

投稿2021/05/04 14:36

shiketa

総合スコア4061

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問