问题
Requirement: I have two csv file input.csv and output.csv The goal is to read the data rows from input.csv, then do some processing on it and if the processing fails then write the failed row of csv to output.csv
Initially input.csv have some data and output.csv is blank. Here is the main class file:
import com.opencsv.bean.ColumnPositionMappingStrategy;
import com.opencsv.bean.CsvToBean;
import com.opencsv.bean.CsvToBeanBuilder;
import com.opencsv.bean.StatefulBeanToCsv;
import com.opencsv.bean.StatefulBeanToCsvBuilder;
import java.io.Reader;
import java.io.Writer;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
public class UploadDocUsingCsv {
private static final String INPUT_CSV_FILE_PATH = "resources/input.csv";
private static final String OUTPUT_CSV_FILE_PATH = "resources/output.csv"; // this file only contain data whose upload is failed
public static void main(String args[]) {
try (
Reader reader4Input = Files.newBufferedReader(Paths.get(INPUT_CSV_FILE_PATH));
Reader reader4Output = Files.newBufferedReader(Paths.get(OUTPUT_CSV_FILE_PATH))
) {
// Read Input File
CsvToBean csvToBean4Input;
CsvToBeanBuilder csvToBeanBuilder4Input = new CsvToBeanBuilder(reader4Input);
csvToBeanBuilder4Input.withType(DocumentDetail.class);
csvToBeanBuilder4Input.withIgnoreLeadingWhiteSpace(true);
csvToBeanBuilder4Input.withSkipLines(0);
csvToBean4Input = csvToBeanBuilder4Input.build();
// Read Output File
CsvToBean csvToBean4Output;
CsvToBeanBuilder csvToBeanBuilder4Output= new CsvToBeanBuilder(reader4Output);
csvToBeanBuilder4Output.withType(DocumentDetail.class);
csvToBeanBuilder4Output.withIgnoreLeadingWhiteSpace(true);
csvToBeanBuilder4Output.withSkipLines(1); // skip header
csvToBean4Output = csvToBeanBuilder4Output.build();
// Declare Set to contain DocumentDetail object whose data could not be sent
HashSet<DocumentDetail> documentDetailsNotSent = new HashSet<DocumentDetail>();
// Call method to upload the document from input file
Iterator<DocumentDetail> csvDocumentDetailIterator = csvToBean4Input.iterator();
DocumentDetail csvHeader = csvDocumentDetailIterator.next(); // skip the header
// documentDetailsNotSent.add(csvHeader);
while (csvDocumentDetailIterator.hasNext()) {
DocumentDetail documentDetail = csvDocumentDetailIterator.next();
System.out.println(documentDetail);
documentDetailsNotSent.add(documentDetail);
}
// Call method to upload the document from output file
csvDocumentDetailIterator = csvToBean4Output.iterator(); // java.lang.RuntimeException: Error capturing CSV header!
while (csvDocumentDetailIterator.hasNext()) {
DocumentDetail documentDetail = csvDocumentDetailIterator.next();
System.out.println(documentDetail);
documentDetailsNotSent.add(documentDetail);
}
Writer writer4Output = Files.newBufferedWriter(Paths.get(OUTPUT_CSV_FILE_PATH));
// write the documentDetail objects that are not uploaded to output file
ArrayList<DocumentDetail> documentDetailNotSetList = new ArrayList<DocumentDetail>(documentDetailsNotSent);
documentDetailNotSetList.add(0, csvHeader);
ColumnPositionMappingStrategy mappingStrategy = new ColumnPositionMappingStrategy();
mappingStrategy.setType(DocumentDetail.class);
StatefulBeanToCsv beanToCsv = new StatefulBeanToCsvBuilder(writer4Output)
.withMappingStrategy(mappingStrategy)
.build();
beanToCsv.write(documentDetailNotSetList);
writer4Output.close();
} catch (Exception e){
System.out.println(e);
}
}
}
DocumentDetail class used as Bean is here:
import com.opencsv.bean.CsvBindByPosition;
import java.util.Objects;
public class DocumentDetail {
@CsvBindByPosition(position = 0)
private String contractId;
@CsvBindByPosition(position = 1)
private String partyId;
@CsvBindByPosition(position = 2)
private String contractBranch;
@CsvBindByPosition(position = 3)
private String customerName;
@CsvBindByPosition(position = 4)
private String vertical;
@CsvBindByPosition(position = 5)
private String referenceContractId;
@CsvBindByPosition(position = 6)
private String bankFlowNo;
@CsvBindByPosition(position = 7)
private String payoutCategory;
@CsvBindByPosition(position = 8)
private String camNo;
@CsvBindByPosition(position = 9)
private String camStatus;
@CsvBindByPosition(position = 10)
private String folderName;
@CsvBindByPosition(position = 11)
private String documentName;
@CsvBindByPosition(position = 12)
private String pdfName;
public String getContractId() {
return contractId;
}
public void setContractId(String contractId) {
this.contractId = contractId;
}
public String getPartyId() {
return partyId;
}
public void setPartyId(String partyId) {
this.partyId = partyId;
}
public String getContractBranch() {
return contractBranch;
}
public void setContractBranch(String contractBranch) {
this.contractBranch = contractBranch;
}
public String getCustomerName() {
return customerName;
}
public void setCustomerName(String customerName) {
this.customerName = customerName;
}
public String getVertical() {
return vertical;
}
public void setVertical(String vertical) {
this.vertical = vertical;
}
public String getReferenceContractId() {
return referenceContractId;
}
public void setReferenceContractId(String referenceContractId) {
this.referenceContractId = referenceContractId;
}
public String getBankFlowNo() {
return bankFlowNo;
}
public void setBankFlowNo(String bankFlowNo) {
this.bankFlowNo = bankFlowNo;
}
public String getPayoutCategory() {
return payoutCategory;
}
public void setPayoutCategory(String payoutCategory) {
this.payoutCategory = payoutCategory;
}
public String getCamNo() {
return camNo;
}
public void setCamNo(String camNo) {
this.camNo = camNo;
}
public String getCamStatus() {
return camStatus;
}
public void setCamStatus(String camStatus) {
this.camStatus = camStatus;
}
public String getFolderName() {
return folderName;
}
public void setFolderName(String folderName) {
this.folderName = folderName;
}
public String getDocumentName() {
return documentName;
}
public void setDocumentName(String documentName) {
this.documentName = documentName;
}
public String getPdfName() {
return pdfName;
}
public void setPdfName(String pdfName) {
this.pdfName = pdfName;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
DocumentDetail that = (DocumentDetail) o;
return contractId.equals(that.contractId) &&
partyId.equals(that.partyId) &&
contractBranch.equals(that.contractBranch) &&
customerName.equals(that.customerName) &&
vertical.equals(that.vertical) &&
referenceContractId.equals(that.referenceContractId) &&
bankFlowNo.equals(that.bankFlowNo) &&
payoutCategory.equals(that.payoutCategory) &&
camNo.equals(that.camNo) &&
camStatus.equals(that.camStatus) &&
folderName.equals(that.folderName) &&
documentName.equals(that.documentName) &&
pdfName.equals(that.pdfName);
}
@Override
public int hashCode() {
return Objects.hash(contractId, partyId, contractBranch, customerName, vertical, referenceContractId,
bankFlowNo, payoutCategory, camNo, camStatus, folderName, documentName, pdfName);
}
@Override
public String toString() {
return "DocumentDetail{" +
"contractId='" + contractId + '\'' +
", partyId='" + partyId + '\'' +
", contractBranch='" + contractBranch + '\'' +
", customerName='" + customerName + '\'' +
", vertical='" + vertical + '\'' +
", referenceContractId='" + referenceContractId + '\'' +
", bankFlowNo='" + bankFlowNo + '\'' +
", payoutCategory='" + payoutCategory + '\'' +
", camNo='" + camNo + '\'' +
", camStatus='" + camStatus + '\'' +
", folderName='" + folderName + '\'' +
", documentName='" + documentName + '\'' +
", pdfName='" + pdfName + '\'' +
'}';
}
}
Input.csv is here
CONTRACT _ID,PARTY_ID ,CONTRACT_BRANCH ,CUSTOMER_NAME,VERTICAL ,REFERENCE_CONTRACT_ID ,BANK FLOW NO,PAYOUT CATEGORY,CAM_NO,CAM_STATUS ,FOLDER _NAME ,Document Name,PDF_NAME
133336,362177,xyz,qwe fghfg,fgh,NG233112344,958875934,Purchase Invoice,NA,APPROVED,dfgdfg Construction_dfg,PAYMENT VOUCHER,9588759.pdf
The question is how to solve the java.lang.RuntimeException: Error capturing CSV header!
while calling csvToBean4Output.iterator();
回答1:
I have solved the problem by checking for the output.csv
is empty or not.
Here is the code:
boolean empty = (new File(OUTPUT_CSV_FILE_PATH)).length() == 0;
if(!empty){
csvDocumentDetailIterator = csvToBean4Output.iterator();
while (csvDocumentDetailIterator.hasNext()) {
DocumentDetail documentDetail = csvDocumentDetailIterator.next();
logger.info(documentDetail);
boolean isSent = commonMethods.uploadDoc(documentDetail);
logger.info("isSent: " + isSent);
if(!isSent){
documentDetailsNotSent.add(documentDetail);
}
}
}
来源:https://stackoverflow.com/questions/53691192/how-to-solve-the-runtime-exception-while-converting-csv-to-bean-using-opencsv-fo