【问题标题】:Java CSVReader skips rows & how to transform csvJava CSVReader 跳过行以及如何转换 csv
【发布时间】:2017-04-28 16:09:33
【问题描述】:

我整天都在研究。而且无论我如何编码,结果都不是我想要的。

首先,我正在处理大数据,因此,我认为保留复制和粘贴行条目效率不高。 我正在阅读一个 CSV 文件,它正在工作,它正在删除我告诉它要删除的所有内容。到目前为止一切都很好。现在,唯一出错的是(我认为)Eclipse(Java)从 csv 文件中删除了标题/列名。如何解决这个问题?

package data;

import java.io.FileReader;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;

import com.opencsv.CSVReader;

public class BelgiumParser {

public static void main(String[] args) {
    // TODO Auto-generated method stub

    //List<String> listBelgium;
    String fileName = "src\\data\\Belgium.csv";


    try{
        List<String> listBelgium = Files.readAllLines(Paths.get(fileName));

        //CSVReader reader = new CSVReader(new FileReader("src\\data\\Belgium.csv"), ',', '"', 1);

        for(String line : listBelgium){

            line = line.replace("\"" , "");
            line = line.replaceAll("T", " ");
            line = line.replaceAll("Z", "");                

            System.out.println(line);

    }}catch(Exception e){
        //System.out.println(e.getMessage());       
        e.printStackTrace();

    }
}

}

还尝试了while循环:

while(line = bufferedReader.readLine()) != null){...}

是的,我尝试了 bufferedReader 和 CSVReader。我什至可能已经找到了 Python 解决方案?

headers = next(reader, None)  # returns the headers or `None` if the input is empty

if headers:
    writer.writerow(headers)

不是我的代码,不知道如何链接。主要问题:

  • 我怎样才能不仅确保打印标题(有效的方式,我不想复制/粘贴一段代码)?
  • 另外,我怎样才能让阅读器也垂直写入一些标题(转换)?

更新:

包含数百行数据: -没有测量等于空 - 测量等于整数或双倍(?)

应该发生的是: - 到时候,T和Z都得走了。 - T 应该是一个空格:“”,而 Z 只是“” - B 列及更高的第 1 行应仅包含植物名称本身。

最终,应该能够将这一切以清晰的格式放入 MySQL 数据库中,这样就可以在 Java Server Faces(类?)中使用 D3.js 折线图来实现它

【问题讨论】:

  • How can I make the Reader also Write the some of the headers vertically (Transforming)?这是什么意思?
  • 想象一下 Excel:第 1 行包含列的标题。我想插入一个新行 (B),从而使所有内容都向右移动一个。然后,从 B 列第 1 行开始,我想翻译这个并让它写在 newRowB

标签: java eclipse csv reader


【解决方案1】:

如果您正在处理大数据,那么我建议您获取univocity-parsers,因为它比其他任何东西都快得多。然后尽量不要将所有行加载到内存中,因为这是一个明显的问题,而是将它们流式传输。下面是一个简单的示例,可以帮助您入门:

CsvParserSettings settings = new CsvParserSettings();
settings.detectFormatAutomatically(); //you can configure the format manually if you prefer.
 parserSettings.setHeaderExtractionEnabled(true); //you want to get the headers from the input
settings.selectFields("a", "b", "c"); //select just the columns you need.

CsvParser parser = new CsvParser(settings);

File input = Paths.get(fileName).toFile();
parser.beginParsing(input, "UTF-8");

String[] row;
while ((row = parser.parseNext()) != null) {
    //do your stuff here.

    //here are your headers
    String[] headers = parser.getContext().parsedHeaders();
}

如果我理解正确,您的第二个问题是您想要转置行,即让列的所有数据与标题相关联。

为此,请使用ColumnProcessor(这会将所有数据加载到内存中,稍后我将向您展示替代方法):

ColumnProcessor columnProcessor = new ColumnProcessor();
parserSettings.setProcessor(columnProcessor);

CsvParser parser = new CsvParser(parserSettings);
parser.parse(input, "UTF-8"); //all rows are submitted to the processor created above.

//At the end of the process, you can get your data like this:
Map<String, List<String>> columnValues = new TreeMap<String, List<String>>(columnProcessor.getColumnValuesAsMapOfNames());

如果数据过多,则需要批量执行转置操作。为此使用BatchedColumnProcessor

BatchedColumnProcessor columnProcessor = new BatchedColumnProcessor(20000 /*runs batches of 20000 rows each*/) {
    @Override
    public void batchProcessed(int rowsInThisBatch) {
        Map<Integer, List<String>> columnsByIndex = getColumnValuesAsMapOfIndexes();

       //process your batch here
    }
};

这应该可以完美运行。希望对您有所帮助。

免责声明:我是这个库的作者,它是开源免费的(Apache V2.0 许可)

【讨论】:

  • 这看起来太令人兴奋了!一旦我再次拿到我的笔记本电脑就会尝试它!今天会处理它,让你知道!
  • 它似乎打印某些东西。不是我认为应该的格式。我相信它与 parserSetting 类有关。它不应该是可导入的吗?
  • 我不清楚您有什么输入以及您期望的输出是什么。您能否使用包含几个输入行的示例以及您期望获得的输出来更新您的问题?
  • 希望可以理解?如果没有,我很乐意更详细地解释
  • 我终于让它工作了!结束了,没有使用你的代码,但我从中学到了很多!非常感谢!
【解决方案2】:
CSVReader reader = new CSVReader(new FileReader("src\\data\\Belgium.csv"), ',', '"', 1);

上面代码中的最后一个参数,您要求 CSVReader 在读取文件时跳过第 1 行。而是使用默认值(零),以便它也读取标题。

CSVReader reader = new CSVReader(new FileReader("src\\data\\Belgium.csv"), ',', '"', CSVReader.DEFAULT_SKIP_LINES);

关于第二个问题,您必须通过将行读入维护顺序的数组或列表来编写自定义逻辑,并使用增量索引处理写入。

【讨论】:

  • 啊哈!谢谢!会试试的!希望能解决1个问题!非常感谢!
  • 太棒了。告诉我进展如何。
  • 再次感谢您的建议!我尝试过这个。但是,当我这样做时,IDE 根本没有运行。
  • 感谢您的宝贵时间!我最终使用了第一行。它有效:D
【解决方案3】:

最好的方法可能是让它读取列的每个值,然后将其存储到数组中。然后将其写入一个新的转换后的 CSV 文件,该文件将按照您想要的任何顺序在一行中打印整个数组。

我真的不能给你一些伪代码,因为我对任何 CSV 阅读器库都不完全熟悉,但通常很容易找到一个并使用 Javadoc 来实现它

【讨论】:

  • 感谢您的评论。我也是 CSV 阅读器库的新手。一直在互联网和书籍上。但不是更明智...我喜欢这个想法,并试图做到这一点。没有成功
【解决方案4】:

终于实现了我想做的:

package code;

import com.opencsv.CSVReader;
import com.opencsv.CSVWriter;

import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class BelgiumParser {

    public static void main(String[] args) throws IOException {

        String fileName = "src/data/Belgium.csv";

        try (CSVReader reader = new CSVReader(new FileReader(fileName), ',', '"', 1)) {
            String[] nextLine;

            while ((nextLine = reader.readNext()) != null) {

                for (String line : nextLine) {

                    line = line.replaceAll("T", " ");
                    line = line.replaceAll("Z", "");
                    line = line.replaceAll("ActualGenerationPerUnit.mean", "");
                    line = line.replaceAll("Plantname:", "");
                    //Escaping curly braces is a must!
                    line = line.replaceAll("\\{", "");
                    line = line.replaceAll("\\}", "");
                    System.out.println(line);

                }


            }
        }
    }}

仍然不够高效,但可以完成工作..

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-02-02
    • 2019-03-16
    • 1970-01-01
    • 2023-04-09
    • 2019-07-06
    • 2021-10-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多