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

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

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

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

Spring Boot

Spring Bootは、Javaのフレームワークの一つ。Springプロジェクトが提供する様々なフレームワークを統合した、アプリケーションを高速で開発するために設計されたフレームワークです。

Q&A

解決済

2回答

13747閲覧

CSVの改行を処理したい

tennis

総合スコア19

Java

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

Spring Boot

Spring Bootは、Javaのフレームワークの一つ。Springプロジェクトが提供する様々なフレームワークを統合した、アプリケーションを高速で開発するために設計されたフレームワークです。

0グッド

0クリップ

投稿2020/08/17 04:36

解決したいこと

JavaでCSVファイルを読み込む際に、改行が混じっていた場合の処理方法がわかりません。
添付した画像の自己PRのところです。
イメージ説明

出力結果

System.out.printlnで自己PRを出力すると、「"誰にも負けない」だけが表示され、
改行されている「心強さがあります」が表示されません。

※data[2]のところに自己PRが入っています。

java

1BufferedReader buf = new BufferedReader(new InputStreamReader(uploadFile.getInputStream())); 2 buf.readLine(); 3 4 int rowNumber = 1; 5 String line; 6 7 while ((line = buf.readLine()) != null) { 8 rowNumber++; 9 String[] data = line.split(",", -1); 10 11 System.out.println(data[2]); 12 13 }

試したこと

改行コードを置換するということを試したのですが、特に何も起こりませんでした。
環境はmacです。

java

1data[2].replaceAll("\n", "");

どのようにすれば「誰にも負けない心強さがあります」という一文を取得することができるのでしょうか。
ご教授のほど、よろしくお願いいたします。

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

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

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

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

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

guest

回答2

0

念のため

カラム数は10くらいあって、それを1つ1つ改行があるか検証して、あったら配列へ…ってやるのは現実的じゃない

改行の有無を検証すること自体が、そもそも不可能です。
改行毎に1行を読みこむので、その1行には改行コードは、ありません。

YakumoSakiさんの回答にある通り

質問者さんのコードだと readLine() でCSVを読み込んでいるので、誰にも負けないまでが1行

複数行読みこんでもカラムが足りない場合、結果的に改行されていると判断するしかありません。
また、そのカラムがどこ?っていうのを記録しておかない限りは、data[2]なのかdata[3]なのかも判断できません。

カンマとダブルクォートで、どの位置を判定しているかを記録しつつ・・・
と、本格的にやるなら、こんな対応(Java:CSVパーサを作る)が必要

ですが、本格的にやるなら、そもそも自前で書かずにcsvのライブラリ使った方がよいです。

簡易版は、コメントでも書きましたが、splitして規定のlengthにならないなら
次の行を読み込んで、連結後、splitをしてlengthの確認を繰り返す感じです。

java

1String s = "氏名,社員ID,自己PR,人材,5,6,7,8,9,10\n" + 2 "飯田次郎,1000,\"誰にも負けない\r" + 3 "心強さがあります。\",ああああ,5,6,7,8,9,10\n" + 4 "山田花子,1001,\"あああああああ\",ああああ,5,6,7,8,9,10\n" + 5 "テスト,1002,\"あ\r" + 6 "い\r" + 7 "う\",かきくけ,5,6,7,8,9,10\n" + 8 "桃太郎,1003,\"おこし\r" + 9 "煮つけ\r" + 10 "焚き火\r" + 11 "団子\",\"一つ\r" + 12 "わたし肉\r" + 13 "ださいな\",5,6,7,8,9,10"; 14 15BufferedReader buf = new BufferedReader(new StringReader(s)); 16buf.readLine(); // ヘッダーは読み飛ばし 17String line; 18String tmp = ""; 19int rowCnt = 0; 20int recCnt = 0; 21while ((line = buf.readLine()) != null) { 22 rowCnt++; 23 tmp = (tmp.length() == 0) ? line : tmp + "\n" + line; // 既存の分と連結 24 String[] data = tmp.split(",", -1); 25 26 // System.out.println(line); 27 if (data.length < 10) { 28 // 次の行を読む 29 } else { 30 recCnt++; 31 // CSV 1レコードが、そろった場合の処理 32 System.out.println(data[0] + ":" + data[1]); 33 System.out.println(data[2]); 34 System.out.println(data[3]); 35 System.out.println("----"); 36 tmp = ""; // 1レコード処理が終わったら、tmpをクリアする 37 } 38} 39System.out.println("csvレコード数 " + recCnt); 40System.out.println("改行数 " + rowCnt); 41

投稿2020/08/17 10:12

momon-ga

総合スコア4826

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

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

tennis

2020/08/18 23:48

サンプルコードありがとうございます!!CSVからの読み込みでこちらのコードを使用させていただいたところ、無事改行があってもデータを取得することができました。大変勉強になりました。ありがとうございます!!
guest

0

ベストアンサー

CSVファイルを見ていただくとおそらく次のようになっていると思います。

csv

1"飯田次郎","1000","誰にも負けない 2心強さがあります","あああ"

質問者さんのコードだと readLine() でCSVを読み込んでいるので、誰にも負けないまでが1行として取得されてしまっています。

ではどうすればいいかというと…
前提条件として、CSVファイル中の値が "" で囲まれていると仮定します。
""の中に出てきた改行は無視して続きを読む。みたいなコードを書く必要があります。

今回のコードをできるだけ替えないようにするならば、readLineで読み込んだあと、
" の数が奇数であれば次の行も読んで、結合した状態で再度チェックするみたいな処理でなんとかなると思います。

投稿2020/08/17 05:30

YakumoSaki

総合スコア2027

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

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

momon-ga

2020/08/17 06:21

String[] data = line.split(",", -1); の時点で、data.length が、想定の個数になっていないはずなので、想定した長さになるまで連結するでもいいかも。 ※データの中にカンマがないことが前提ですが。
tennis

2020/08/17 06:33 編集

回答ありがとうございます。冗長ではあるのですが、自己PRをつなげて取得することができました。お恥ずかしいコードなのですが、一応こんな感じで書きました。 StringBuilder sb = new StringBuilder(); if(data[2].contains("")) { sb.append(data[2]); sb.append(buf.readLine()); String str = sb.toString().replace("\"", ""); int index = str.indexOf(","); data[2] = str.substring(0,index); System.out.println(data[2]); }
tennis

2020/08/17 07:04 編集

ただ、これだと次の行にある「"あああ"」がdata[3]で取得することができなく、ArrayIndexOutOfBoundsExceptionが出てしまいます…。 > momon-gaさんの言う通り、 改行があるため、data.lengthをやると3となり、 自己PR以降のものがdataの中にないと判断されていました。
momon-ga

2020/08/17 07:24 編集

雑な実装ですが、data[2]と連結するのでなく、元のlineと連結してからsplitしてはどうでしょうか --- int rowNumber = 1; // 0始まりじゃなくていいの? String line; String tmp = ""; while ((line = buf.readLine()) != null) { rowNumber++; tmp = tmp + line; // 既存の分と連結 // あ、改行コードつけてなかった String[] data = tmp.split(",", -1); if (data.length < 4) { // 4はマジックナンバー CSVのカラム数に合わせて rowNumber--; } else { // CSV 1レコードが、そろった場合の処理 System.out.println(data[0] + ":" + data[1]); System.out.println(data[2]); // 必要に応じて前後のダブルクォートを削除 System.out.println(data[3]); System.out.println("----"); tmp = ""; // 1レコード処理が終わったら、tmpをクリアする } }
tennis

2020/08/17 07:20

すみません!rowNumberはここでは全然使ってませんでした…。エラーを返すときに、「◯行目の◇◇さんにエラーがあります」という文言の◯のところで使っているだけでした。紛らわしくてすみません…。
tennis

2020/08/17 07:46

実装ありがとうございます。 既存のlineをsysoutしてみたところ、 「飯田次郎,1000,"誰にも負けない」のように出力されました。 この時点で「心強さがあります。"」というのと、そのあとにある「あああ」が入っていません。 自分が書いたコードの sb.append(data[2]); sb.append(buf.readLine()); この部分でsbをsysoutしてみると、ここで 「"誰にも負けない心強さがあります。",あああああ」と取れます。 ここでダブルクウォートを外して、カンマまでの値を取れば data[2]には「誰にも負けない心強さがあります。」だけが入るのですが、 そのあとの「あああああ」をdata[3]で取れずに…
momon-ga

2020/08/17 08:05

えっと、その実装だと無理ですよ。<data[3]を取る 新しく、String[]を作成して、data[0]~data[1]までをコピーしたあとに、 data[2]のカンマの前までを、新しい配列の[2]へコピー data[2]のカンマのあとを新しい配列の[3]へコピー みたいなことやらないといけない。 あと、改行が1個の場合は、 sb.append(data[2]); sb.append(buf.readLine()); でもいいけど、2個以上ある場合は、つど sb.append(buf.readLine()); を、ループしないとダメなんだけど大丈夫だろうか。
tennis

2020/08/17 08:09

そうですよね…実際にはカラム数は10くらいあって、それを1つ1つ改行があるか検証して、あったら配列へ…ってやるのは現実的じゃないですよね…。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問