JAVAでCSVファイルの重複チェックについて

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 4,677

kumakumatan

score 154

CSVファイル内容
社員番号(ABC1582),社員名(漢字), 任意番号(124566),携帯番号(xxx-xxxx-xxxx)
配列にデータをセットして、重複している項目を表示させたく思います。
重複チェックで引っかかったものを例えば、「2行目と29行目の社員番号(値)が重複しています」と表示させたく思います。全ての列(A~D列)でチェックをしたく思います。
どのようにしたらいいでしょうか。
下記に途中まで作成したコードを記載します。
宜しくお願い致します。

package ren01;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.regex.Pattern;

public class read3 {

    public static void main(String[] args) {
        // ここにコードを挿入

        try {

            String path = new File(".").getAbsoluteFile().getParent();
            //System.out.println(path + "\\sample.csv");
            String path2 = (path + "\\sample.csv");
            //System.out.println(path2);

            // ファイルのパスを指定してオブジェクトを生成。
            //File file = new File("C:\\ws01\\ren01\\src\\ren01\\sample.csv");
            File file = new File(path2);

            // 入力ストリームを生成。( FileNotFoundException が発生 )
            FileInputStream input = new FileInputStream(file);
            /* 入力ストリームの読み込み。 ( UnsupportedEncodingException が発生 )
             * ここでCSVファイルの文字コードを設定しないと文字化けします。 */
            // 読み込むファイルの文字コード(SJIS)
            InputStreamReader stream = new InputStreamReader(input, "SJIS");
            // バッファに取り込み。

            BufferedReader buffer = new BufferedReader(stream);

            String line;
            int count = 0;

            /* readLine()でバッファの1行を取り出す作業を、読み込める行が無くなるまでwhile文で実行。
             * line = buffer.readline() でBufferedReaderが保持する一行を取出しているので、ループする毎に書き変わります。 */
            while((line = buffer.readLine()) != null) {
                // 取出した1行の文字セットを変換して新たに文字列を生成。
                byte[] b = line.getBytes();
                // String で UnsupportedEncodingException が発生 (変換したい文字コード:UTF-8)
                line = new String(b, "UTF-8");
                // 文字列をカンマ区切りで配列に分けて要素ごとに出力。
                // line.splitの第2引数に"-1"を指定しないと、他の行と要素数が
                // 違うため、出力結果の様にはなりません。
                String[] columns = line.split(",", -1);

                // 読み込み行数カウント
                count++;

                Pattern p1 = Pattern.compile("^[0-9]+$"); // 内線番号
                Pattern p2 = Pattern.compile("^[0-9]{3}-[0-9]{4}-[0-9]{4}$"); // 携帯番号
                //Pattern p3 = Pattern.compile("^[a-zA-Z]{3}[0-9]{4}$"); //社員番号(英数字)
                // 数字が含まれていればOK(社員番号)
                //Pattern p3 = Pattern.compile("^[^0-9]*$"); //社員番号(英数字)
                Pattern p4 = Pattern.compile("^[^\\d]+$"); // 簡単な正規表現(単純に数字が含まれていないというのを確認)

                for(int j = 0; j < columns.length; j++) {
                    //    System.out.println(j + " : " + columns[j]);

                    //データ型チェック開始
                    //if(j == 0 && p3.matcher(columns[j]).matches() == false) {
                    //    System.out.println(count + "行目の" + "(A列)がおかしい: " + columns[j]);
                    //} else if(j == 1 && p4.matcher(columns[j]).matches() == false) {
                    if(j == 1 && p4.matcher(columns[j]).matches() == false) {
                        System.out.println(count + "行目の" + "(B列)がおかしい: " + columns[j]);
                    } else if(j == 2 && p1.matcher(columns[j]).matches() == false) {
                        System.out.println(count + "行目の" + "(C列)がおかしい: " + columns[j]);
                    } else if(j == 3 && p2.matcher(columns[j]).matches() == false) {
                        System.out.println(count + "行目の" + "(D列)がおかしい: " + columns[j]);
                    }
                    //データ型チェック終了

                }

                //System.out.println("");

            }

            // 開いたストリームとバッファを閉じて関連するシステム・リソースを解放します。 ( IOException が発生 )
            input.close();
            stream.close();
            buffer.close();

        } catch (UnsupportedEncodingException | FileNotFoundException e) {
            e.printStackTrace();

        } catch (IOException e) {
            e.printStackTrace();

        }

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 2

checkベストアンサー

+2

1-社員クラスを作る、社員クラスは行番号,社員番号,社員名,任意番号,携帯番号のフィールドを持つ。
2-CSVを社員クラスのリストに変換
3-変換するタイミングで各項目の値をチェックする。。
4-出来上がった社員リストに対して重複
チェックをする。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/06/16 13:30

    各チェック項目をクラス化して、インスタンス化して、クラスを呼び出すようにしようと思います。
    「4-出来上がった社員リストに対して重複」の所がどうしたらいいか悩んでいます。
    「読み込み行数とそれに伴う配列までは表示」することができました。
    ここから先の項目名(列)に対しての重複チェックをして表示するところができなくて悩んでいます。下記にソースコードを記載しますので、ご教授いただければと思います。
    =========JAVAコード===========================
    package ren01;
    /*
    * 重複カウント
    */

    import java.io.BufferedReader;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.UnsupportedEncodingException;

    public class Distinct01 {
    //処理フラグ(0なら正常:1以上なら異常)
    int flg = 0;

    public static void main(String[] args) {
    // クラス化
    //public void method() {
    // ここにコードを挿入

    try {

    //String path = new File(".").getAbsoluteFile().getParent();
    //System.out.println(path + "\\sample.csv");
    //String path2 = (path + "\\sample.csv");
    //System.out.println(path2);

    // ファイルのパスを指定してオブジェクトを生成。
    File file = new File("C:\\ws01\\ren01\\src\\ren01\\sample.csv");
    //File file = new File(path2);

    // 入力ストリームを生成。( FileNotFoundException が発生 )
    FileInputStream input = new FileInputStream(file);
    /* 入力ストリームの読み込み。 ( UnsupportedEncodingException が発生 )
    * ここでCSVファイルの文字コードを設定しないと文字化けします。 */
    // 読み込むファイルの文字コード(SJIS)
    InputStreamReader stream = new InputStreamReader(input, "SJIS");
    // バッファに取り込み。

    BufferedReader buffer = new BufferedReader(stream);

    //変数定義
    //読み込み行
    String line;
    //読み込み件数
    int count = 0;
    //配列数
    //int len1 = 0;

    /* readLine()でバッファの1行を取り出す作業を、読み込める行が無くなるまでwhile文で実行。
    * line = buffer.readline() でBufferedReaderが保持する一行を取出しているので、ループする毎に書き変わります。 */
    while((line = buffer.readLine()) != null) {
    // 取出した1行の文字セットを変換して新たに文字列を生成。
    byte[] b = line.getBytes();
    // String で UnsupportedEncodingException が発生 (変換したい文字コード:UTF-8)
    line = new String(b, "UTF-8");
    // 文字列をカンマ区切りで配列に分けて要素ごとに出力。
    // line.splitの第2引数に"-1"を指定しないと、他の行と要素数が
    // 違うため、出力結果の様にはなりません。
    String[] columns = line.split(",", -1);

    // 読み込み行数カウント
    count++;
    //配列数定義
    //len1 = columns.length;
    //System.out.println(len1);

    for(int j = 0; j < columns.length; j++) {
    //for(int j = 0; j < 4; j++) {
    //System.out.println(j + " : " + columns[j]);
    System.out.println(count + "行目 : " + "配列番号:" + j + ":" + columns[j]);

    }
    System.out.println("");

    }
    //配列数表示
    //System.out.println(len1);
    //処理フラグ確認
    //System.out.println(flg);

    // 開いたストリームとバッファを閉じて関連するシステム・リソースを解放します。 ( IOException が発生 )
    input.close();
    stream.close();
    buffer.close();

    } catch (UnsupportedEncodingException | FileNotFoundException e) {
    e.printStackTrace();

    } catch (IOException e) {
    e.printStackTrace();

    }

    }

    }
    ==========================================

    キャンセル

  • 2016/06/16 13:45

    チェックをするたびにCSVを全て読み込むつもりですか?無駄が多いですね。

    クラスにするのは社員だと思いますよ。
    チェック処理をクラス化するのは良いことですが、渡すのは社員のリストにすべきだと思いますよ。

    また、「これから先の項目名」に対して、重複チェックを行うことは不可能です。先にCSVを全て読み込むしかありません。

    キャンセル

  • 2016/06/16 15:19

    具体的にどうするかご教授いただけないでしょうか?
    お願い致します。

    キャンセル

  • 2016/06/16 15:21

    回答の通りです。

    キャンセル

0

各項目と行番号のリストをセットにしたHashMapを使ってみては?

//こんな感じのMapを各項目について作成する
Map<String, List<Integer>> map = new HashMap<>();

//仮に名前についてやってみる(実際はループで処理?)
String name;  //名前
int i;  //行番号

List<Integer> list = map.get(name);
if(list == null) {
    list = new ArrayList<>();
    map.put(name, list);
}
list.add(i);
//この後、mapについてループし、Listのサイズが2以上になっているものが重複と判定できる

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

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