问题描述
Java是“按值调用”,但是当我传递CSVReader对象时,它正在按引用进行调用。
private CSVReader csvReader=null;
public String getColumn(String filePath,String tagValue,int inputColumn,int outputColumn) throws Exception {
if(csvReader == null){
FileReader fileReader = new FileReader(filePath);
csvReader= new CSVReader(fileReader);
}
return fileReader(csvReader,tagValue,inputColumn,outputColumn);
}
private String fileReader(CSVReader csvReader1,int tagValue,int inputIndex,int outputIndex) throws Exception {
String[] value = csvReader1.readNext();
while ((value = csvReader1.readNext()) != null) {
String inputColumnValue = value[inputIndex];
String ouputColumnValue = value[outputIndex];
if(isNullOrEmpty(inputColumnValue) && isNullOrEmpty(ouputColumnValue))
if(inputColumnValue.equals(tagValue))
return ouputColumnValue;
}
return null;
}
例如:
输入文件包含:
a1,b1,c1
a2,b2,b3
a3,b3,c3
可以说,我正在这样调用fileReader:
getColumn(input file,"a3",2);
然后,它将返回c3作为输出。 如果我再这样叫它:
getColumn(input file,2);
然后,它将返回异常。 因为csvReader通过引用传递而不是通过值调用。 首先,当getColumn调用csvReader指向第0行时。 但是经过处理后,当我再次调用它时,它将在N + 1行上。 因此,它将返回异常。
任何可重复使用getColumn()的解决方案。
解决方法
参数始终在Java中按值传递。您遇到的问题是该值实际上是对位于堆内存中的真实对象的引用。
对于您而言,每当调用getColumn
方法时,都必须创建一个新的csvReader实例。
public String getColumn(String filePath,String tagValue,int inputColumn,int outputColumn) throws Exception {
FileReader fileReader = new FileReader(filePath);
CSVReader csvReader= new CSVReader(fileReader);
return fileReader(csvReader,tagValue,inputColumn,outputColumn);
}
使用filePath
作为输入参数是每次必须创建新的csv实例的另一个原因。
没有人可以保证您第二次通话的路径相同。
我在这里发现的另一个问题是这部分:
if(isNullOrEmpty(inputColumnValue) && isNullOrEmpty(ouputColumnValue))
if(inputColumnValue.equals(tagValue))
return ouputColumnValue;
如果inputColumnValue
为空或为空,那么问inputColumnValue.equals(tagValue)
就没有多大意义。特别是如果它为NULL,则将得到NullPointerException。
这里是一个如何从CSV(通知阅读器关闭部分)读取所有数据的示例
public List<String[]> readAll(Reader reader) throws Exception {
CSVReader csvReader = new CSVReader(reader);
List<String[]> list = new ArrayList<>();
list = csvReader.readAll();
reader.close();
csvReader.close();
return list;
}
如果您的csv不太大,也许您可以阅读一次csv内容,然后每次下一次遍历列表,而不是一遍又一遍地打开csv。