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

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

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

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

Q&A

解決済

2回答

1444閲覧

Java:入力した数値(1-8)に対応する行を削除する(ファイル操作)

退会済みユーザー

退会済みユーザー

総合スコア0

Java

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

0グッド

0クリップ

投稿2018/05/30 17:12

前提・実現したいこと

こんばんは、Javaについての質問です。
とあるJavaの問題を学習中に途中で分からなくなってしまい、困っています。
お手数おかけしますが、お力お貸し頂けますと幸いです。よろしくお願いいたします。
下記が問題文となります。

問題文

数値(1-8)を入力させ、「sample.txt」の入力された行を削除する。 (1~8)以外が入力された場合はもう一度入力させること。 「sample.txt」の内容 あいうえお かきくけこ さしすせそ おえういあ 12 34 56 あ1

作成途中のソースコード

Java

1import java.io.BufferedReader; 2import java.io.BufferedWriter; 3import java.io.File; 4import java.io.FileReader; 5import java.io.FileWriter; 6import java.io.IOException; 7 8public class Insert2File { 9 public static void main(String[] args) throws IOException { 10 11 //書き込み用 12 File file = new File("sample.txt"); 13 FileWriter filewriter = new FileWriter(file); 14 BufferedWriter bw = new BufferedWriter(filewriter); 15 16 //読み込み 17 FileReader fr = new FileReader("sample.txt"); 18 BufferedReader br = new BufferedReader(fr); 19 20 //一行ずつ読み込んでいく 21 String line; 22 23 System.out.println("削除する行を入力してください"); 24 25 26 try { 27 28 for(int i = 1; (line = br.readLine()) != null; i++) { 29 30 switch (i) { 31 case 0: // あいうえお 32 bw.write(line); 33 bw.newLine(); 34 break; 35 36 case 1: // かきくけこ 37 bw.write(line); 38 bw.newLine(); 39 break; 40 41 case 2: // さしすせそ 42 bw.write(line); 43 bw.newLine(); 44 break; 45 46 case 3: // おえういあ 47 bw.write(line); 48 bw.newLine(); 49 break; 50 51 case 4: // 12 52 bw.write(line); 53 bw.newLine(); 54 break; 55 56 case 5: // 34 57 bw.write(line); 58 bw.newLine(); 59 break; 60 61 case 6: // 56 62 bw.write(line); 63 bw.newLine(); 64 break; 65 66 case 7: // あ1 67 bw.write(line); 68 bw.newLine(); 69 break; 70 71 72 } 73 74 bw.flush(); 75 bw.close(); 76 77 br.close(); 78 79 } 80 81 } catch (IOException e) { 82 System.out.println(e); 83} 84} 85} 86 87

実行したいこと等

現状のプログラムだとエラーは起こらずコンパイルは通りますが、テキストファイルには何も効果は効いておらず、何も変化はありませんでした。
問題文のイメージからとりあえず作成しようと試みてここまでは作成できた次第です。
まだ完成までの全体のイメージは掴みかねていますが、まずはここからswich文をどう効かせれば良いのか、また再入力を求めるにはwhile文を使用するとは思うのですがどこに使用すれば良いのかが分かりません。
ご教授くださいますと大変助かります。何卒よろしくお願いいたします。

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

Java
java version "1.8.0_161"

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

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

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

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

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

guest

回答2

0

テキストファイルには何も効果は効いておらず、何も変化はありませんでした。

そうでしょうか?ご質問のコードをそのまま動かすと元のテキストファイルの内容如何によらず必ず内容が全部消えてしまうと思います。

原因はプログラム開始直後にnew FileWriter(file);としているためです。これやると大抵のOSで(Linux, Macintosh, Windowsともに)元のファイルの中身は捨てられ0バイトのファイルになってしまうと思います。その同じファイルをnew FileReader(file)で開いてもそこからはもはや1行も入力できないと思います。

まずは方針を考え直したほうがよさそうです。ファイルを編集する平易な方法は

(1) 編集対象のファイルを入力用のストリーム(FileReaderなど)で開く。
(2) 編集結果を格納するファイルは別のファイル(一次ファイル)にする。
(3) 全ての編集結果を出力し終わったらファイルをクローズして元のファイルを削除し、一時ファイルを元のファイル名へrenameする。

他の方法も有り得ますが処理が難しくなります。まずは上記の平易な方法をトライしてみることをお奨めします。


なお・・・他にもおかしなところがあるので一応指摘しておきます。ただ、本題に直接関係ない(C)は本筋を解決してから取り組んだ方がよいかも知れません。一度にあれこれ考え始めると混乱するかもしれませんので。

(A) 削除対象行の入力処理漏れ
どの行を削除すべきか入力するコードが欠落しています。

(B)switch文
単純な繰り返し制御では処理しきれないような変則パターンを処理するときにこそswitch文を使うべきであって、規則的な処理の場合は使うべきでないと考えてください。Nが与えられていてN行目を削除するという仕様の場合は充分に規則的であり、switch文の出番はないと考えるべきです。
N行目を削除するには入力ファイルから全ての行を読み込み、N行目を除く全ての行を出力ファイルへコピーすればよいだけです。

(C)本題から外れますが少なくともJava7以降を前提にするならI/O処理ではtry-with-resource文を使うのが常道です。学習中と思いますので急がなくてもいいですが例外について学ぶ際にtry-with-resourceを使うべきという話を思い出していただければと思います。

投稿2018/05/30 18:30

KSwordOfHaste

総合スコア18394

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

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

退会済みユーザー

退会済みユーザー

2018/06/04 14:09

ご回答いただきありがとうございます。返信が遅くなり大変申し訳ございません。 テキストファイルにつきましては後にコンパイルしたところ、どうやら私の入力ミスだったようで、ご回答者さまのおっしゃる通り、もともと入っていたデータが全て消えてしまっていました。 キーボードからある一定の数値を用いて入力を求める際には、if~else文かswitch文を使用するものだと考えていたので、ご指摘いただきまた勉強になりました。 try-with-resource文はまだ例外の学習の途中のため、理解が及んでおりませんが、これからまた勉強していきたいと思います。 まだまだ未熟なコードに質問でしたが、ご指摘にご回答いただけて大変助かりました。ありがとうございました!
guest

0

ベストアンサー

こんにちは、
読み込んだデータの指定した行を消す方法を以下の方法でやりました。

(i)読み込んだデータをString型の文字列に変換する.
(ii)改行刻みで文字列を分割し[]Stringに格納する。
(iii)消去したい行を入力する。(再入力はdo~while文で処理する。)
(iv)for文で入力した数字以外をループさせ新たなファイルに書き込む

質問欄のテーマには

入力した数値(1-8)に対応する行を削除する

とありますが、配列は0から始まるので0-7となっています。
1-8にしたい場合は適宜ソースコードを書き換えてください。

また、読み込むファイルや新たに作るファイルの場所の指定も重要と思われます。
私の場合はc:\prog2\new.txt,"c:\prog2\new2.txt"にしていますが、適宜変更してください。

(ちなみにswitch文は使いませんでした.....)

java

1import java.io.*; 2import java.util.Scanner; 3 4public class Main{ 5 6 public static void main(String[] args) throws IOException { 7 String s = fileToString(new File("c:\prog2\new.txt")); 8 String []resultArray = s.split("\n"); 9 10 for(int i = 0; i < 8; i++){ 11 System.out.println(i + " " + resultArray[i]); 12 } 13 Scanner sc = new Scanner(System.in); 14 System.out.println("削除する行を入力してください"); 15 int n; 16 do{ 17 n = sc.nextInt(); 18 if(n < 0 || 7 < n){ 19 System.out.println("再入力してください。"); 20 } 21 }while(n < 0 || 7 < n ); 22 23 try { 24 // FileWriterクラスのオブジェクトを生成する 25 FileWriter file = new FileWriter("c:\prog2\new2.txt"); 26 // PrintWriterクラスのオブジェクトを生成する 27 PrintWriter pw = new PrintWriter(new BufferedWriter(file)); 28 29 //ファイルに書き込む 30 for(int i = 0; i < 8; i++){ 31 if(i != n){ 32 pw.println(resultArray[i]); 33 } 34 } 35 36 //ファイルを閉じる 37 pw.close(); 38 } catch (IOException e) { 39 e.printStackTrace(); 40 } 41 42 System.out.println("第" + n + "行が消去されました。"); 43 44 } 45 public static String fileToString(File file) throws IOException { //読み込んだデータをString型に変換するメソッド 46 BufferedReader br = null; 47 try { 48 49 br = new BufferedReader(new InputStreamReader(new FileInputStream(file))); 50 StringBuffer sb = new StringBuffer(); 51 int c; 52 53 while ((c = br.read()) != -1) { 54 sb.append((char) c); 55 } 56 57 return sb.toString(); 58 } finally { 59 60 br.close(); 61 } 62 } 63} 64 65

投稿2018/05/31 06:56

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

退会済みユーザー

退会済みユーザー

2018/06/04 14:10

ご回答いただきありがとうございます。返信が遅くなり大変申し訳ございません。 お教えいただいたコードを参考に、ファイルの指定や入力値の調整と修正を行い、想定していた通りの動きになりました。 キーボードからの入力を求める際には、if~else文かswitch文を使用するものだと考えていたので、do~while文を主に使用して記述する方法もあるのだとまたひとつ勉強になりました。 コードの解説や重要な点へのコメントも大変助かりました。ありがとうございました!
退会済みユーザー

退会済みユーザー

2018/06/08 02:03

すみません、今更ですが 行数の8のところをresultArray.lengthにすると行数がいくらになっても対応します。 int m = resultArray.length;を宣言し、コードの8のところをmにして、 do~while文の7のところをm - 1にします。 (最初lengthを使おうと思いましたがその時はlength()にしたためエラーになってしまい 定数8を書いていました。)
退会済みユーザー

退会済みユーザー

2018/06/13 16:37

返信が遅くなり申し訳ございません。また、ご丁寧にありがとうございます! ご教授いただき参考にさせていただいたコードの個人的な不明点は、あちこち調べて自己学習に励んでいたのですが、行数がいくらでも対応するようになる点は気がついておりませんでした…! ご指摘いただいて試してなるほどと思い、ますます勉強になりました。 また、こちらのコードに更に要素を加え、文字を入力した場合エラーを表示して再入力を求める時はdo-while文をtry-catchで囲むのでしょうか…? こちらに追加でご質問して良いのか迷っていたのですが、もしよろしければお力をお貸し頂けますと幸いです。繰り返し質問してしまい恐縮ですが、何卒よろしくお願いいたします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問