■概要
作成する処理の概要は以下の通り。
- 作成したCSVファイル(以降、実測値とする)を読み込む
- データ項目が期待値通りか確認する
- 1レコードずつ取得し、1カラムずつ一致している確認する
- CSVファイル内のデータについて、日付は対象外
なお、実測値および期待値については、それぞれMap(HashMap)に値を格納し、比較するものとする。
■CSVファイルのデータ項目
実測値および期待値のデータ項目は以下に示す。
なお、実測値および期待値は2種類用意する。
▼Case1:実測値に余剰なデータあり
・実測値
id | value1 | value2 | value3 | date (YYYYMMDD) |
---|---|---|---|---|
001 | hoge1 | huga1 | hgehuga1 | 20241102 |
002 | hoge9 | huga2 | hgehuga2 | 20241103 |
003 | hoge3 | huga9 | hgehuga3 | 20241104 |
004 | hoge4 | huga4 | hgehuga9 | 20241105 |
005 | hoge | huga | hgehuga | 20241106 |
009 | hoge9 | huga9 | hgehuga9 | 20241110 |
※2 日付は比較対象外
・期待値
id | value1 | value2 | value3 | date (YYYYMMDD) |
---|---|---|---|---|
001 | hoge1 | huga1 | hgehuga1 | 20241002 |
002 | hoge2 | huga2 | hgehuga2 | 20241003 |
003 | hoge3 | huga3 | hgehuga3 | 20241004 |
004 | hoge4 | huga4 | hgehuga4 | 20241005 |
005 | hoge5 | huga5 | hgehuga5 | 20241006 |
※2 日付は比較対象外
▼Case2:実測値に必要なデータなし(期待値に余剰データあり)
・実測値
id | value1 | value2 | value3 | date (YYYYMMDD) |
---|---|---|---|---|
001 | hoge1 | huga1 | hgehuga1 | 20241102 |
002 | hoge9 | huga2 | hgehuga2 | 20241103 |
003 | hoge3 | huga9 | hgehuga3 | 20241104 |
004 | hoge4 | huga4 | hgehuga9 | 20241105 |
005 | hoge | huga | hgehuga | 20241106 |
※2 日付は比較対象外
・期待値
id | value1 | value2 | value3 | date (YYYYMMDD) |
---|---|---|---|---|
001 | hoge1 | huga1 | hgehuga1 | 20241002 |
002 | hoge2 | huga2 | hgehuga2 | 20241003 |
003 | hoge3 | huga3 | hgehuga3 | 20241004 |
004 | hoge4 | huga4 | hgehuga4 | 20241005 |
005 | hoge5 | huga5 | hgehuga5 | 20241006 |
009 | hoge9 | huga9 | hogehuga9 | 20241010 |
※2 日付は比較対象外
■クラス図
実装するモジュールのクラス図を以下に示す。
■モジュールのディレクトリ階層
実装するモジュールのディレクトリ階層を以下に示す。
expectedvaluecheck
├── expected
│ └── expected.csv
├── input
│ └── case.csv
└── src
├── checker
│ └── InputExpectedChecker.java
├── constant
│ ├── CsvHeaderConstant.java
│ └── FilePathConstant.java
├── converter
│ └── CsvToHashMapConverter.java
├── main
│ └── ExpectedValueCheckMain.java
└── reader
└── CsvReader.java
■フローチャート
実装するモジュールのフローチャートを以下に示す。
▼メイン処理
ExpectedValueCheckMain.java
▼CSVファイル読み込み
CsvReader.java
▼CSVからHashMapへ変換
CsvToHashMapConverter.java
▼差分比較
InputExpectedChecker.java
・期待値 -> 実測値比較(expectedInputChecker)
・実測値 -> 期待値比較(inputExpectedChecker)
■サンプルコード
実装するモジュールのコードを以下に示す。
▼メイン処理
ExpectedValueCheckMain.java
package main;
import java.io.BufferedReader;
import java.util.HashMap;
import checker.InputExpectedChecker;
import constant.FilePathConstant;
import converter.CsvToHashMapConverter;
import reader.CsvReader;
public class ExpectedValueCheckMain {
public static void main(String[] args) {
// インプットファイル読み込み
BufferedReader inputFile = CsvReader.csvFileReader(FilePathConstant.INPUT_FILEPATH);
// HashMap形式でデータを格納
HashMap<Integer, HashMap<String, String>> inputDatas = CsvToHashMapConverter.resultHashMap(inputFile);
// 期待値ファイル読み込み
BufferedReader expectedFile = CsvReader.csvFileReader(FilePathConstant.EXPECTED_FILEPATH);
// HashMap形式でデータを格納
HashMap<Integer, HashMap<String, String>> expectedDatas = CsvToHashMapConverter.resultHashMap(expectedFile);
// 相互比較(期待値 -> 実測値)
InputExpectedChecker.expectedInputChecker(expectedDatas, inputDatas);
// 相互比較(実測値 -> 期待値)
InputExpectedChecker.inputExpectedChecker(expectedDatas, inputDatas);
}
}
▼CSVファイル読み込み
CsvReader.java
package reader;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import constant.FilePathConstant;
// CSVファイル読み込みクラス
public class CsvReader {
/*
* CSVファイル読み込み処理
*
* @input ファイルパス
*
* @return BufferedReader
*/
public static BufferedReader csvFileReader(final FilePathConstant path) {
try {
// ファイルオブジェクト生成
final File csvFile = new File(path.getFilePathConstant());
// FileReaderオブジェクト生成
final FileReader fReader = new FileReader(csvFile);
// BufferedReaderオブジェクトを返却
return new BufferedReader(fReader);
} catch (Exception e) {
System.out.println("csvFileReader例外エラー:" + e);
return null;
}
}
}
▼CSVからHashMapへ変換
CsvToHashMapConverter.java
package converter;
import java.io.BufferedReader;
import java.util.HashMap;
import constant.CsvHeaderConstant;
public class CsvToHashMapConverter {
/*
* csv -> HashMap変換処理
*
* @param csvFile csvファイル情報
*/
public static HashMap<Integer, HashMap<String, String>> resultHashMap(
final BufferedReader csvFile) {
// 返却用HashMap
final HashMap<Integer, HashMap<String, String>> result = new HashMap<>();
// データ件数カウンタ
int dataCount = 1;
// csvファイルの1行
String readLine = "";
// csvヘッダ部要素配列
final CsvHeaderConstant[] keys = CsvHeaderConstant.values();
// csvファイルが存在する場合
if (csvFile != null) {
try {
// csvファイルの中身を1行ずつ繰り返し
while ((readLine = csvFile.readLine()) != null) {
// ヘッダー部以外の場合
if (!readLine.contains(CsvHeaderConstant.ID.getCsvHeaderConstant())) {
// csvのデータを配列に格納
String[] items = readLine.split(",");
// データ部格納用HashMap
HashMap<String, String> data = new HashMap<>();
// csvヘッダ部配列要素分繰り返し
for (int i = 0; i < keys.length; i++) {
// {ヘッダ部要素名:csvのデータ}形式でデータを格納=データ部
data.put(keys[i].getCsvHeaderConstant(), items[i]);
}
// 返却用HashMap{データカウンタ:データ部}の形式で格納
result.put(dataCount, data);
// カウンタインクリメント
dataCount++;
}
}
} catch (Exception e) {
System.out.println("resultHashMap処理例外エラー:" + e);
}
}
return result;
}
}
▼差分比較
InputExpectedChecker.java
package checker;
import java.util.HashMap;
import constant.CsvHeaderConstant;
// 相互比較クラス
public class InputExpectedChecker {
/*
* 期待値 -> 実測値 比較処理
*
* @param expectedDatas 期待値HashMap
*
* @param inputDatas 実測値HashMap
*/
public static void expectedInputChecker(HashMap<Integer, HashMap<String, String>> expectedDatas,
HashMap<Integer, HashMap<String, String>> inputDatas) {
// チェックフラグ(true:比較OK、false:比較NG)
boolean isData = true;
// csvヘッダ部要素配列
final CsvHeaderConstant[] keyHeaders = CsvHeaderConstant.values();
System.out.println("##### 相互参照:期待値->実測値 #####");
// 期待値のキー項目分繰り返し
for (Integer keyCount : expectedDatas.keySet()) {
// チェックフラグ初期化
isData = true;
System.out.println("===== データ:" + keyCount + " =====");
// csvヘッダ部配列要素分繰り返し
for (CsvHeaderConstant keyHeader : keyHeaders) {
// ヘッダ部が日付の項目はチェック対象外
if (CsvHeaderConstant.TARGET_DATE.equals(keyHeader)) {
continue;
}
// 実測値にデータが存在しない場合
if (inputDatas.get(keyCount) == null) {
// 結果出力
System.out.println("*** " + keyHeader.getCsvHeaderConstant() + " ***");
System.out
.println("期待値:" + expectedDatas.get(keyCount).get(keyHeader.getCsvHeaderConstant()));
System.out.println("実測値:データなし");
// チェックフラグNG
isData = false;
// 期待値と実測値が異なる場合
} else if (!expectedDatas.get(keyCount).get(keyHeader.getCsvHeaderConstant())
.equals(inputDatas.get(keyCount).get(keyHeader.getCsvHeaderConstant()))) {
// 結果出力
System.out.println("*** " + keyHeader.getCsvHeaderConstant() + " ***");
System.out
.println("期待値:" + expectedDatas.get(keyCount).get(keyHeader.getCsvHeaderConstant()));
System.out
.println("実測値:" + inputDatas.get(keyCount).get(keyHeader.getCsvHeaderConstant()));
// チェックフラグNG
isData = false;
}
}
// チェックフラグOKの場合
if (isData) {
// 結果出力
System.out.println("OK");
}
}
}
/*
* 実測値 -> 期待値 比較処理
*
* @param expectedDatas 期待値HashMap
*
* @param inputDatas 実測値HashMap
*/
public static void inputExpectedChecker(HashMap<Integer, HashMap<String, String>> expectedDatas,
HashMap<Integer, HashMap<String, String>> inputDatas) {
// チェックフラグ(true:比較OK、false:比較NG)
boolean isData = true;
// csvヘッダ部要素配列
final CsvHeaderConstant[] keyHeaders = CsvHeaderConstant.values();
System.out.println("##### 相互参照:実測値->期待値 #####");
// 期待値のキー項目分繰り返し
for (Integer keyCount : inputDatas.keySet()) {
// チェックフラグセット
isData = true;
// 期待値が存在しない
if (expectedDatas.get(keyCount) == null) {
System.out.println("===== データ:" + keyCount + " =====");
// csvヘッダ部配列要素分繰り返し
for (CsvHeaderConstant keyHeader : keyHeaders) {
// 日付はスキップ
if (CsvHeaderConstant.TARGET_DATE.equals(keyHeader)) {
continue;
}
System.out.println("*** " + keyHeader.getCsvHeaderConstant() + " ***");
System.out.println("期待値:データなし");
System.out
.println("実測値:" + inputDatas.get(keyCount).get(keyHeader.getCsvHeaderConstant()));
// チェックフラグNG
isData = false;
}
}
}
// チェックフラグOKの場合
if (isData) {
// 結果出力
System.out.println("OK");
}
}
}
▼定数
CsvHeaderConstant.java
package constant;
public enum CsvHeaderConstant {
// ID
ID("id"),
// value1
VALUE1("value1"),
// value2
VALUE2("value2"),
// value3
VALUE3("value3"),
// 日付
TARGET_DATE("date(YYYYMMDD)");
// フィールド変数
private final String header;
// コンストラクタ
private CsvHeaderConstant(String header) {
this.header = header;
}
// ゲッター
public String getCsvHeaderConstant() {
return header;
}
}
FilePathConstant.java
package constant;
public enum FilePathConstant {
// インプットファイルパス
INPUT_FILEPATH("input/case.csv"),
// 期待値ファイルパス
EXPECTED_FILEPATH("expected/expected.csv");
// フィールド変数
private final String filePath;
// コンストラクタ
private FilePathConstant(String filePath) {
this.filePath = filePath;
}
// ゲッター
public String getFilePathConstant() {
return filePath;
}
}
■実行結果
▼Case1:実測値に余剰なデータあり
・実測値
id,value1,value2,value3,date(YYYYMMDD)
001,hoge1,huga1,hogehuga1,20241102
002,hoge9,huga2,hogehuga2,20241103
003,hoge3,huga9,hogehuga3,20241104
004,hoge4,huga4,hogehuga9,20241105
005,hoge,huga,hogehuga,20241106
009,hoge9,huga9,hogehuga9,20241110
・期待値
id,value1,value2,value3,date(YYYYMMDD)
001,hoge1,huga1,hogehuga1,20241002
002,hoge2,huga2,hogehuga2,20241003
003,hoge3,huga3,hogehuga3,20241004
004,hoge4,huga4,hogehuga4,20241005
005,hoge5,huga5,hogehuga5,20241006
・結果
##### 相互参照:期待値->実測値 #####
===== データ:1 =====
OK
===== データ:2 =====
*** value1 ***
期待値:hoge2
実測値:hoge9
===== データ:3 =====
*** value2 ***
期待値:huga3
実測値:huga9
===== データ:4 =====
*** value3 ***
期待値:hogehuga4
実測値:hogehuga9
===== データ:5 =====
*** value1 ***
期待値:hoge5
実測値:hoge
*** value2 ***
期待値:huga5
実測値:huga
*** value3 ***
期待値:hogehuga5
実測値:hogehuga
##### 相互参照:実測値->期待値 #####
===== データ:6 =====
*** id ***
期待値:データなし
実測値:009
*** value1 ***
期待値:データなし
実測値:hoge9
*** value2 ***
期待値:データなし
実測値:huga9
*** value3 ***
期待値:データなし
実測値:hogehuga9
▼Case2:実測値に必要なデータなし(期待値に余剰データあり)
・実測値
id,value1,value2,value3,date(YYYYMMDD)
001,hoge1,huga1,hogehuga1,20241102
002,hoge9,huga2,hogehuga2,20241103
003,hoge3,huga9,hogehuga3,20241104
004,hoge4,huga4,hogehuga9,20241105
005,hoge,huga,hogehuga,20241106
・期待値
id,value1,value2,value3,date(YYYYMMDD)
001,hoge1,huga1,hogehuga1,20241002
002,hoge2,huga2,hogehuga2,20241003
003,hoge3,huga3,hogehuga3,20241004
004,hoge4,huga4,hogehuga4,20241005
005,hoge5,huga5,hogehuga5,20241006
009,hoge9,huga9,hogehuga9,20241010
・結果
##### 相互参照:期待値->実測値 #####
===== データ:1 =====
OK
===== データ:2 =====
*** value1 ***
期待値:hoge2
実測値:hoge9
===== データ:3 =====
*** value2 ***
期待値:huga3
実測値:huga9
===== データ:4 =====
*** value3 ***
期待値:hogehuga4
実測値:hogehuga9
===== データ:5 =====
*** value1 ***
期待値:hoge5
実測値:hoge
*** value2 ***
期待値:huga5
実測値:huga
*** value3 ***
期待値:hogehuga5
実測値:hogehuga
===== データ:6 =====
*** id ***
期待値:009
実測値:データなし
*** value1 ***
期待値:hoge9
実測値:データなし
*** value2 ***
期待値:huga9
実測値:データなし
*** value3 ***
期待値:hogehuga9
実測値:データなし
##### 相互参照:実測値->期待値 #####
OK
コメント