Java 将带有计算的列添加到 CSV 文件
Java Add Column with calculation to CSV file
我将如何向 CSV 文件添加新列,并在每列中添加计算数据?
示例
userid,expDate
1,012015
2,022016
3,032018
我会从每一行中获取 expDate,计算它相对于当前月份和年份以获得到期前的月数,然后将 monthsTill 舍入(因此下个月的 monthsTill 将为 1,无论它是第一天还是本月的最后一天)
userid,expDate,monthsTill
1,022017,0
2,032017,1
3,042017,2
3,052017,3
另外,您如何 "skip" 在相应列中具有特定值的行?
我还没有测试过,但下面的一段代码应该可以解决你的问题。
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);
注意 'FileUtils' class 来自 APache Commons IO 包
编辑:如果您不想使用 FileUtils,请替换
List<String> input = FileUtils.readLines(new File("SomeFile"), StandardCharsets.UTF_8);
和
List<String> input = new ArrayList<String>();
File inputFile = new File("SomeFile");
BufferedReader bufferedReader = new BufferedReader(new FileReader(inputFile));
String readLine = "";
while ((readLine = bufferedReader.readLine()) != null) {
input.add(readLine);
}
和
FileUtils.writeLines(new File("SomeFile"), output, false);
和
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();
当然,如果你不使用 Apache Commons IO,你将不得不自己处理关闭资源,如流等。
这是我正在尝试做的一些伪代码
// 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 Library
这是我计算到
时间的函数
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;
}
}
我将如何向 CSV 文件添加新列,并在每列中添加计算数据?
示例
userid,expDate
1,012015
2,022016
3,032018
我会从每一行中获取 expDate,计算它相对于当前月份和年份以获得到期前的月数,然后将 monthsTill 舍入(因此下个月的 monthsTill 将为 1,无论它是第一天还是本月的最后一天)
userid,expDate,monthsTill
1,022017,0
2,032017,1
3,042017,2
3,052017,3
另外,您如何 "skip" 在相应列中具有特定值的行?
我还没有测试过,但下面的一段代码应该可以解决你的问题。
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);
注意 'FileUtils' class 来自 APache Commons IO 包
编辑:如果您不想使用 FileUtils,请替换
List<String> input = FileUtils.readLines(new File("SomeFile"), StandardCharsets.UTF_8);
和
List<String> input = new ArrayList<String>();
File inputFile = new File("SomeFile");
BufferedReader bufferedReader = new BufferedReader(new FileReader(inputFile));
String readLine = "";
while ((readLine = bufferedReader.readLine()) != null) {
input.add(readLine);
}
和
FileUtils.writeLines(new File("SomeFile"), output, false);
和
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();
当然,如果你不使用 Apache Commons IO,你将不得不自己处理关闭资源,如流等。
这是我正在尝试做的一些伪代码
// 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 Library
这是我计算到
时间的函数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;
}
}