Java将带计算的列添加到CSV文件
如何向CSV文件中添加新列,并在每列中添加计算数据 范例 用户ID,expDate 1,012015 2,022016 3032018 我会从每一行取expDate,计算它相对于当前月份和年份的值,得到它到期的月份数,然后取整MonthsToll,所以下个月的MonthsToll将是1,不管它是当前月份的第一天还是最后一天 userid,expDate,monthsTill 1,022017,0 2,032017,1 3,042017,2 305217,3Java将带计算的列添加到CSV文件,java,csv,duration,Java,Csv,Duration,如何向CSV文件中添加新列,并在每列中添加计算数据 范例 用户ID,expDate 1,012015 2,022016 3032018 我会从每一行取expDate,计算它相对于当前月份和年份的值,得到它到期的月份数,然后取整MonthsToll,所以下个月的MonthsToll将是1,不管它是当前月份的第一天还是最后一天 userid,expDate,monthsTill 1,022017,0 2,032017,1 3,042017,2 305217,3 另外,如何跳过在相应列中具有特定值的行
另外,如何跳过在相应列中具有特定值的行?我还没有对其进行测试,但下面的代码应该可以解决您的问题
List<String> input = FileUtils.readLines(new File("SomeFile"), StandardCharsets.UTF_8);
List<String> output = new ArrayList<String>();
if(input.size()>1){
Calendar cal = Calendar.getInstance();
cal.setTime(new Date());
int month = cal.get(Calendar.MONTH) + 1;
String header = input.get(0) + ",monthsTill";
output.add(header);
int length = input.size();
for(int i=1;i<length;i++){
StringBuilder str = new StringBuilder();
String row = input.get(i);
String [] elements = row.split(",");
if(elements.length == 2){
// You have access to both the index and expiry date. So if you want to skip some row, simply don't add it to the ouput collection
int exp = Integer.parseInt(elements[1].substring(0, 2));
int monRemaining = month-exp;
str.append(row).append(",").append(monRemaining);
output.add(str.toString());
} else {
throw new IllegalArgumentException();
}
}
FileUtils.writeLines(new File("SomeFile"), output, false);
与
当然,如果您不使用ApacheCommonsIO,您将不得不自己处理关闭资源,如streams等 下面是我试图做的一些伪代码
// read csv file
// append timeTillExpired to end of first row of CSV
// for each row after first row
// calculate timeTillExpired
// if format MYYYY (ex 22017)
// M and YYYY
// calculate relative to current date as months
//else
// MM and YYYY (ex 122017)
// calculate relative to current date as months
// if calculated > 3
// timeTillExpired = ">3"
// add timeTillExpired to end of row
//else
// add timeTillExpired to end of row
// save file
// close file
根据您的伪代码,下面是应该做的事情
private void process(){
BufferedReader bufferedReader = null;
PrintWriter p = null;
String sep = ",";
String newCol = "monthsTill";
String defaultTillExpMonth = ">3";
Calendar cal = Calendar.getInstance();
cal.setTime(new Date());
int currMonth = cal.get(Calendar.MONTH) + 1;
try {
// read csv file
List<String> input = new ArrayList<String>();
File inputFile = new File("InputFile");
bufferedReader = new BufferedReader(new FileReader(inputFile));
String readLine = "";
while ((readLine = bufferedReader.readLine()) != null) {
input.add(readLine);
}
// for each row after first row
// calculate timeTillExpired
// if format MYYYY (ex 22017)
// M and YYYY -> MM and YYYY
// calculate relative to current date as months
int numOfRecords = input.size();
if(numOfRecords>1){
List<String> output = new ArrayList<String>();
String header = input.get(0) +sep +newCol;
output.add(header);
// for each row after first row
// calculate timeTillExpired
// if format MYYYY (ex 22017)
// M and YYYY -> MM and YYYY
// calculate relative to current date as months
for(int i=1;i<numOfRecords;i++){
// I am simply going to get the last column from record
String row = input.get(i);
StringBuilder res = new StringBuilder(row);
String [] entries = row.split(sep);
int length = entries.length;
if(length>0){
res.append(sep);
String rec = entries[length-1];
int expMonth = 0;
// Case of MYYYY. Assumption is it's either MYYYY or MMYYYY
if(rec.length()==5){
expMonth = Integer.valueOf(rec.substring(0, 1));
} else {
expMonth = Integer.valueOf(rec.substring(0, 2));
}
int monToExp = expMonth - currMonth;
// if calculated > 3
if(monToExp > 3){
res.append(defaultTillExpMonth);
} else {
res.append(monToExp);
}
output.add(res.toString());
}
}
// Write into the same file.
// First We'll delete everything in the input file and then write the modified records
p = new PrintWriter(new FileWriter("output.txt",false));
// Ouch. Very bad way to handle resources. You should find a better way
p.print("");
p.close();
// Write into file
p = new PrintWriter(new FileWriter("InputFile"));
for(String row : output)
{
p.println(row);
}
} else {
System.out.println("No records to process");
}
} catch(IOException e){
e.printStackTrace();
} finally { // Close file
if(p!=null){
p.close();
}
if(bufferedReader!=null){
try {
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
我强烈建议您了解什么是文件资源,如何有效地处理它们并改进此代码。稍后您应该转到Apache Commons库这里是我的函数,用于计算到
private static int calculateTimeTill(int date)
{
// TODO Auto-generated method stub
String numberAsString = Integer.toString(date);
if(numberAsString.length() == 5)
{
//format 22017
String month = numberAsString.substring(0,1);
String year = numberAsString.substring(1,5);
int monthResult = Integer.parseInt(month);
int yearResult = Integer.parseInt(year);
int day = 1;
// using Joda - Time http://joda-time.sourceforge.net/installation.html
// downloaded Joda - Convert as well
LocalDate expDate = new LocalDate(yearResult, monthResult, day);
LocalDate currDate = new LocalDate();
int output = Months.monthsBetween(expDate, currDate).getMonths();
return output;
}
else
{
//format 122017
String month = numberAsString.substring(0,2);
String year = numberAsString.substring(2,6);
int monthResult = Integer.parseInt(month);
int yearResult = Integer.parseInt(year);
int day = 1;
// using Joda - Time http://joda-time.sourceforge.net/installation.html
// downloaded Joda - Convert as well
LocalDate expDate = new LocalDate(yearResult, monthResult, day);
LocalDate currDate = new LocalDate();
int output = Months.monthsBetween(expDate, currDate).getMonths();
return output;
}
}
您是否愿意使用外部库,如apache commons csv和apache commons io?我希望代码尽可能简单,如果apache commons有助于做到这一点,并且可以方便地使用,我也愿意使用。没有apache commons,还有其他方法可以做到这一点吗?我找不到org.apache.commons.io.FileUtils.apache commons不是Java SDK的一部分。您可以将其用作外部Jar或使用Maven之类的构建工具—我获得了所有文件,并在抛出新的IllegalArgumentException时出错;ifelements.length==2检查是否正好有两个值由逗号分隔。您的输入csv文件正确吗?这是一个总体思路的示例,实际数据中有13列。基于什么?/您在哪里跳过行?如何确保它只从我的数据文件的第13列获取数据?我只是花了一些时间,写了一个单独的函数,从该列中获取输入,并输出一个时间,以月为单位,例如22017,当前日期和年份是22017,因此它将输出0,下个月发送int 22017,它将输出1。对于我来说,将计算到的时间与通过记录的时间分开会更容易。我已经在你的伪代码下添加了注释。无论如何,您可以替换iflength>0,String rec=entries[length-1];iflength>12且字符串rec=条目[12];我同意。计算时间的逻辑应该是一个独立的函数;LocalDate currDate=新的LocalDate;int output=Months.monthbetweenUpdate,currDate.getMonths;在if-else块之外调用该方法
PrintWriter f0 = new PrintWriter(new FileWriter("SomeFile",false));
f0.print("");
// Erase the contents of the input file in a
// Very bad way
f0.close();
f0 = new PrintWriter(new FileWriter("output.txt"));
for(String row : output)
{
f0.println(row);
}
f0.close();
// read csv file
// append timeTillExpired to end of first row of CSV
// for each row after first row
// calculate timeTillExpired
// if format MYYYY (ex 22017)
// M and YYYY
// calculate relative to current date as months
//else
// MM and YYYY (ex 122017)
// calculate relative to current date as months
// if calculated > 3
// timeTillExpired = ">3"
// add timeTillExpired to end of row
//else
// add timeTillExpired to end of row
// save file
// close file
private void process(){
BufferedReader bufferedReader = null;
PrintWriter p = null;
String sep = ",";
String newCol = "monthsTill";
String defaultTillExpMonth = ">3";
Calendar cal = Calendar.getInstance();
cal.setTime(new Date());
int currMonth = cal.get(Calendar.MONTH) + 1;
try {
// read csv file
List<String> input = new ArrayList<String>();
File inputFile = new File("InputFile");
bufferedReader = new BufferedReader(new FileReader(inputFile));
String readLine = "";
while ((readLine = bufferedReader.readLine()) != null) {
input.add(readLine);
}
// for each row after first row
// calculate timeTillExpired
// if format MYYYY (ex 22017)
// M and YYYY -> MM and YYYY
// calculate relative to current date as months
int numOfRecords = input.size();
if(numOfRecords>1){
List<String> output = new ArrayList<String>();
String header = input.get(0) +sep +newCol;
output.add(header);
// for each row after first row
// calculate timeTillExpired
// if format MYYYY (ex 22017)
// M and YYYY -> MM and YYYY
// calculate relative to current date as months
for(int i=1;i<numOfRecords;i++){
// I am simply going to get the last column from record
String row = input.get(i);
StringBuilder res = new StringBuilder(row);
String [] entries = row.split(sep);
int length = entries.length;
if(length>0){
res.append(sep);
String rec = entries[length-1];
int expMonth = 0;
// Case of MYYYY. Assumption is it's either MYYYY or MMYYYY
if(rec.length()==5){
expMonth = Integer.valueOf(rec.substring(0, 1));
} else {
expMonth = Integer.valueOf(rec.substring(0, 2));
}
int monToExp = expMonth - currMonth;
// if calculated > 3
if(monToExp > 3){
res.append(defaultTillExpMonth);
} else {
res.append(monToExp);
}
output.add(res.toString());
}
}
// Write into the same file.
// First We'll delete everything in the input file and then write the modified records
p = new PrintWriter(new FileWriter("output.txt",false));
// Ouch. Very bad way to handle resources. You should find a better way
p.print("");
p.close();
// Write into file
p = new PrintWriter(new FileWriter("InputFile"));
for(String row : output)
{
p.println(row);
}
} else {
System.out.println("No records to process");
}
} catch(IOException e){
e.printStackTrace();
} finally { // Close file
if(p!=null){
p.close();
}
if(bufferedReader!=null){
try {
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
private static int calculateTimeTill(int date)
{
// TODO Auto-generated method stub
String numberAsString = Integer.toString(date);
if(numberAsString.length() == 5)
{
//format 22017
String month = numberAsString.substring(0,1);
String year = numberAsString.substring(1,5);
int monthResult = Integer.parseInt(month);
int yearResult = Integer.parseInt(year);
int day = 1;
// using Joda - Time http://joda-time.sourceforge.net/installation.html
// downloaded Joda - Convert as well
LocalDate expDate = new LocalDate(yearResult, monthResult, day);
LocalDate currDate = new LocalDate();
int output = Months.monthsBetween(expDate, currDate).getMonths();
return output;
}
else
{
//format 122017
String month = numberAsString.substring(0,2);
String year = numberAsString.substring(2,6);
int monthResult = Integer.parseInt(month);
int yearResult = Integer.parseInt(year);
int day = 1;
// using Joda - Time http://joda-time.sourceforge.net/installation.html
// downloaded Joda - Convert as well
LocalDate expDate = new LocalDate(yearResult, monthResult, day);
LocalDate currDate = new LocalDate();
int output = Months.monthsBetween(expDate, currDate).getMonths();
return output;
}
}