有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java将csv数据解析为具有不同列长度的对象

我是Java新手,正在练习将csv文件解析到对象中。我已经试过了,但还是想不出来

该文件如下所示:

  [0],    [1], [2],    [3]  ,    [4]    ,   [5]   ,  [6] ,   [7]  ,  [8] , [9]
class, gender, age, bodyType, profession, pregnant, isYou ,species, isPet, role
scenario:green,   ,         ,           ,         ,        ,      ,      ,
person, female, 24, average ,           , FALSE   ,        ,      ,      , passenger
animal, male  ,  4,         ,           , FALSE   ,        , dog  , TRUE , pedestrian
scenario:red
person, male  , 16, athletic, boxer     , FALSE   ,  TRUE  ,      ,      , passenger
person, female, 25, athletic, doctor    , TRUE    ,  FALSE ,      ,      , pedestrian

我需要在任何情况下,由任意数量的乘客和行人对其进行分析。最后,将这些场景添加到ArrayList中进行分析

我认为:

  1. 在每条线路上循环,到达下一个scenario:red时停止,将乘客和行人添加到Character阵列列表中。(我已经添加了,但不知道如何停止)
  2. 使用构造函数scenario(ArrayList<Character> passenger, ArrayList<Character> pedestrians, boolean redOrGreen);创建一个scenario
  3. ArrayListscenarios添加创建的场景

我所做的是把所有的东西放在一起,而不是把它们分开。非常感谢您的任何帮助或提示

感谢这个社区帮助我,以下是我迄今为止所得到的

    public void loadCsv() throws IOException {

    String csvFile = "config.csv";
    String line = "";
    String csvSplit = "\\s*,\\s*";

    Scenario scenario = new Scenario();
    Person person = new Person();
    Animal animal = new Animal();

    ArrayList<Scenario> scenaios = new ArrayList<Scenario>();
    ArrayList<String> csvContents = new ArrayList<String>();

    ArrayList<Character> passengers = new ArrayList<Character>();
    ArrayList<Character> pedestrians = new ArrayList<Character>();

    try (BufferedReader csvReader = new BufferedReader(new FileReader(csvFile));) {
        String headerLine = csvReader.readLine(); //get rid of the header
        //add each line to the arrayList
        while ((line = csvReader.readLine()) != null) { 
            csvContents.add(line);   
        }

        for(String csvLine : csvContents) {                
            String[] data = csvLine.split(csvSplit); // split by comma and remove redundant spaces

            if (data.length == NO_OF_FIELD) { //check and avoid indexOutOfBoundException

                String clazz = data[0].toLowerCase();// cannot use word "class" as a variable

                if (clazz.startsWith("scenario") && data.length == 1) { 
                    scenario = new Scenario();
                    scenario.setLegalCrossing(clazz.endsWith("green"));
                    continue;
                } 

                else if ("person".equals(clazz) && data.length ==10) {

                    person = loadCsvPerson(data);
                    addCharacter(person, data);

                } 

                else if ("animal".equals(clazz) && data.length ==10) {

                    animal = loadCsvAnimal(data);
                    addCharacter(animal, data);

                    }                        
                }
            }                               
        }
        //passenger and pedestrians are in position
        System.out.println("passengers: " + passengers);
        System.out.println("pedestrians: " + pedestrians);

        if (null != scenario) {
            scenario.setPassengers(passengers);
            scenario.setPedestrians(pedestrians);
        }

    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } 
}

共 (4) 个答案

  1. # 1 楼答案

    如果可以更改csv文件格式,我将添加scenario type列(以及scenario id或name,如果需要),以便在连接表(scenario+passenger+Pedering)并返回普通行时,可以使用csv文件作为数据库中的结果集

    使用这种方法,您将能够将解析委托给任何csv库,并分别执行您的逻辑(按场景id/名称/类型分组)。使用代理行(场景:绿色…)您必须编写自定义解析器

    例如,您可以使用univocity简单地将文件解析到您的模型中(甚至使用注释),并迭代地对其进行分组和处理

  2. # 2 楼答案

    或者,如果需要使用现有文件格式,请执行以下操作:

    if (clazz.startsWith("scenario") && data.length == 1) { 
        // collect existing scenario before starting processing new one
        if (scenario != null) {
            scenario.setPassengers(passengers);
            scenario.setPedestrians(pedestrians);
    
            passengers = new ArrayList();
            pedestrians = new ArrayList();
    
            scenarios.add(scenario);
        }
    
        // now start new group (scenario)
        scenario = new Scenario();
        scenario.setLegalCrossing(clazz.endsWith("green"));
        continue;
    } 
    
  3. # 3 楼答案

    我需要在第二轮中添加上一个scenario。 由于最后一组数据不会被捕获,我需要设置另一个新的scenario来添加它。谢谢你的艺术,先生

    Character character = null;
        try (BufferedReader csvReader = new BufferedReader(new FileReader(csvFile));) {
            String headerLine = csvReader.readLine(); //get rid of the header
            //add each line to the arrayList
            while ((line = csvReader.readLine()) != null) { 
                csvContents.add(line);   
            }
            final int NO_OF_FIELDS = 10;
    
            for(String csvLine : csvContents) {                
                String[] data = csvLine.split(csvSplit); // split by comma and remove redundant spaces                
                String clazz = data[0].toLowerCase();// cannot use word "class" as a variable
    
                if (clazz.startsWith("scenario") && data.length == 1) {
                    // adding scenario after one set of data
                    // i.e second round adding the first round data
                    if (passengers.size() != 0 && pedestrians.size() != 0) {
                        Scenario scenario = new Scenario();
                        scenario.setPassengers(passengers);
                        scenario.setPedestrians(pedestrians);
                        scenarios.add(scenario);
                    }
    
                    passengers = new ArrayList<Character>();
                    pedestrians = new ArrayList<Character>();
    
                    if (clazz.endsWith("green")) {
                        scenario.setLegalCrossing(true);
                        System.out.println("green light");
                    }
    
                    else if (clazz.endsWith("red")){
                        scenario.setLegalCrossing(false);
                        System.out.println("red light");
                    } 
    
                    continue;
                }
            //...
                Scenario scenario = new Scenario();
                scenario.setPassengers(passengers);
                scenario.setPedestrians(pedestrians);
                scenarios.add(scenario);
    
                scenario.setPassengers(passengers);
                scenario.setPedestrians(pedestrians);
    
                Audit audit = new Audit();
                audit.setScenario(scenarios);
    
  4. # 4 楼答案

    需要在代码中解决以下问题:

    1. 尽量避免使用标准库已经使用过的类的名称(特别是当它在默认包中时,java.lang),例如,Java库中已经有一个类Character,因此您应该为自定义类使用不同的名称

    2. 使用continue跳过行scenario:red

      for(String csvLine : csvContents) { 
          if(csvLine.equals("scenario:red")){
              continue;
          }
          String[] data = csvLine.split(csvSplit); // split by comma and remove redundant spaces
      
          if (data.length == NO_OF_FIELD) {
              //..
          }
          //..
      }
      
    3. 如果已经定义了final int NO_OF_FIELD = 10,则可以使用相同的值,而不是直接使用值10,即在以下代码中应使用NO_OF_FIELD而不是10

      if (data.length == NO_OF_FIELD) { //check and avoid indexOutOfBoundException
      
          String clazz = data[0].toLowerCase();// cannot use word "class" as a variable
      
          //...
      
          else if ("person".equals(clazz) && data.length ==10) {
      

      但是,您还需要了解&& data.length ==10在这里是不必要的,因为您已经在封闭的if条件中选中了data.length == NO_OF_FIELD

    我无法理解你其余的观点。如果你能澄清这些问题,我将能进一步帮助你