【问题标题】:How to pass CSVReader object as call by value instead of call by reference in java?java - 如何将CSVReader对象作为值调用而不是java中的引用调用传递?
【发布时间】:2020-09-11 15:27:35
【问题描述】:

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", 0, 2);

然后,它将返回 c3 作为输出。 如果我再这样称呼它:

getColumn(input file, "a3", 0, 2);

然后,它会返回异常。 因为 csvReader 作为按引用调用而不是按值调用传递。 首先,当 getColumn 调用 csvReader 指向第 0 行时。 但是在处理完我再次调用它之后,它将位于 N+1 行。 所以,它会返回异常。

任何重用 getColumn() 的解决方案。

【问题讨论】:

  • 您的问题与 pass-by-value 或 pass-by-reference 无关。它是关于一个读者不能读两次的。这是一个单一的通过过程。如果你只想阅读一次并进行大量查询,则必须将内容加载到数据结构中并对其进行迭代。

标签: java csv file fileinputstream opencsv


【解决方案1】:

在 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。

【讨论】:

  • 嗨@Master Yoda,我已将 FileReader 创建为全局,因为我不想一次又一次地读取文件。并将 CSVReader 创建为本地。但它也不起作用。同样的问题。
  • 嗨 Krishna,每次都实例化新的阅读器实例应该可以解决问题。也许您仍然有问题,因为您没有关闭读者(只是猜测)。我会用一个小例子来更新我的答案
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-05-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-24
  • 2013-09-15
  • 2011-11-10
相关资源
最近更新 更多