【问题标题】:Method reads csv input stream differently than csv file方法读取 csv 输入流与 csv 文件不同
【发布时间】:2022-01-24 15:55:12
【问题描述】:

我的任务是编写一个方法,该方法将接收一个 csv 文件并将其数据保存到数据库中的适当空间中。当直接输入csv数据时,我编写的函数就成功了。但是,当使用 cURL 并输入整个 csv 文件时,它不会读取换行符。实际上,csv 然后变成一行 x 列数,其中 x 是文件中的单元格数。我尝试更改 csv 格式(例如使用回车与换行),但似乎没有任何效果。附件是通过csv运行的代码,它接受InputStream csvData

CSVReader reader = new CSVReader(new InputStreamReader(csvData));
String[] line;
int bookNum = 1, lineNum = 2; // skip headers
while ((line = reader.readNext()) != null) {
    // map line
    String productCode = line[0]; 
    String author = line[1];
    String description = line[2];
    Integer edition;
    try {
        edition = Integer.parseInt(line[3].replaceAll("[^\\d.]", ""));
    } catch (NumberFormatException nfe) {
        edition = null;
    }
    String copyright = line[4];
    String publisher = line[5];
    BigDecimal listPrice = !line[6].equals("") ? new BigDecimal(line[6]) : null;

    // do stuff with data...

    if (bookNum == 1) System.out.println("1 book has been processed");
    else System.out.println(bookNum + " books have been processed");
    ++bookNum;
    ++lineNum;
}

【问题讨论】:

  • 您应该简化问题以隔离问题。听起来您正在下载的文件无效并且缺少行尾字符,但这也可能是您将下载内容写入磁盘的方式。
  • @Deadron 我对 csv 执行了 hexdump,它似乎有行尾字符,但 CSVReader 似乎无法识别它们。
  • 会不会是windows和linux EOL字符的区别?
  • @Yepher 这是我的第一个猜测,但我尝试了 EOL 字符的回车和换行,但似乎没有任何区别。
  • 如何在该代码中将数据打包到“csvData”中?填充该变量时,您是否可能正在执行“readline”?如果是这样,在那种情况下它是否剥离了 \n?

标签: java csv curl opencsv


【解决方案1】:

这对我有用。我认为问题在于您的输入 csvData 是如何形成的。当您尝试时,这是否有效?

import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;

import com.opencsv.CSVReader;
import com.opencsv.exceptions.CsvValidationException;

public class TestCsv {

    private static final String TEST_CSV = "ISBN,Author,Title,Edition,Copyright,Publisher,Value,Grade\n"
            + "1781435460553,1ALTEN,1WORKING WITH AUDIO (PB),12,,1CENGAGE L,0.01,1\n"
            + "2781435460553,2ALTEN,1WORKING WITH AUDIO (PB),22,,2CENGAGE L,0.02,2\r\n"
            + "3781435460553,3ALTEN,1WORKING WITH AUDIO (PB),32,,3CENGAGE L,0.03,3\r\n";

    public static void main(String[] args) throws CsvValidationException, UnsupportedEncodingException, IOException {
        System.out.println("String Test");
        parseCsv(new ByteArrayInputStream(TEST_CSV.getBytes("UTF-8"))); // from String
        
        System.out.println("\n\n---------------------\nFrom File Test");
         String fileName = "/tmp/test.csv";

            try (FileInputStream fis = new FileInputStream(fileName)) {
                parseCsv(fis);
            }
        
        
        
    }

    public final static void parseCsv(InputStream csvData) throws CsvValidationException, IOException {
        CSVReader reader = new CSVReader(new InputStreamReader(csvData));
        String[] line;
        int bookNum = 1, lineNum = 2; // skip headers
        while ((line = reader.readNext()) != null) {
            // map line
            String productCode = line[0];
            String author = line[1];
            String description = line[2];
            Integer edition;
            try {
                edition = Integer.parseInt(line[3].replaceAll("[^\\d.]", ""));
            } catch (NumberFormatException nfe) {
                edition = null;
            }
            String copyright = line[4];
            String publisher = line[5];
            String listPrice = line[6];

            // do stuff with data...

            if (bookNum == 1) {
                System.out.println("1 book has been processed");
            } else {
                System.out.println(bookNum + " books have been processed");
            }
            
            ++bookNum;
            ++lineNum;
        }

    }

}

这也适用于我,所以不太确定您遇到了什么问题:

    System.out.println("standard input");
    try {
        parseCsv(System.in);
    } catch (IOException e) {
        // If nothing is passed in
        e.printStackTrace();
    }

【讨论】:

  • 它仍然将所有数据读取到一行中......这一定是输入文件有问题。
【解决方案2】:

我认为没有办法实现你想要的 reader.readNext() 本身返回数组表示 CSV 文件的列,数组中的列按 CSV 文件中列的顺序索引,您可以通过事先知道列标题来操作数组,以便您可以正确获取数据。 基于此:

line[0] 将是您的第一列 / line[1] 将是第二列,依此类推。

更新添加一些代码,请尝试此代码而不是您的代码,并告诉我们结果如何

InputStream inputStream = Files.newInputStream(Paths.get(ClassLoader.getSystemResource("csv/test.csv").toURI()));
    List<String[]> list = new ArrayList<>();
    CSVReader csvReader = new CSVReader(new 
                                     InputStreamReader(inputStream));
    String[] line;
    while ((line = csvReader.readNext()) != null) {
        System.out.println(line[0]+" --- "+line[1]);
        list.add(line);
    }
    inputStream.close();
    csvReader.close();
    return list;

我的文件在同一个项目的类路径中,我假设数据如下:

colA | colB
 A   | B
 C   | D
 D   | E

输出如下:

colA --- colB
 A --- B
 C --- D
 E --- F

【讨论】:

  • 是的,目标是能够根据其列标题操作数据。这里的问题是由于某种原因没有逐行读取数据。取而代之的是,所有数据都作为一行读入,因此数据没有按预期分为列(即 readNext 不是 20 行和 6 列,而是返回 1 行,每列 120 列。
猜你喜欢
  • 1970-01-01
  • 2018-11-01
  • 1970-01-01
  • 2023-01-31
  • 1970-01-01
  • 1970-01-01
  • 2017-06-29
  • 2011-03-09
  • 1970-01-01
相关资源
最近更新 更多