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

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

ただいまの
回答率

90.76%

  • Java

    13162questions

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

CSVファイルのデータ集計

解決済

回答 2

投稿

  • 評価
  • クリップ 1
  • VIEW 558

Welchs

score 1

前提・実現したいこと

javaでCSVファイルのデータを読み込み、カテゴリ別に価格の総合を計算し、その結果を画面に出力し、CSVファイルで保存したいです。

CSVファイルの読み込み内容
カテゴリー,商品,価格
食品,水,90
日用品,タオル,500
食品,弁当,500
日用品,ブラシ,600
家電品,冷蔵庫,60000
食品,バナナ,200
家電品,アイロン,7000
日用品,シャンプー,700

出力画面表示結果
カテゴリー,総合
食品:790
日用品:1800
家電品:67000

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

エラーメッセージ

該当のソースコード

```ここに言語を入力
ここにご自身が実行したソースコードを書いてください
package java_practice;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.StringTokenizer;

public class CSV {

public static void main(String args[]) {

try {
//ファイルを読み込む
FileReader fr = new FileReader("c:\\Users\\data.csv");
BufferedReader br = new BufferedReader(fr);

//読み込んだファイルを1行ずつ処理する
String line;
StringTokenizer token;
while ((line = br.readLine()) != null) {
//区切り文字","で分割する
token = new StringTokenizer(line, ",");

//分割した文字を画面出力する
while (token.hasMoreTokens()) {
System.out.println(token.nextToken());
}
System.out.println("******");
}

//終了処理
br.close();

} catch (IOException ex) {
//例外発生時処理
ex.printStackTrace();
}
}

}

試したこと

課題に対してアプローチしたことを記載してください
CSVファイルのデータを読み込むところまでできました。それ以下のコードの表し方に苦戦しています。

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

より詳細な情報

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

+2

hashmapにぶち込めばいいんじゃないかな?

HashMap<String,Integer> map=new HashMap<>();
while (token.hasMoreTokens()) {
  String cate=token.nextToken(); token.nextToken();
 Integer val=Integer.valueOf(token.nextToken());
 map.merge(cate,val,Integer::sum);//使えないなら普通に足すこと
}


問題点
想定している出力順と違う可能性がある
LinkedHashMap使おう

気になる点

例外発生時にbrが閉じられない

  • finally使う
  • try with resources使う

StringTokenizerはレガシークラス(新規での使用は勧められない)
String#split(String)使う
java.util.regix使う

上2つを直したやつ

try(BufferedReader br=new BufferedReader(new FileReader("c:\\Users\\data.csv"))){
  String[] header=br.readLine().split(",");//一行目見出し
  String line;
  while((line=br.readLine())!=null){
    HashMap<String,Integer> map=new HashMap<>();
    String[] token=line.split(",");
    String cate=token[0];
    Integer val=Integer.valueOf(token[2]);
    map.merge(cate,val,Integer::sum);
  }
  System.out.println(header[0]+",総合");
  map.forEach((k,v)->System.out.println(k+":"+v));
}catch(IOException ex){
  ex.printStackTrace();
}


問題点
想定していた出力順を得られない→解決策は同じ

一言

問題点は明確でない仕様のせいであるかないかわからなくなってます。
Java8な感じでも書こうと思ったけどヘッダー行のせいでメンドーなことに。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/01/16 01:44

    StringTokenizerはレガシークラスで、新規に使う際はString#splitを使うようドキュメントで指示されています。

    キャンセル

  • 2018/01/16 02:32

    回答を編集しました。
    ご指摘ありがとうございます。

    キャンセル

checkベストアンサー

+1

集約結果を出力するcsvファイル名が質問文では指定されていなかったので、grouped.csvという名前にしておきました。
集約結果を表示とwriteメソッドはStream APIを使った形に改良できそうな気がしますが・・・

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Map;
import java.util.Map.Entry;
import java.util.stream.Collectors;

public class Q109103 {

    public static void main(String[] args) {
        File data_file = new File("c:\\Users\\data.csv");
        File grouped_file = new File("c:\\Users\\grouped.csv");
        try {
            Map<String, Long> grouped = readAndgrouped(data_file);
            // 集約結果を表示
            grouped.forEach((k, v) -> System.out.println(k + ":" + String.valueOf(v)));
            // ファイルに出力
            write(grouped_file, grouped);
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    public static Map<String, Long> readAndgrouped(File data_file) throws IOException {
        try (BufferedReader br = Files.newBufferedReader(Paths.get(data_file.toURI()))) {
            Map<String, Long> grouped = br.lines().skip(1).map((String line) -> {
                String[] arr = line.split(",");
                return new CsvData(arr[0], arr[1], Long.parseLong(arr[2]));
            }).collect(Collectors.groupingBy(x -> x.category, Collectors.summingLong(x -> x.price)));
            return grouped;
        }
    }

    public static void write(File grouped_file, Map<String, Long> grouped) throws IOException {
        Charset encoding = Charset.forName("Windows-31j");
        try (BufferedWriter bw = Files.newBufferedWriter(Paths.get(grouped_file.toURI()), encoding)) {
            // ヘッダー行
            bw.write("カテゴリー,総合");
            bw.newLine();
            // データ行
            for (Entry<String, Long> entry : grouped.entrySet()) {
                bw.write(entry.getKey());
                bw.write(":");
                bw.write(String.valueOf(entry.getValue()));
                bw.newLine();
            }
        }
    }
}

class CsvData {
    final String category;
    final String subitem;
    final Long price;

    public CsvData(String category, String subitem, Long price) {
        this.category = category;
        this.subitem = subitem;
        this.price = price;
    }

    @Override
    public String toString() {
        String[] array = { this.category, this.subitem, String.valueOf(this.price) };
        return String.join(" ", array);
    }
}

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/01/16 09:31

    String lsep=System.lineSeparator();
    grouped.map((k,v)->k+":"+v+lsep).forEach(bw::write);
    こうですか?(なんかあまり良くなさげ)

    キャンセル

  • 2018/01/16 14:19

    回答ありがとうございます。
    Map<String, Long> grouped = readAndgrouped(data_file);

    Map<String, Long> grouped = br.lines().skip(1).map((String line) -> {
    String[] arr = line.split(",");
    return new CsvData(arr[0], arr[1], Long.parseLong(arr[2]));
    }).collect(Collectors.groupingBy(x -> x.category, Collectors.summingLong(x -> x.price)));
    の行で実行がうまくいかなかったです。
    変数のスコープを設定すればよいでしょうか?

    キャンセル

  • 2018/01/16 15:15

    例外の型とスタックトレースを書いてください。
    java.lang.NumberFormatExceptionでcsvがここからコピーしたままのものなら最後に空白が入ってるのが悪い。
    余計な空白(これも定義が難しいなぁ)に対応したいなら(ここでは三番目のキーの数字以外のものを余計なものとして処理する) Long.parseLong(arr[2].replaceAll("\\D","")));にするとか。

    キャンセル

  • 2018/01/16 22:49

    tsukkaさんへ
    コードのヘルプありがとうございました。
    Welchsさんへ
    1,あと可能性として有り得そうなのが入力ファイルのファイルエンコード形式が違うとかそーいう問題がありますが。エラーが発生した時のメッセージを追加してください。
    2,あくまでもこれはこういう書き方ができますよというサンプルソースコードなので、コードの意味を理解していないままそのまま取り込むのは大変危険な行為です。

    キャンセル

  • 2018/01/17 12:19

    集約するだけならわざわざCsvDataなんてクラスを作らなくてもいいような
    Map<String, Long> grouped = br.lines().skip(1).map(line -> line.split(","))

    .collect(Collectors.groupingBy(x -> x[0], Collectors.summingLong(y -> Long.parseLong(y[2]))));

    書いてて気付いた。summingLongのラムダの引数にxを使うと重複する。

    キャンセル

  • 2018/01/17 15:48

    皆様へ
    回答ありがとうございます。

    umyuさんへ
    1.こういうエラーメッセージが出ています。
    デバックでは、値を返すメソッドが存在しないとででいます。
    Exception in thread "main" java.io.UncheckedIOException: java.nio.charset.MalformedInputException: Input length = 1
    at java.io.BufferedReader$1.hasNext(BufferedReader.java:574)
    at java.util.Iterator.forEachRemaining(Iterator.java:115)
    at java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801)
    at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
    at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
    at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
    at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
    at scvfiledatacounting.File01.readAnddata2(File01.java:37)
    at scvfiledatacounting.File01.main(File01.java:22)
    Caused by: java.nio.charset.MalformedInputException: Input length = 1
    at java.nio.charset.CoderResult.throwException(CoderResult.java:281)
    at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:339)
    at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
    at java.io.InputStreamReader.read(InputStreamReader.java:184)
    at java.io.BufferedReader.fill(BufferedReader.java:161)
    at java.io.BufferedReader.readLine(BufferedReader.java:324)
    at java.io.BufferedReader.readLine(BufferedReader.java:389)
    at java.io.BufferedReader$1.hasNext(BufferedReader.java:571)
    ... 9 more
    2.ご指摘ありがとうございます。javaの勉強始めてまだ間もないですが、ソースコードの理解に、日々奮闘中です。

    キャンセル

  • 2018/01/17 16:06 編集

    エンコードがあってないって怒られてます。
    csvファイルのエンコードとCharset.forName("Windows-31j");のエンコードを合わせてください。
    もしUTF-8ならBOMを使っているのか確認すること。

    キャンセル

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

  • ただいまの回答率 90.76%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

  • 解決済

    Javaでcsvファイルを編集して出力したい

    タイトル通りですが、コーディングしたのですが、なかなか思い通りに行きません。 問題はこちらです。 下記部分をInput.csvとしてファイルを作成し、 英語の得点を全て+10した

  • 受付中

    csvの抽出条件について質問です

    csvファイルの読み込みにキーボード入力をした文字と一致するものを抽出させるプログラムをつくっています。 ただ読み込むだけならできるのですが、それに条件をつけると読み込めなくなりま

  • 受付中

    ファイルのコピー

    Java開発初心者です。 ファイルのコピーを行うコードを書いています。 FileInputStreamとFileOutputStreamを使って、 コピーしたいファイ

  • 受付中

    プログラムソースを教えて欲しいです

    前提・実現したいこと しりとりプログラムを作ろうとしています。 CSVデータ中の情報を読み込みデータ内の単語のみでしりとりを行います。 ルールとして ・CPUとの対戦型

  • 解決済

    javaでデータを読み込んでソートしたいのですがうまく来ません

    コンパイルするとエラーになって 「シンボルが見つかりません」と表示されます。 他にも問題があれば教えてください import java.io.File; import

  • 解決済

    Javaでarraylistを使って任意順のソートをしたい

    前提・実現したいこと CSVを読んで中身を変換、ソートして標準出力をしたい。 CSVの中身は 1 A100,yyyyMMdd,名前 S234,yyyyMMdd,名前

  • 解決済

    CSVからデータを取得して検索した文字列のみを表示したい

    プログラム初心者です。 Javaを勉強中で、質問があります。 CSVからデータを取得し、取得したデータの中から検索した文字列のみを表示するプログラムを作りたいです。

  • 解決済

    java リスト 並び替え

    テキストファイルからデータを読み込んで、ソート(金額順)をかけたいのですが、文字列で読み込んでいるため、金額でソートしようとしてもうまくいきません。 テキストデータは(1 H

同じタグがついた質問を見る

  • Java

    13162questions

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