본문 바로가기

Spring

[220213] csv 파일 읽기

1. openCSV 라이브러리 사용

pom.xml에 추가

<!-- https://mvnrepository.com/artifact/net.sf.opencsv/opencsv -->
		<dependency>
		    <groupId>net.sf.opencsv</groupId>
		    <artifactId>opencsv</artifactId>
		    <version>2.3</version>
		</dependency>

 

2. 문자를 하나도 포함하지 않는 유효 라인의 최소, 최대, 합계, 평균, 표준편차, 중간값 구하기

package com.lmry.home.test1.controller;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

import au.com.bytecode.opencsv.CSVReader;

@Controller
public class Test1Controller {
	private static final Logger logger = LoggerFactory.getLogger(Test1Controller.class);
	
	@RequestMapping(value = "/test1", method = RequestMethod.GET)
	public String test1() {
		
		return "test/test1";
	}
	
	@RequestMapping(value = "/test1.do", method = RequestMethod.GET)
	public String test1(HttpServletRequest request, Model model) {
		logger.info("method: GET, test1(), 테스트1 페이지 요청");
		System.out.println("테스트");
		String simple = request.getParameter("simple");
		//csv 파일 읽기
		String fileName = "sample.csv";
		if(simple != null) {
			fileName = "tttt.csv";
		}
		final String filePath = request.getServletContext().getRealPath("/resources/csv/");

		int tot = 0; //계산 범위에 들어가는 총 라인의 갯수 (행의 갯수)
		int calculated = 0;
		StringBuffer nan = new StringBuffer();
		boolean flag; //문자를 포함하는 열이 없는 유효 라인이면 계산하기 위함
		
		//계산 결과를 모아서 view에 뿌려주기 위해 리스트 선언
		List<double[]> datas = new ArrayList<double[]>();
		double min, max, sum, avg, std, med = 0;
		
		CSVReader reader;
		try {
			reader = new CSVReader(new FileReader(filePath+fileName));
			String [] name = reader.readNext(); //첫 줄(p0 ~ p9)은 탐색이 필요 없으므로 while문을 돌지 않도록 한다.
	        String [] nextLine;

	        //readNext()로 CSV 파일을 한줄씩 읽는다. 행의 개수만큼 배열이 리턴된다.
	        while ((nextLine = reader.readNext()) != null) {
	        	tot++;
	        	flag = true; //한 라인 for문으로 문자열 탐색이 끝나면 true로 초기화해야 함 
	            for (int i = 0; i < nextLine.length; i++) { //모든 행 탐색
	               // System.out.println(i + " " + nextLine[i]);
	                //숫자가 아닌 컬럼값을 가진 오류 행 거르기
	                //5gh0 이런식으로 작성된 경우도 있을 수 있으므로 한 문자씩 판단한다.
	                char[] cArr = nextLine[i].toCharArray(); //한 행 = String[](문자열 배열), 인덱스로 한 칸(문자열)씩 쪼개서 판별 
	                for(int j = 0; j < cArr.length; j++){
	                    if(cArr[j] > '9' || cArr[j] < '0'){ //'0'~'9' 사이(0123456789)가 아니라면(숫자아님)
	                        System.out.println("숫자가 아닌 값을 가진 컬럼값 ->" + String.valueOf(cArr));
	                        nan.append(String.valueOf(cArr[j]));
	                        flag = false;
	                    } 
	                }
	            }
	            if(flag) {
                	//무사통과했을때 여기에서 최대최소등등 원하는것계산한다.
	            	calculated++;
                	min = minMax(nextLine)[0];
                	max = minMax(nextLine)[1];
                	sum = sum(nextLine);
                	avg = sum/nextLine.length;
                	std = std(nextLine, avg);
                	med = med(nextLine);
                	//구한 결과 리스트에 저장
                	datas.add(new double[]{min,max,sum,avg,std,med});                	
                }
	            System.out.println(" ");
	           // tot = nextLine.length - 1;  이거 아님 이건 열의 값(한 라인의 String 배열의 길이)이지 행의 값 아님
	        }
            System.out.println("The total Lines : " + tot);
            System.out.println("The calculated Lines : " + calculated);
            System.out.println("The error values : " + nan);
            model.addAttribute("datas", datas);
            model.addAttribute("tot", tot);
            model.addAttribute("calculated", calculated);
            model.addAttribute("nan", nan);
            
		} catch (FileNotFoundException e) {
			System.out.println("읽기 작업을 수행할 파일을 찾을 수 없습니다.");
		}
		catch (IOException e) {
			System.out.println("읽기 작업중 문제가 발생하였습니다.");
		}

		return "test/test1";
	}

	//최소값 최대값 구하기
    private double[] minMax(String[] s) {
        double[] minMax = {Double.parseDouble(s[0]), Double.parseDouble(s[0])};
        for(int i = 1; i < s.length; i++){
            minMax[0] = Math.min(minMax[0],Double.parseDouble(s[i]));
            minMax[1] = Math.max(minMax[1],Double.parseDouble(s[i]));
        }
        return minMax;
    }
    //합계
    private double sum(String[] s) {
        double sum = 0;
        for(int i = 0; i < s.length; i++){
            sum += Double.parseDouble(s[i]);
        }
 
        return sum;
    }
    //표준편차
    private double std(String[] s, double avg) {
        double std = 0;
        double d = 0;
        for(int i = 0; i < s.length; i++){
        	//각 값에서 평균값을 뺀 후 제곱한 값을 모두 더한다.
        	d += Math.pow((Double.parseDouble(s[i]) - avg), 2);
    	}
        //더한 값을 모집단의 개수로 나눈 후 제곱근을 구한다.
        std = Math.sqrt(d/s.length);
        //System.out.println("모집단 표준편차 : " + std);;
        return std;
    }
    //중간값
    private double med(String[] s) {
        double med = 0;
        double[] d = new double[s.length];
        //String을 double로 형변환 한다.
        for(int i = 0; i < s.length; i++){
        	d[i] = Double.parseDouble(s[i]);
    	}
        //double 배열을 정렬한다.
        Arrays.sort(d);
        
        //배열의 중간 인덱스를 구한다. 
        int m = d.length / 2;            

        if (d.length % 2 == 1) { //요소 개수가 홀수면
        	//중간 요소를 그대로 할당
        	med = d[m];
        } else { // 요소 개수가 짝수면
        	//중간에 위치한 두 수의 평균값을 할당
        	med = (d[m-1] + d[m]) / 2.0; 
        }
        return med;
    }
}

'Spring' 카테고리의 다른 글

[211229] Spring 설치  (0) 2021.12.30