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

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

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

CSV(Comma-Separated Values)はコンマで区切られた明白なテキスト値のリストです。もしくは、そのフォーマットでひとつ以上のリストを含むファイルを指します。

Java

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

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

Q&A

解決済

3回答

975閲覧

javaでの表の作成

taka0145

総合スコア7

CSV

CSV(Comma-Separated Values)はコンマで区切られた明白なテキスト値のリストです。もしくは、そのフォーマットでひとつ以上のリストを含むファイルを指します。

Java

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

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

0グッド

0クリップ

投稿2021/10/10 06:24

編集2021/11/01 05:08

前提・実現したいこと

テキストファイルの情報を読み込みそれを基に、表を作成。

・テキストファイル
田中ゆうき,国語,80
佐藤かつひこ,数学,50

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

エラーメッセージ

該当のソースコード

java

1class Sample { 2 3 4 5 public static void main(String[] args)throws IOException { 6 7 File file = new File("Sample1.txt"); 8 ArrayList<String[]> lineList = new ArrayList<>(); 9 String az= "名前,国語,数学"; 10 lineList.add(az.split(",")); 11 12 try(BufferedReader br= Files.newBufferedReader(file.toPath(), StandardCharsets.UTF_8)){ 13 String line; 14 while ((line = br.readLine()) != null) { 15 lineList.add(line.split(",")); 16 } 17 } catch (IOException e) { 18 e.printStackTrace(); 19 } 20 21 String[][] data = lineList.toArray(new String[lineList.size()][]); 22 23 24 } 25 26 27 28}

試したこと

ここに問題に対して試したことを記載してください。

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

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

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

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

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

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

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

BeatStar

2021/10/10 07:07

Markdownの```がズレています。ご自身の質問を読んでみてください。
taka0145

2021/10/10 07:24

失礼しました。 訂正させていただきます。
BeatStar

2021/10/10 07:41

後、タイトルも変えた方がいいです。内容と一致していません。 確かに表を作ろうとしているようですが、『表の作り方』というより、 『どのようにテーブルに合わせてハイフン(-)を連続させるか』のように見えます。 内容とタイトルが乖離(かいり)していると回答者は戸惑いますよ。
taka0145

2021/10/10 07:48

分かりにくいタイトルで申し訳ありません。 訂正しました。
jimbe

2021/10/10 08:12

ご質問とコードの出来に差があるように感じられますが、このコードはご自身で作ったものでしょうか。
taka0145

2021/10/10 08:14

ネットに載っていたコードをアレンジしたもので、一から私が作ったものではないです。
dodox86

2021/10/10 08:21

結構これは難しい(面倒くさい)問題のはずなのですけど、count()メソッドで1バイト文字で行けるかどうか判定してそうなので、ここまで意識しようとしている割りには質問内容とレベルが合ってないかんじがしますね。(コードは追っていませんが)
jimbe

2021/10/10 08:22

なるほど。 コードをお読みになれば、各列の表示幅は maxWidth メソッドによって max 配列に入れられることがお分かりになると思います。 "-" の必要数は、各列の表示幅と縦線の数を足すことで計算できるのではないでしょうか。
taka0145

2021/10/10 08:42

ご返信ありがとうございます。 ご教授頂い方法でやってみたいと思います。
guest

回答3

0

点数のみを該当セルに入れる方法は主に二つ、データを読んだ時に編集するか、表示する時に編集するか、です。

読んだ時に編集する場合は、 lineList.add(line.split(",")); で直接 lineList に入れているのを変えて、必要な構造で add するようにします。

表示する時に変数する場合は、 writeLine の //2列目以降を右寄せ の中での k のループの時点で、line[j] を出力するか空白を出力するかを判断するようにします。
が、List をわざわざ 2次元配列にしているなどの構造から見て、読み込み時に変換したほうが良いと思います。


Sample クラスを活用するようにしてみました。
科目の表示順・追加等は Sample のコンストラクタで行ってください。
ex) Sample sample = new Sample("名前","国語","外国語","数学");

同一名のデータは、纏めます。
ex)

plain

1田中ゆうき,国語,80 2佐藤かつひこ,数学,50 3田中ゆうき,数学,30 4田中たくや,国語,60

plain

1| 名前 |国語|外国語|数学| 2+-----------------------------+ 3|田中ゆうき | 80| | 30| 4+-----------------------------+ 5|佐藤かつひこ| | | 50| 6+-----------------------------+ 7|田中たくや | 60| | | 8+-----------------------------+

java

1package teratail_java.q363724; 2 3import java.io.*; 4import java.nio.charset.StandardCharsets; 5import java.nio.file.Files; 6import java.util.*; 7 8public class Sample { 9 public static void main(String[] args) throws IOException { 10 Sample sample = new Sample("名前","国語","外国語","数学"); 11 File file = new File("Sample1.txt"); 12 try(BufferedReader br = Files.newBufferedReader(file.toPath(), StandardCharsets.UTF_8); ) { 13 for(String line; (line=br.readLine()) != null; ) { 14 String[] array = line.split(","); 15 sample.put(array[0], array[1], Integer.parseInt(array[2])); 16 } 17 sample.drawSheet(); 18 } catch (IOException e) { 19 e.printStackTrace(); 20 } 21 } 22 23 private List<String> headerList; 24 private int nameIndex; 25 private int[] maxWidth; 26 private Map<String,Student> studentMap = new HashMap<>(); 27 28 private static class Student { 29 final int number; 30 final String name; 31 private final Map<String,Integer> scoreMap = new HashMap<>(); 32 Student(int number, String name) { 33 this.number = number; 34 this.name = name; 35 } 36 void putScore(String subject, int score) { 37 scoreMap.put(subject, score); 38 } 39 boolean hasScore(String subject) { 40 return scoreMap.containsKey(subject); 41 } 42 int getScore(String subject) { 43 return scoreMap.get(subject); 44 } 45 } 46 47 Sample(String... header) { 48 headerList = Arrays.asList(header); 49 50 nameIndex = headerList.indexOf("名前"); 51 if(nameIndex < 0) throw new IllegalArgumentException("'名前' がありません"); 52 53 maxWidth = new int[headerList.size()]; 54 for(int i=0; i<headerList.size(); i++) { 55 maxWidth[i] = count(headerList.get(i)); 56 } 57 } 58 59 void put(String name, String subject, int score) { 60 Student s = studentMap.get(name); 61 if(s == null) { 62 s = new Student(studentMap.size()+1, name); //number は出現順にしておく 63 studentMap.put(name, s); 64 maxWidth[nameIndex] = Math.max(maxWidth[nameIndex], count(s.name)); 65 } 66 s.putScore(subject, score); 67 int i = headerList.indexOf(subject); 68 if(i >= 0 && i != nameIndex) maxWidth[i] = Math.max(maxWidth[i], count(""+score)); 69 } 70 71 void drawSheet() { 72 drawHeader(); 73 drawRowSeparator(); 74 studentMap.values().stream() 75 .sorted(Comparator.comparingInt(s -> s.number)) //number順に並び替え 76 .forEach(s -> { drawStudent(s); drawRowSeparator(); }); 77 } 78 79 private void drawHeader() { 80 StringJoiner sj = new StringJoiner("|","|","|"); 81 for(int i=0; i<headerList.size(); i++) { 82 sj.add(getCenteringString(headerList.get(i), maxWidth[i])); 83 } 84 System.out.println(sj.toString()); 85 } 86 87 private String getCenteringString(String str, int width) { 88 int space = width - count(str); 89 int pre = space / 2; 90 int post = space - pre; 91 return " ".repeat(pre)+str+" ".repeat(post); 92 } 93 94 private String rowSeparator; 95 private void drawRowSeparator() { 96 if(rowSeparator == null) { 97 StringJoiner sj = new StringJoiner("-","+","+"); 98 for(int i=0; i<maxWidth.length; i++) { 99 sj.add("-".repeat(maxWidth[i])); 100 } 101 rowSeparator = sj.toString(); 102 } 103 System.out.println(rowSeparator); 104 } 105 106 private void drawStudent(Student s) { 107 StringJoiner sj = new StringJoiner("|","|","|"); 108 for(int i=0; i<maxWidth.length; i++) { 109 if(i == nameIndex) { 110 sj.add(s.name + " ".repeat(maxWidth[i]-count(s.name))); //名前=左詰め 111 } else if(s.hasScore(headerList.get(i))) { 112 sj.add(String.format("%"+maxWidth[i]+"d", s.getScore(headerList.get(i)))); //得点=右詰め 113 } else { 114 sj.add(" ".repeat(maxWidth[i])); 115 } 116 } 117 System.out.println(sj.toString()); 118 } 119 120 //英数字、カタカナ、ひらがな、漢字の文字コードを分類する 121 public static int count(String str) { 122 int count = 0; 123 for(char c : str.toCharArray()) { 124 count += Character.UnicodeBlock.of(c) == Character.UnicodeBlock.BASIC_LATIN ? 1 : 2; 125 } 126 return count; 127 } 128}

投稿2021/10/10 08:46

編集2021/10/10 18:26
jimbe

総合スコア12756

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

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

taka0145

2021/10/10 09:02

splitで分割する方法しか存じ上げないのですが、「必要な構造でaddする」についてもう少しヒントをいただけないでしょうか? 勉強不足で申し訳ありません。
jimbe

2021/10/10 09:59

lineList.add(line.split(",")); は String[] a = line.split(","); lineList.add(a); と分割出来ます。これは具体的なデータから考えますと、 String line = "田中ゆうき,国語,80" の時、String[] a には a[0]="田中ゆうき", a[1]="国語", a[2]="80"・・・(A) と入り、lineList にそのまま入って表示されます。 lineList に入れてから以降は現状のままとすると、もし String[] a に a[0]="田中ゆうき", a[1]="80", a[2]=""・・・(B) と入れられれば、ご希望の表示になるはずですね。 つまり、 lineList.add(line.split(",")); を split と add に分割したうえで、split した結果 (A) を必要な構造 (B) になるように編集等してから add すれば良いのではないでしょうか。
taka0145

2021/10/10 12:14

ご返信ありがとうございます。 ご教授頂いたことを基に作成しました。 正しいのかわかりませんが... String line; while ((line = br.readLine()) != null) { String[] array = line.split(","); String num1 = array[1]; String num2 = array[2]; if(num1.equals("国語")){ array[1] = num2; array[2] = num1; array[2] = ""; }else if(num1.equals("数学")){ array[1] = ""; } lineList.add(array); }
guest

0

タイトルの「ハイフンを連続して表示させたい」についての回答です。
次のコードのどこにあるか見つけてください。

Java

1import java.util.ArrayList; 2import java.io.*; // IOExcepton, File, BufferedReader 3import java.nio.file.Files; 4import java.nio.charset.StandardCharsets; 5 6class Sample { 7 public static void main(String[] args) throws IOException { 8 File file = new File("Sample1.txt"); 9 ArrayList<String[]> lineList = new ArrayList<>(); 10 lineList.add("名前,国語,数学".split(",")); 11 int[] width = { 4, 4, 4 }; 12 String line; 13 try (BufferedReader br = Files.newBufferedReader(file.toPath(), 14 StandardCharsets.UTF_8)) { 15 while ((line = br.readLine()) != null) { 16 String[] s = line.split(","); 17 String[] t = { s[0], "", "" }; 18 if (s[1].equals("国語")) t[1] = s[2]; 19 if (s[1].equals("数学")) t[2] = s[2]; 20 for (int n, i = 0; i < 3; i++) 21 if ((n = count(t[i])) > width[i]) width[i] = n; 22 lineList.add(t); 23 } 24 } catch (IOException e) { 25 e.printStackTrace(); 26 return; 27 } 28 line = "+" + "-".repeat(width[0] + width[1] + width[2] + 2) + "+"; 29 drawHeader(lineList, width, line); 30 drawTable(lineList, width, line); 31 } 32 33 public static void drawHeader(ArrayList<String[]> a, int[] width, String line) { 34 String[] s = a.get(0); 35 System.out.println(line); 36 for (int i = 0; i < 3; i++) { 37 int w = count(s[i]); 38 int j = (width[i] - w) / 2, k = width[i] - j - w; 39 System.out.print("|" + " ".repeat(j) + s[i] + " ".repeat(k)); 40 } 41 System.out.println("|"); 42 System.out.println(line); 43 } 44 45 public static void drawTable(ArrayList<String[]> a, int[] width, String line) { 46 for (int i = 1; i < a.size(); i++) { 47 String[] s = a.get(i); 48 System.out.print("|" + s[0] + " ".repeat(width[0] - count(s[0]))); 49 System.out.print("|" + " ".repeat(width[1] - count(s[1])) + s[1]); 50 System.out.print("|" + " ".repeat(width[2] - count(s[2])) + s[2]); 51 System.out.println("|"); 52 System.out.println(line); 53 } 54 } 55 56 public static int count(String str) { 57 int count = 0; 58 for (int i = 0; i < str.length(); i++) { 59 var b = Character.UnicodeBlock.of(str.charAt(i)); 60 if (b.equals(Character.UnicodeBlock.BASIC_LATIN)) 61 count++; 62 else if (b.equals(Character.UnicodeBlock.KATAKANA) || 63 b.equals(Character.UnicodeBlock.HIRAGANA) || 64 b.equals(Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS)) 65 count += 2; 66 } 67 return count; 68 } 69}

投稿2021/10/10 14:23

kazuma-s

総合スコア8224

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

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

taka0145

2021/10/10 14:50

素晴らしい回答をありがとうございます。 lineのところで表示させているという認識で正しいでしょうか? まとめ方がきれいで大変勉強になります。 1つ質問させていただきたいのですが、 仮にテキストファイルに情報が追加された場合はどうなるのでしょうか?
kazuma-s

2021/10/10 16:23

追加された情報の具体例を示してください。
taka0145

2021/10/10 16:33

田中たくや,国語、60 テキストファイルにこのような情報が追加された際、特に処理を追加する必要はないのでしょうか?
kazuma-s

2021/10/10 16:40

「,」以外に「、」も区切りにしたいということでしょうか? 「田中たくや,国語,60」の間違いだったとして、なぜ自分で試してみないのですか?
taka0145

2021/10/10 16:46

申し訳ありません。私のミスです。 田中たくや,国語,60で合っております。 先ほどお伝えした情報や、科目数を増やしたりなどしているのですが、 エラーが出るので確認させていただきました。
guest

0

ベストアンサー

まず気になったのは『例外処理』関係。

try(BufferedReader br= Files.newBufferedReader(file.toPath(), StandardCharsets.UTF_8)){ String line; while ((line = br.readLine()) != null) { lineList.add(line.split(",")); } } catch (IOException e) { e.printStackTrace(); } String[][] data = lineList.toArray(new String[lineList.size()][]);

確かに動きはしますが、『なんのための例外処理』なのでしょうか。

例外処理は『ファイルが無かった場合』とかのように例外的な、『想定されていない』場合を対処するためのはずです。

でも上記コードだと、『ファイルが無い場合でも、リストを配列に変換する』とかの処理をしてしまいます。

ただし、今回の問題はここじゃないので中断します。

次に、質問にあるコードは絶対にダメだとは言いませんが、あまり良い傾向ではありませんね。
(別に悪く言うつもりはまったくありません)

参考1: なぜ読みやすいコードが必要なのか - コードの可読性を高める手法をサンプルで学ぶ
参考2: 良いコードとは slideshare
参考3: 他の人のコードが読みづらい理由でのmrasuさんのご回答

参考3でのmrasuさんのご回答で、

コードが読める人向け

コードが何をしたいかわからない。
直観に反した(「自分だったらこう書く」という物と違う)動きをしていて、動きが把握しづらい
データ変更と描画が同時に行われているなど、多数の状況を把握し続ける必要がある
というのがあるかなと思います。

と書かれています。これが私が初見で思ったことですねぇ。

ダメとは言いませんが、今回の場合、もっとシンプルに書けるはずです。
完璧なロジックはまだ思い浮かんでいませんが、ざっくりとしたロジックが思い浮かんでいます。(私の中で)

プログラミングっていうのは、出鱈目に書けばいいってものではありません。
プログラミングは現実世界のシミュレーションです。

なのでとりあず、プログラミングがとかは置いといて、現実世界で考えてみましょう。

田中ゆうき,国語,80 佐藤かつひこ,数学,50

というのを、

| 名前 |国語|数学| +----------------------+ |田中ゆうき | 80| | +----------------------+ |佐藤かつひこ| | 50| +----------------------+

の状態にするにはどうしますか? (なんかズレがあるようなのでこちらで適当に修正しています。違う所があるなら読みかえてください)

私なら、

1. 何を書くかを考える( 国語の方に書くのか、数学の方に書くのかとか ) 2. それぞれのセル(?)の長さはどういう風にするか(長さの基準等) 3. 文字はどのように並んでいるか(右揃え? 左揃え? センタリング? ) 4. 数字(国語の点数等)はどのように並んでいるか(〃) 5. 区切り線(?)の"+----+"のやつの長さはどうするか 6. 区切り線(?)の"|"はどのように入れるか(位置とか)

をそれぞれ考える。

つまり、規則性を見付けるのです。

何を書くか(= 1)は元のデータ "田中ゆうき,国語,80" とかの二番目から考える。

それぞれのセル云々(= 2) は『その列の最大行数から考える』。

文字や数字はどのように並んでいるか(= 3, 4)は『項目名は中央揃え、名前は左揃え、点数は右寄せ』。

"+---+" の長さ(= 5) は『レコード(*1)の長さ分』。
*1: ここでいうレコードは、一行分のデータ列(ただし"|"等も含めている)

6は2と一緒ですね。

次に実際にノートかホワイトボードかなんかに上記の表を書いてみましょう。

[Flow]: 1. Excelでいう列のそれぞれの最大行数を求める 2. (1)のそれぞれの長さを『最大値』として"名前"や"国語"等が中心に来るように書く 3. 以下を『書くものが無くなるまで』繰り返す 3.1. (2)で出来た行の最大の長さ分、"+---+" 的なものを書く 3.2. (2)と同様に『名前を左揃え』、『数字を右揃え』で書く 4. (3.1)と同様に線を引く

みたいな流れになるはずです。(まあ、実際には(3.1)と(3.2)が逆になるかもしれないが )

後はこれを実装すればいいだけです。

まだわかりにくい部分があれば、同じように流れを考える。

で、(3.1)での"+---+" のやつは、どの行?でも同じ長さですね。完全固定。
なので、一度定義すれば単に描画すればいいだけです。

と考えると、

[Flow] 1. 列のそれぞれの最大行数を計算する 2. ヘッダに相当する、"名前"等の部分を(1)を最大数としてセンタリングして表示 3. (2)の長さ分、"+---+"のような文字列を生成 4. 以下を『書くものが無くなるまで』繰り返す 4.1. (3)で生成した文字列を表示 4.2. (2)の要領で『左揃え』や『右揃え』で表示していく 5. (3)で生成した文字列を表示

のような感じになりますね。(順番が変わる可能性があるが)

[コメントにて]

1番の何を書くかを考えるについてですが、...

あ、それでもいいですよ。

とりあえず、一気に作るのではなく、少しづつ作っていってください。
自分の考えが正しいかどうかもそれでわかります。

投稿2021/10/10 08:23

編集2021/10/10 08:59
BeatStar

総合スコア4958

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

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

taka0145

2021/10/10 08:41

勉強不足で申し訳ありません。 1番の何を書くかを考えるについてですが、 for文のcontinueなどを用いて処理すると考えたのですが、実現可能でしょうか?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.46%

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

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

質問する

関連した質問