Javaを使用してコンソールで操作するクイズアプリケーションを作成する方法を解説します。この記事では、オブジェクト指向プログラミングの原則を活用し、ファイル操作やユーザー入力処理を含む実践的なアプリケーション開発のプロセスを紹介します。
- 【Java】コンソールで操作するメモ帳アプリを作成(1/2)
- 【Java】コンソールで操作するメモ帳アプリを作成(2/2)
はじめに
この記事のコードをコピペしてEclipseで出力結果を確認してみよう!
コンソールで操作するメモ帳アプリ作成
以下のメモ帳アプリを作成します。
=== メモ帳アプリ ===
現在のメモ: なし
------------------------
1. 新規メモ作成
2. 既存のメモを開く
3. 現在のメモを保存
4. 現在のメモを編集
5. 終了
選択してください:
メモ帳アプリ操作ガイド
アプリケーションの起動:
- Javaがインストールされている環境で、メモ帳アプリケーションを実行します。
- コンソールにメニューが表示されます。
操作 | 選択肢 | 操作手順 | 結果 |
---|---|---|---|
1. 新規メモ作成 | 1 | ・1を入力してEnterキーを押す ・新しいメモの内容をコンソールに入力 ・空行を入力してEnterキーを押す(Enterキーを2回押す) | 新しいメモが作成される |
2. 既存のメモを開く | 2 | ・2を入力してEnterキーを押す ・ファイル選択ダイアログからファイルを選択 | 選択したファイルの内容が読み込まれ、コンソールに表示される |
3. 現在のメモを保存 | 3 | ・3を入力してEnterキーを押す ・ファイル保存ダイアログで保存先とファイル名を指定 | 現在のメモが指定した場所に保存される |
4. 現在のメモを編集 | 4 | ・4を入力してEnterキーを押す ・表示された内容を編集 ・編集終了後、空行を入力してEnterキーを押す(Enterキーを2回押す) ※ 最初の行に’cancel’と入力でキャンセル可能 | メモが更新される (キャンセル時は変更が反映されない) |
5. アプリケーションの終了 | 5 | ・5を入力してEnterキーを押す | アプリケーションが終了する |
このガイドに従って、簡単にメモ帳アプリケーションをご利用いただけます。必要に応じて新しいメモを作成したり、既存のメモを開いて編集・保存できます。
コード例
- クリックするとコードが表示されます。
Note.javaでメモデータの構造を実装
/**
* メモを表すクラス
*/
public record Note(String content) {
/**
* コンストラクタ
* @param content メモの内容
*/
public Note {
if (content == null) {
throw new IllegalArgumentException("Content cannot be null");
}
}
}
NotePadApp.javaでメインアプリケーションロジックとユーザーインターフェースを実装
import java.io.File;
import java.util.Scanner;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.filechooser.FileNameExtensionFilter;
/**
* メモ帳アプリケーションのメインクラス
*/
public class NotePadApp {
private final NoteManager noteManager;
private final Scanner scanner;
private final JFileChooser fileChooser;
/**
* NotePadAppのコンストラクタ
* 必要なオブジェクトの初期化を行う
*/
public NotePadApp() {
this.noteManager = new NoteManager();
this.scanner = new Scanner(System.in);
this.fileChooser = createCustomJFileChooser();
}
/**
* カスタマイズされたJFileChooserを作成する
*/
private JFileChooser createCustomJFileChooser() {
JFileChooser chooser = new JFileChooser() {
@Override
public void approveSelection() {
File selectedFile = getSelectedFile();
if (selectedFile.exists()) {
int response = JOptionPane.showConfirmDialog(this,
"ファイル '" + selectedFile.getName() + "' はすでに存在します。\n上書きしますか?",
"ファイルの上書き確認",
JOptionPane.YES_NO_OPTION,
JOptionPane.WARNING_MESSAGE);
if (response != JOptionPane.YES_OPTION) {
return;
}
}
super.approveSelection();
}
};
FileNameExtensionFilter filter = new FileNameExtensionFilter("テキストファイル", "txt");
chooser.setFileFilter(filter);
return chooser;
}
/**
* アプリケーションのメインループを実行する
*/
public void run() {
while (true) {
displayMenu();
int choice = scanner.nextInt();
scanner.nextLine(); // 改行文字を消費
switch (choice) {
case 1 -> createNewNote();
case 2 -> openExistingNote();
case 3 -> saveCurrentNote();
case 4 -> editCurrentNote();
case 5 -> {
System.out.println("アプリケーションを終了します。");
return;
}
default -> System.out.println("無効な選択です。もう一度お試しください。");
}
}
}
/**
* メインメニューを表示する
*/
private void displayMenu() {
System.out.println("\n=== メモ帳アプリ ===");
displayCurrentNoteInfo();
System.out.println("1. 新規メモ作成");
System.out.println("2. 既存のメモを開く");
System.out.println("3. 現在のメモを保存");
System.out.println("4. 現在のメモを編集");
System.out.println("5. 終了");
System.out.print("選択してください: ");
}
/**
* 現在のメモの情報を表示する
*/
private void displayCurrentNoteInfo() {
Note currentNote = noteManager.getCurrentNote();
String fileName = noteManager.getCurrentFileName();
if (currentNote != null) {
System.out.println("現在のメモ:");
System.out.println("ファイル名: " + (fileName != null ? fileName : "未保存"));
System.out.println("内容:");
System.out.println(currentNote.content());
System.out.println("------------------------");
} else {
System.out.println("現在のメモ: なし");
System.out.println("------------------------");
}
}
/**
* 新規メモを作成する
*/
private void createNewNote() {
System.out.println("新しいメモの内容を入力してください。入力が終わったら空行を入力してEnterキーを押してください:");
StringBuilder content = new StringBuilder();
String line;
while (!(line = scanner.nextLine()).isEmpty()) {
content.append(line).append("\n");
}
noteManager.setCurrentNote(new Note(content.toString().trim()));
noteManager.setCurrentFileName(null);
System.out.println("新しいメモが作成されました。");
}
/**
* 既存のメモを開く
*/
private void openExistingNote() {
int result = fileChooser.showOpenDialog(null);
if (result == JFileChooser.APPROVE_OPTION) {
File selectedFile = fileChooser.getSelectedFile();
try {
noteManager.loadNote(selectedFile.getAbsolutePath());
noteManager.setCurrentFileName(selectedFile.getName());
System.out.println("メモを開きました: " + selectedFile.getName());
} catch (Exception e) {
System.out.println("エラー: " + e.getMessage());
}
}
}
/**
* 現在のメモを保存する
*/
private void saveCurrentNote() {
if (noteManager.getCurrentNote() == null) {
System.out.println("保存するメモがありません。");
return;
}
int result = fileChooser.showSaveDialog(null);
if (result == JFileChooser.APPROVE_OPTION) {
File selectedFile = fileChooser.getSelectedFile();
// ファイル名に .txt 拡張子を追加(必要な場合)
if (!selectedFile.getName().toLowerCase().endsWith(".txt")) {
selectedFile = new File(selectedFile.getParentFile(), selectedFile.getName() + ".txt");
}
try {
noteManager.saveNote(selectedFile.getAbsolutePath());
noteManager.setCurrentFileName(selectedFile.getName());
System.out.println("メモを保存しました: " + selectedFile.getName());
} catch (Exception e) {
System.out.println("エラー: " + e.getMessage());
}
}
}
/**
* 現在のメモを編集する
*/
private void editCurrentNote() {
if (noteManager.getCurrentNote() == null) {
System.out.println("編集するメモがありません。新規メモを作成するか、既存のメモを開いてください。");
return;
}
System.out.println("現在のメモ内容を編集します。編集が終わったら空行を入力してください。");
System.out.println("編集をキャンセルする場合は、最初の行に 'cancel' と入力してください。");
System.out.println("現在の内容:");
System.out.println(noteManager.getCurrentNote().content());
StringBuilder newContent = new StringBuilder();
String line = scanner.nextLine();
if ("cancel".equalsIgnoreCase(line.trim())) {
System.out.println("編集をキャンセルしました。");
return;
}
newContent.append(line).append("\n");
while (!(line = scanner.nextLine()).isEmpty()) {
newContent.append(line).append("\n");
}
noteManager.setCurrentNote(new Note(newContent.toString().trim()));
System.out.println("メモが更新されました。");
}
}
NoteManager.javaでメモの管理機能を実装し、ファイル操作の基本
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
/**
* メモの管理を行うクラス
*/
public class NoteManager {
private Note currentNote;
private String currentFileName;
/**
* 現在のメモを取得
* @return 現在のメモ
*/
public Note getCurrentNote() {
return currentNote;
}
/**
* 現在のメモを設定
* @param note 設定するメモ
*/
public void setCurrentNote(Note note) {
this.currentNote = note;
}
/**
* 現在のファイル名を取得
* @return 現在のファイル名
*/
public String getCurrentFileName() {
return currentFileName;
}
/**
* 現在のファイル名を設定
* @param fileName 設定するファイル名
*/
public void setCurrentFileName(String fileName) {
this.currentFileName = fileName;
}
/**
* メモをファイルから読み込む
* @param fileName 読み込むファイル名
* @throws IOException ファイル読み込みエラー時
*/
public void loadNote(String fileName) throws IOException {
Path path = Paths.get(fileName);
String content = Files.readString(path);
this.currentNote = new Note(content);
this.currentFileName = path.getFileName().toString();
}
/**
* 現在のメモをファイルに保存
* @param fileName 保存するファイル名
* @throws IOException ファイル書き込みエラー時
*/
public void saveNote(String fileName) throws IOException {
if (currentNote == null) {
throw new IllegalStateException("No note to save");
}
Path path = Paths.get(fileName);
Files.writeString(path, currentNote.content());
this.currentFileName = path.getFileName().toString();
}
}
Main.javaで開始地点を実装
/**
* メモ帳アプリケーションのメインクラス
*/
public class Main {
/**
* アプリケーションのエントリーポイント
* @param args コマンドライン引数(使用しない)
*/
public static void main(String[] args) {
NotePadApp app = new NotePadApp();
app.run();
}
}
NoteManager.javaの解説
インポート文
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
これらは必要なクラスをインポートしています:
IOException
: 入出力操作に関連する例外を処理するために使用Files
,Path
,Paths
: ファイル操作を行うためのモダンなJava NIO API
クラス定義
/**
* メモの管理を行うクラス
*/
public class NoteManager {
// ...
}
これはNoteManager
クラスの定義です。JavaDocコメントでクラスの目的を説明しています。
フィールド
private Note currentNote;
private String currentFileName;
これらはクラスのメンバー変数(フィールド)です:
currentNote
: 現在編集中のメモを保持currentFileName
: 現在のファイル名を保持
ゲッターとセッター
/**
* 現在のメモを取得
* @return 現在のメモ
*/
public Note getCurrentNote() {
return currentNote;
}
/**
* 現在のメモを設定
* @param note 設定するメモ
*/
public void setCurrentNote(Note note) {
this.currentNote = note;
}
/**
* 現在のファイル名を取得
* @return 現在のファイル名
*/
public String getCurrentFileName() {
return currentFileName;
}
/**
* 現在のファイル名を設定
* @param fileName 設定するファイル名
*/
public void setCurrentFileName(String fileName) {
this.currentFileName = fileName;
}
これらはゲッターとセッターメソッドです:
currentNote
とcurrentFileName
のアクセスと変更を可能にします- カプセル化の原則に従っています
メモの読み込み
メソッド定義
/**
* メモをファイルから読み込む
* @param fileName 読み込むファイル名
* @throws IOException ファイル読み込みエラー時
*/
public void loadNote(String fileName) throws IOException {
// ...
}
- これは
loadNote
というパブリックメソッドです。 - ファイルからメモを読み込む機能を提供します。
- JavaDocコメントでメソッドの目的、パラメータ、例外を説明しています。
throws IOException
は、このメソッドがIOExceptionを発生させる可能性があることを示しています。
ファイルパスの作成
Path path = Paths.get(fileName);
Paths.get()
メソッドを使用して、ファイル名からPath
オブジェクトを作成します。Path
は、ファイルシステム内のファイルやディレクトリの場所を表します。
ファイルの内容を読み込む
String content = Files.readString(path);
Files.readString()
メソッドを使用して、ファイルの内容を一度に全て読み込みます。- 読み込んだ内容は
String
としてcontent
変数に格納されます。
新しいNoteオブジェクトの作成
this.currentNote = new Note(content);
- 読み込んだ内容を使用して、新しい
Note
オブジェクトを作成します。 - この新しいオブジェクトを
currentNote
フィールドに代入します。
現在のファイル名の設定
this.currentFileName = path.getFileName().toString();
path.getFileName()
でファイル名部分のみを取得し、それを文字列に変換します。- 取得したファイル名を
currentFileName
フィールドに設定します。
重要なポイント:
- 例外処理: このメソッドは
IOException
をスローすることを宣言しています。呼び出し元でこの例外を適切に処理する必要があります。 - Java NIO API:
Path
、Paths
、Files
クラスを使用して、モダンなファイル操作を行っています。 - ファイル読み込み:
Files.readString()
を使用して、ファイルの内容を効率的に読み込んでいます。 - 状態管理: 読み込んだ内容を新しい
Note
オブジェクトとして保存し、現在のファイル名も更新しています。 - メソッドの単一責任: このメソッドは「ファイルからメモを読み込む」という単一の責任を持っています。
このコードは、Java NIOを使用したファイル操作の良い例です。効率的なファイル読み込み、適切な例外処理、そしてオブジェクト指向プログラミングの原則(新しいNote
オブジェクトの作成)を示しています。また、メソッドの責任が明確で、再利用性が高いコードとなっています。
メモの保存
メソッド定義
/**
* 現在のメモをファイルに保存
* @param fileName 保存するファイル名
* @throws IOException ファイル書き込みエラー時
*/
public void saveNote(String fileName) throws IOException {
// ...
}
- これは
saveNote
というパブリックメソッドです。 - 現在のメモをファイルに保存する機能を提供します。
- JavaDocコメントでメソッドの目的、パラメータ、例外を説明しています。
throws IOException
は、このメソッドがIOExceptionを発生させる可能性があることを示しています。
保存するメモの存在確認
if (currentNote == null) {
throw new IllegalStateException("No note to save");
}
- 現在のメモが存在するかどうかをチェックします。
- メモがない場合(
currentNote
がnull
の場合)、IllegalStateException
をスローします。 - これは、メソッドの前提条件を確認する重要なステップです。
ファイルパスの作成
Path path = Paths.get(fileName);
Paths.get()
メソッドを使用して、ファイル名からPath
オブジェクトを作成します。Path
は、ファイルシステム内のファイルやディレクトリの場所を表します。
ファイルへの書き込み
Files.writeString(path, currentNote.content());
Files.writeString()
メソッドを使用して、メモの内容をファイルに書き込みます。currentNote.content()
で現在のメモの内容を取得し、それをファイルに書き込みます。
現在のファイル名の更新
this.currentFileName = path.getFileName().toString();
path.getFileName()
でファイル名部分のみを取得し、それを文字列に変換します。- 取得したファイル名を
currentFileName
フィールドに設定します。
重要なポイント:
- 例外処理:
- このメソッドは
IOException
をスローすることを宣言しています。 - また、不適切な状態(メモがない)の場合に
IllegalStateException
をスローします。
- このメソッドは
- Java NIO API:
Path
、Paths
、Files
クラスを使用して、モダンなファイル操作を行っています。 - ファイル書き込み:
Files.writeString()
を使用して、ファイルへの書き込みを効率的に行っています。 - 状態チェック: メソッドの開始時に現在のメモの存在を確認し、不正な操作を防いでいます。
- 状態管理: 保存後に現在のファイル名を更新しています。
- メソッドの単一責任: このメソッドは「現在のメモをファイルに保存する」という単一の責任を持っています。
このコードは、Java NIOを使用したファイル操作、適切な例外処理、そして堅牢なプログラミング(前提条件のチェック)の良い例です。また、メソッドの責任が明確で、再利用性が高いコードとなっています。
Main.javaの解説
クラス定義
/**
* メモ帳アプリケーションのメインクラス
*/
public class Main {
// ...
}
- これは
Main
クラスの定義です。 public
キーワードは、このクラスが他のクラスからアクセス可能であることを示します。- クラス名の上にある部分はJavaDocコメントで、クラスの目的を説明しています。
main メソッド
/**
* アプリケーションのエントリーポイント
* @param args コマンドライン引数(使用しない)
*/
public static void main(String[] args) {
// ...
}
- これは
main
メソッドで、Javaアプリケーションのエントリーポイント(開始点)です。 public
: このメソッドが外部からアクセス可能であることを示します。static
: このメソッドがクラスに属し、インスタンス化せずに呼び出せることを示します。void
: このメソッドが値を返さないことを示します。String[] args
: コマンドライン引数を受け取るための配列です(この場合は使用していません)。
アプリケーションの実行
NotePadApp app = new NotePadApp();
app.run();
NotePadApp
クラスの新しいインスタンスを作成しています。app.run()
を呼び出して、アプリケーションを開始しています。
重要なポイント:
- メインクラス: このクラスは、アプリケーションの起動点として機能します。
- main メソッド: Javaアプリケーションを実行する際に、JVMが最初に呼び出すメソッドです。
- インスタンス化:
NotePadApp
クラスのインスタンスを作成することで、アプリケーションのメイン機能を初期化しています。 - メソッド呼び出し:
run()
メソッドを呼び出すことで、アプリケーションの主要な処理を開始しています。 - シンプルな構造: このクラスは非常にシンプルで、アプリケーションの開始のみを担当しています。実際の機能は
NotePadApp
クラスに実装されています。
このコードは、Javaアプリケーションの標準的な開始方法を示しています。Main
クラスは、アプリケーションの他の部分(この場合はNotePadApp
)を初期化し、実行するための橋渡し役として機能します。これにより、アプリケーションの構造が整理され、メイン処理を別のクラス(NotePadApp
)に集中させることができます。
まとめ
- NoteManager.javaでメモの管理機能を実装し、ファイル操作の基本
- Main.javaでメインアプリケーションロジックとユーザーインターフェースを実装
- ファイル読み書きの実装方法、データの永続化について
- 例外処理を通じて、堅牢なエラーハンドリングの実装方法
- オブジェクト指向設計の原則を実践し、モジュール化されたコードの書き方
- ユーザー入力の処理とコンソールベースのインターフェース設計
NoteManagerクラスの実装を通じて、ファイル操作とデータ管理の基本的な概念を学ぶことができます。これは多くのアプリケーション開発で必要とされる重要なスキルです。
また、追加の機能(例:メモの検索、タグ付け、複数ユーザー対応など)を実装することで、さらに複雑なアプリケーションへと発展させることができます。
コメント