一.了解csv文件的特点
1.1 csv文件即comma-seperated values的缩写,与excel文件类似,但是用逗号分隔。
1.2 我们可以利用csv的特点来对他进行部分操作如对分割数据等,即使用String字符串的split方法
二.读取csv文件
2.1步骤
第一步:创建一个空二维数据准备存数据,创建缓冲字符流读取出文件的行数
第二步:重置缓冲流,将行数赋给数组,用字符串记录每一行的数据,用逗号分割,存入二维数组
第三步:将二维数组遍历输出,先输出第一个数据,再拼接逗号
第四步:对数据进行操作
2.2开始创建CsvReader文件
public static void main(String[] args) throws Exception {
//第一步,创建一个空二维数据准备存数据,创建缓冲流读取出文件的行数
String filePath = "D:\\winequality-red.csv";
String[][] allData = null; //创建二维数组
BufferedReader br = new BufferedReader(new FileReader(filePath));// 创建缓冲流读取行
int lineNumber = 0; // 记录文件行数
while (br.readLine() != null) {//读取文件行数
lineNumber++;
}
//第二步,重置缓冲流,将行数赋给数组,用字符串记录每一行的数据,用逗号分割,存入二维数组
br = new BufferedReader(new FileReader(filePath));//将缓冲流重置
allData = new String[lineNumber][];
String line; //每一行的数据
lineNumber = 0;
while ((line = br.readLine()) != null) {
String[] data = line.split(","); //用一个一维数组存,将每一行元素用逗号分开
allData[lineNumber] = data;
lineNumber++;
}
//将二维数组遍历输出,先输出第一个数据,再拼接逗号
for (int i = 0; i < lineNumber; i++) {
System.out.print(allData[i][0]); //输出第i行第一个数据
for (int j = 1; j < allData[0].length; j++) {
System.out.print("," + allData[i][j]); //在第一个数据还没加逗号拼接
}
System.out.println();//换行
}
br.close();
}
接下来是对数据的操作,分为四个方法
1.计算某个数据在某列出现的次数
/**
* 返回一个数据在某一列(字段)的出现次数
* @param allData //原来存的二维数组
* @param lineNumber //要找的列数,在上文line代表行,由于csv文件每个字段是按列存,所以此处line代表列
* @param number 要找的数据
* @return count
*/
public static int getCount(String[][] allData,int lineNumber,double number){
ArrayList<Double> numbers = new ArrayList<>();
for (int i = 1; i < allData.length; i++) { //第二列是数组的allData[][1]
numbers.add(Double.valueOf(allData[i][lineNumber-1]));//将字符串转为数字添加到集合里
}
int count = 0;
for (int i = 0; i < numbers.size(); i++) {
if (numbers.get(i).equals(number)){
count++;
}
}
return count;
}
2.计算某列最大值
/**
* 返回某一列数据的最大值
* @param allData
* @param lineNumber
* @return max
*/
public static double getMax(String[][] allData,int lineNumber){
ArrayList<Double> numbers = new ArrayList<>();
for (int i = 1; i < allData.length; i++) {
numbers.add(Double.valueOf(allData[i][lineNumber-1]));//将字符串转为数字
}
double max =0;
for (int i = 0; i < numbers.size(); i++) {
if (numbers.get(i)>max){
max = numbers.get(i);
}
}
return max;
}
3.计算最小值
/**
* 返回某一列数据的最小值
* @param allData
* @param lineNumber
* @return min
*/
public static double getMin(String[][] allData,int lineNumber){
ArrayList<Double> numbers = new ArrayList<>();//创建list集合存double类型的数据
for (int i = 1; i < allData.length; i++) {
numbers.add(Double.valueOf(allData[i][lineNumber-1]));//将字符串转为数字
}
double min =numbers.get(0);//取第一个数为基准
for (int i = 1; i < numbers.size(); i++) {
if (numbers.get(i)<min){
min = numbers.get(i);
}
}
return min;
}
4.计算平均值
/**
* 返回某一列数据的平均值
* @param allData
* @param lineNumber
* @return avg
*/
public static double getAvg(String[][] allData,int lineNumber){
ArrayList<Double> numbers = new ArrayList<>();
for (int i = 1; i < allData.length; i++) {
if (allData[i][lineNumber-1] != "") { //如果不判空会导致empty String错误,
numbers.add(Double.valueOf(allData[i][lineNumber - 1]));//将字符串转为数字
}else { //为空
}
}
double sum =0;
for (int i = 0; i < numbers.size(); i++) {
sum += numbers.get(i);
}
double avg = sum/(numbers.size());
return avg;
}
三.写入csv文件
目的主要是为了缺值处理
2.1步骤
第一步:先读取源文件,存入二维数组,与前文一致
第二步:找处缺点处坐标,将二维数组补齐
第三步:将二维数组写入新文件
2.2开始创建CsvWriter文件
与前文一致
//第一步,创建一个空二维数据准备存数据,创建缓冲流读取出文件的行数
String filePath = "D:\\wy.csv";
String[][] allData ; //创建二维数组
BufferedReader br = new BufferedReader(new FileReader(filePath));// 创建缓冲流读取行
int lineNumber = 0; // 记录文件行数
while (br.readLine() != null) {//读取文件行数
lineNumber++;
}
//第二步,重置缓冲流,将行数赋给数组,用字符串记录每一行的数据,用逗号分割,存入二维数组
br = new BufferedReader(new FileReader(filePath));//将缓冲流重置
allData = new String[lineNumber][];
String line; //每一行的数据
lineNumber = 0;
while ((line = br.readLine()) != null) {
String[] data = line.split(","); //用一个一维数组存,将每一行元素用逗号分开
allData[lineNumber] = data;
lineNumber++;
}
br.close();
接下来用方法找出缺点
/**
* 返回缺点处的坐标
* @param allData
* @return site
*/
public static int[] getFlaw(String[][] allData){
int []site =new int[2]; //建立一个数组代表点的坐标
for (int i = 0; i < allData.length; i++) {
for (int j = 0; j < allData[0].length; j++) {
if (allData[i][j] .equals("")) {
site[0] = i+1; //初始的i和j指数组里面的坐标,由于数组的索引从0开始,加一是csv文件的坐标
site[1]=j+1;
System.out.println("缺点在allData中坐标为"+i+","+j);
}
}
}
return site;
}
最后补齐二维数组再写入
BufferedWriter bw = new BufferedWriter(new FileWriter("D:\\wy2.csv"));
int []site = getFlaw(allData);
System.out.println("缺点坐标为"+site[0]+","+site[1]);
double avg = CsvReader.getAvg(allData,site[1]);//将缺点的列数传入csvReader的方法,算出平均数
allData[site[0]-1][site[1]-1] = String.valueOf(avg);//用平均值补齐二维数组
for(String[] str: allData){ //将二维数组分成一行行字符串,即一维数组
String context = str[0];
for (int i = 1; i < allData[0].length; i++) { //从第二个开始拼接逗号
context = context+","+str[i];
}
bw.write(context);
bw.newLine();//换行
}
bw.close();