
csv파일 한글 깨짐 현상때문에 수많은 검색과 방법을 취했음에도 해결이 되지 않아 헤맬 때 감사히 현규멘토님께서 도와주셨습니다.

메모장을 다른이름저장으로 UTF-8로 저장하거나 인텔리제이에서 UTF-8과 관련된 모든 설정을 해도 깨지게 나올 때엔

구글드라이브에 파일업로드 후에

Google 스프레드시트로 파일을 열어서

csv로 다운로드 후에 메모장으로 열어보면 한글깨짐 현상이 사라져있습니다.

그러나 한글깨짐 파일과 멀쩡한 파일에 차이점인 큰따옴표("") 가 있어서 파싱할 때 Split을

"\",\"" 대신에 ","로 바꿔야 제대로된 값이 나옵니다.


그러나 10만건이 아닌 4만건이 떴습니다. 중간에 예외가 껴서 파싱이 안된 것 같습니다만 아직 해결을 못했습니다.
Hospital
@AllArgsConstructor
@Getter
@Setter
@NoArgsConstructor
public class Hospital {
private int id;
private String openServiceName;
private int openLocalGovernmentCode;
private String managementNumber;
private LocalDateTime licenseDate;
private int businessStatus;
private int businessStatusCode;
private String phone;
private String fullAddress;
private String roadNameAddress;
private String hospitalName;
private String businessTypeName;
private int healthcareProviderCount;
private int patientRoomCount;
private int totalNumberOfBeds;
private float totalAreaSize;
}
@AllArgsConstructor : 모든 필드 값을 파라미터로 받는 생성자를 만듦
@NoArgsConstructor : 기본 생성자를 만들어줌
HospitalParser
public class HospitalParser implements Parser<Hospital> {
@Override
public Hospital parse(String str) {
String[] row =str.split(",");
Hospital hospital = new Hospital();
hospital.setId(Integer.parseInt(row[0].replace("\"","")));
hospital.setOpenServiceName(row[1]);
hospital.setOpenLocalGovernmentCode(Integer.parseInt(row[3]));
hospital.setManagementNumber(row[4]);
int year = Integer.parseInt(row[5].substring(0,4));
int month = Integer.parseInt(row[5].substring(4,6));
int day = Integer.parseInt(row[5].substring(6,8));
hospital.setLicenseDate(LocalDateTime.of(year,month,day,0,0,0));
hospital.setBusinessStatus(Integer.parseInt(row[7]));
hospital.setBusinessStatusCode(Integer.parseInt(row[9]));
hospital.setPhone(row[15]);
hospital.setFullAddress(row[18]);
hospital.setRoadNameAddress(row[19]);
hospital.setHospitalName(row[21]);
hospital.setBusinessTypeName(row[25]);
hospital.setHealthcareProviderCount(Integer.parseInt(row[29]));
hospital.setPatientRoomCount(Integer.parseInt(row[30]));
hospital.setTotalNumberOfBeds(Integer.parseInt(row[31]));
hospital.setTotalAreaSize(Float.parseFloat(row[32]));
return hospital;
}
}
Parser
public interface Parser<T> {
T parse(String str);
}
ParserFactory
@Configuration
public class ParserFactory {
@Bean
public ReadLineContext<Hospital> hospitalReadLineContext(){
return new ReadLineContext<Hospital>(new HospitalParser());
}
}
ReadLineContext
public class ReadLineContext<T>{
private Parser<T> parser;
public ReadLineContext(Parser<T> parser) {
this.parser = parser;
}
public List<T> readByLine(String filename) throws IOException {
List<T> result = new ArrayList<>();
BufferedReader reader = new BufferedReader(
new FileReader(filename)
);
String str;
while ((str = reader.readLine()) != null) {
try {
result.add(parser.parse(str));
}catch (Exception e){
System.out.printf("파싱 중 문제가 생겨 이 라인은 넘어갑니다. 파일 내용 : %s\n", str.substring(0,20));
}
}
reader.close();
return result;
}
}
@SpringBootTest(classes = ParserFactory.class)
class HospitalParserTest {
@Autowired
ReadLineContext<Hospital> hospitalReadLineContext;
@Test
@DisplayName("10만건 이상 데이터가 파싱 되는지")
void oneHundreadThousandRows() throws IOException {
String filename = "C:\\Users\\proje\\Desktop\\fulldata_01_01_02_P_의원.csv";
List<Hospital> hospitalList = hospitalReadLineContext.readByLine(filename);
assertTrue(hospitalList.size() > 1000);
// assertTrue(hospitalList.size() > 10000);
for(int i =0; i< 10; i++){
System.out.println(hospitalList.get(i).getHospitalName());
}
System.out.printf("파싱된 데이터 개수 :%d ", hospitalList.size());
}
@Test
@DisplayName("csv 1줄을 Hospital로 잘 만드는지 Test")
void convertToHospital() {
HospitalParser hp = new HospitalParser();
String str = "\"1\",\"의원\",\"01_01_02_P\",\"3620000\",\"PHMA119993620020041100004\",\"19990612\",\"\",\"01\",\"영업/정상\",\"13\",\"영업중\",\"\",\"\",\"\",\"\",\"062-515-2875\",\"\",\"500881\",\"광주광역시 북구 풍향동 565번지 4호 3층\",\"광주광역시 북구 동문대로 24, 3층 (풍향동)\",\"61205\",\"효치과의원\",\"20211115113642\",\"U\",\"2021-11-17 02:40:00.0\",\"치과의원\",\"192630.735112\",\"185314.617632\",\"치과의원\",\"1\",\"0\",\"0\",\"52.29\",\"401\",\"치과\",\"\",\"\",\"\",\"0\",\"0\",\"\",\"\",\"0\",\"\",";
Hospital hospital = hp.parse(str);
assertEquals(1, hospital.getId()); // col:0
assertEquals("의원", hospital.getOpenServiceName());//col:1
assertEquals(3620000,hospital.getOpenLocalGovernmentCode()); // col: 3
assertEquals("PHMA119993620020041100004",hospital.getManagementNumber()); // col:4
assertEquals(LocalDateTime.of(1999, 6, 12, 0, 0, 0), hospital.getLicenseDate()); //19990612 //col:5
assertEquals(1, hospital.getBusinessStatus()); //col:7
assertEquals(13, hospital.getBusinessStatusCode());//col:9
assertEquals("062-515-2875", hospital.getPhone());//col:15
assertEquals("광주광역시 북구 풍향동 565번지 4호 3층", hospital.getFullAddress()); //col:18
assertEquals("광주광역시 북구 동문대로 24, 3층 (풍향동)", hospital.getRoadNameAddress());//col:19
assertEquals("효치과의원", hospital.getHospitalName());//col:21
assertEquals("치과의원", hospital.getBusinessTypeName());//col:25
assertEquals(1, hospital.getHealthcareProviderCount()); //col:29
assertEquals(0, hospital.getPatientRoomCount()); //col:30
assertEquals(0, hospital.getTotalNumberOfBeds()); //col:31
assertEquals(52.29f, hospital.getTotalAreaSize()); //col:32
}
}