新手上路,遇到CSV读写需求,CSV文件中有空行。
参考了一些博客,自己动手写了下JAVA读写CSV文件工具类。
CsvReader:
/**
* @Title: CsvReader.java
* @Package:xxd.tools
* @Description:TODO
* @author XingXuDong
* @date:2018年9月26日 下午19:47
*/
package xxd.tools.csvTools;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
public class CsvReader {
// 文件路径
private String filePath;
private File file;
private DataInputStream in;
private BufferedReader br;
public CsvReader(String filepath) {
this.filePath = filepath;
}
/**
* 读取标题
*
* @return 以字符串数组存储的一行数据
*/
public String[] ReadTitle() {
String[] titleItems;
try {
file = new File(filePath);
in = new DataInputStream(new FileInputStream(file));
// CSV默认为GBK编码格式
br = new BufferedReader(new InputStreamReader(in, "GBK"));
// 独处的结果为String
String titleLine = br.readLine();
// 用字符串数组存储此行不同列数据
titleItems = titleLine.split(",");
// 关掉是个好习惯
br.close();
return titleItems;
} catch (Exception ex) {
ex.printStackTrace();
return null;
}
}
/**
* 按行号读取数据
*
* @param index
* 行号
* @return 以字符串数组存储的一行数据
*/
public String[] ReadByLineIndex(int index) {
String[] resultItems = null;
String resultLine = null;
try {
file = new File(filePath);
in = new DataInputStream(new FileInputStream(file));
br = new BufferedReader(new InputStreamReader(in, "GBK"));
// 遍历文件,直到找到那一行
for (int i = 0; i < index; i++) {
resultLine = br.readLine();
}
if (resultLine != null) {
resultItems = resultLine.split(",");
}
br.close();
return resultItems;
} catch (Exception ex) {
ex.printStackTrace();
return null;
}
}
/**
* 按列号读取数据,包括标题
*
* @param index
* 列号
* @return 以字符串链表保存的数据,一个字符串为此列一行数据
*/
public ArrayList<String> ReadByColumnIndex(int index) {
ArrayList<String> resultItems = new ArrayList<String>();
String[] lineItem;
String line;
try {
file = new File(filePath);
in = new DataInputStream(new FileInputStream(file));
br = new BufferedReader(new InputStreamReader(in, "GBK"));
// 遍历每一行,提取每一行对应列的数据
while ((line = br.readLine()) != null) {
lineItem = line.split(",");
if (lineItem.length != 0) {
resultItems.add(lineItem[index - 1]);
} else {
resultItems.add(null);
}
}
br.close();
return resultItems;
} catch (Exception ex) {
ex.printStackTrace();
return null;
}
}
/**
* 按列号读取数据,不包括标题
*
* @param index
* @return 以字符串链表保存的数据,一个字符串为此列一行数据
*/
public ArrayList<String> ReadDataByColumnIndex(int index) {
ArrayList<String> result = this.ReadByColumnIndex(index);
if (result != null) {
result.remove(0);
return result;
} else {
return null;
}
}
/**
* 读取所有数据,包括标题
*
* @return 以字符串数组链表保存的数据,一个字符串数组为一行数据
*/
public ArrayList<String[]> ReadAll() {
ArrayList<String[]> result = new ArrayList<String[]>();
String[] lineItem;
String line;
try {
file = new File(filePath);
in = new DataInputStream(new FileInputStream(file));
br = new BufferedReader(new InputStreamReader(in, "GBK"));
// 遍历读取
while ((line = br.readLine()) != null) {
lineItem = line.split(",");
result.add(lineItem);
}
br.close();
return result;
} catch (Exception ex) {
ex.printStackTrace();
return null;
}
}
}
CsvWriter:
/**
* @Title: CsvReader.java
* @Package:xxd.tools
* @Description:TODO
* @author XingXuDong
* @date:2018年9月27日 上午09:41
*/
package xxd.tools.csvTools;
import java.io.BufferedWriter;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
public class CsvWriter {
// 保存路径
private String savePath;
private File file;
private DataOutputStream out;
private BufferedWriter bw;
public CsvWriter() {
}
public CsvWriter(String path) {
this.savePath = path;
}
/**
* 创建一个新的CSV文件,并将数据写入
*
* @param data
* 用字符串数组链表存放的数据,第一个数组不能为空,非空数组中不能有空值
* @return 成功true;失败false
*/
public boolean SaveNewCsv(ArrayList<String[]> data) {
try {
file = new File(savePath);
if (file.exists()) {
file.delete();
}
out = new DataOutputStream(new FileOutputStream(file));
// CSV默认为GBK编码格式
bw = new BufferedWriter(new OutputStreamWriter(out, "GBK"));
if (data != null && data.size() != 0) {
// 依据第一行获取列数
int colCount = 0;
colCount = data.get(0).length;
// 遍历链表
for (int i = 0; i < data.size(); i++) {
String[] lineItems;
String line = "";
lineItems = data.get(i);
// 判断此行是否有值
if (lineItems.length != 0) {
// 有值,则遍历字符串数组
for (int j = 0; j < lineItems.length; j++) {
line = line + lineItems[j] + ",";
}
// 整理格式后写入
line = line.substring(0, line.lastIndexOf(","));
line = line + "\r";
bw.append(line);
} else {
// 无值,则整理为空行格式后写入
for (int count = 0; count < colCount; count++) {
line = line + " ,";
}
line = line + "\r";
bw.append(line);
}
}
// 关掉是个好习惯
bw.close();
return true;
} else {
bw.close();
return false;
}
} catch (Exception ex) {
ex.printStackTrace();
return false;
}
}
public boolean AppendData(String[] data) {
try {
file = new File(savePath);
// 文件输出流设置为追加
out = new DataOutputStream(new FileOutputStream(file, true));
bw = new BufferedWriter(new OutputStreamWriter(out, "GBK"));
String line = "";
for (int i = 0; i < data.length; i++) {
line = line + data[i] + ",";
}
line = line.substring(0, line.lastIndexOf(","));
line = line + "\r";
bw.append(line);
bw.close();
return true;
} catch (Exception ex) {
return false;
}
}
}
自己编的简单测试用数据:
颜色 | 数字 | 水果 |
紫色 | 1 | 葡萄 |
红色 | 2 | 苹果 |
橙色 | 3 | 橙子 |
黄色 | 4 | 香蕉 |
蓝色 | 5 | 蓝莓 |
测试代码:
package test.main;
import java.util.ArrayList;
import xxd.tools.csvTools.CsvReader;
import xxd.tools.csvTools.CsvWriter;
public class test {
public static void main(String[] args) {
CsvReader csvReader = new CsvReader(
"test.csv");//路径自己更改
// 读标题
String[] re1 = csvReader.ReadTitle();
String result1 = "";
for (int i = 0; i < re1.length; i++) {
result1 = result1 + re1[i] + ",";
}
result1 = result1.substring(0, result1.lastIndexOf(","));
System.out.println(result1);
System.out.println("***************");
// 读一行数据
String[] re2 = csvReader.ReadByLineIndex(3);
String result2 = "";
for (int i = 0; i < re2.length; i++) {
result2 = result2 + re2[i] + ",";
}
result2 = result2.substring(0, result2.lastIndexOf(","));
System.out.println(result2);
System.out.println("***************");
//读一个空行
String[] re3 = csvReader.ReadByLineIndex(6);
String result3 = "";
if (re3.length != 0) {
for (int i = 0; i < re3.length; i++) {
result3 = result3 + re3[i] + ",";
}
result3 = result3.substring(0, result3.lastIndexOf(","));
} else {
result3 = null;
}
System.out.println(result3);
System.out.println("***************");
//判定超出行索引
String[] re4 = csvReader.ReadByLineIndex(9);
String result4 = "";
if (re4 != null) {
if (re4.length != 0) {
for (int i = 0; i < re4.length; i++) {
result4 = result4 + re4[i] + ",";
}
result4 = result4.substring(0, result4.lastIndexOf(","));
} else {
result4 = null;
}
} else {
result4 = "超出索引范围!";
}
System.out.println(result4);
System.out.println("***************");
// 读一列数据,带标题
ArrayList<String> re5 = csvReader.ReadByColumnIndex(3);
if (re5 != null) {
if (re5.size() != 0) {
for (int i = 0; i < re5.size(); i++) {
System.out.println(re5.get(i));
}
}
} else {
System.out.println("超出索引范围!");
}
System.out.println("***************");
// 读一列数据,不带标题
ArrayList<String> re6 = csvReader.ReadDataByColumnIndex(1);
if (re6 != null) {
if (re6.size() != 0) {
for (int i = 0; i < re6.size(); i++) {
System.out.println(re6.get(i));
}
} else {
System.out.println("null");
}
} else {
System.out.println("超出索引范围!");
}
System.out.println("***************");
// 读表格内所有数据,带标题
ArrayList<String[]> re7 = csvReader.ReadAll();
if (re7 != null) {
if (re7.size() != 0) {
for (int i = 0; i < re7.size(); i++) {
String[] lineItems;
String line = "";
lineItems = re7.get(i);
if (lineItems.length!=0) {
for (int j = 0; j < lineItems.length; j++) {
line = line + lineItems[j] + ",";
}
line = line.substring(0, line.lastIndexOf(","));
System.out.println(line);
} else {
System.out.println("null");
}
}
}
} else {
System.out.println("超出索引范围!");
}
System.out.println("***************");
// 将结果7读取的数据重新写入新的CSV
CsvWriter csvWriter = new CsvWriter("test1.csv");//路径自己更改
csvWriter.SaveNewCsv(re7);
// 向新的CSV文件追加一行
String[] appendData = new String[3];
appendData[0]="color";
appendData[1]="number";
appendData[2]="fruit";
csvWriter.AppendData(appendData);
}
}
测试输出结果:
颜色,数字,水果
***************
红色,2,苹果
***************
null
***************
超出索引范围!
***************
水果
葡萄
苹果
橙子
香蕉
null
蓝莓
***************
紫色
红色
橙色
黄色
null
蓝色
***************
颜色,数字,水果
紫色,1,葡萄
红色,2,苹果
橙色,3,橙子
黄色,4,香蕉
null
蓝色,5,蓝莓
***************
输出的测试文件:
颜色 | 数字 | 水果 |
紫色 | 1 | 葡萄 |
红色 | 2 | 苹果 |
橙色 | 3 | 橙子 |
黄色 | 4 | 香蕉 |
蓝色 | 5 | 蓝莓 |
color | number | fruit |
参考:https://blog.csdn.net/ganzhantoulebi0546/article/details/72954409
https://www.cnblogs.com/beihoushan/p/6428162.html