【问题标题】:Reading from csv files从 csv 文件中读取
【发布时间】:2016-02-29 15:47:25
【问题描述】:

这是我在大学时正在做的一个项目,除了初始化游戏的游戏类之外,一切似乎都很好。这是一个sn-p

public class Game{
 private Player                         player;
 private World                          world;
 private ArrayList<NonPlayableFighter>  weakFoes;
 private ArrayList<NonPlayableFighter>  strongFoes;
 private ArrayList<Attack>              attacks;
 private ArrayList<Dragon>              dragons;

public Game() throws IOException{
    player      = new Player("");
    world       = new World();
    weakFoes    = new ArrayList<NonPlayableFighter>();
    strongFoes  = new ArrayList<NonPlayableFighter>();
    attacks     = new ArrayList<Attack>();
    dragons     = new ArrayList<Dragon>();
    loadAttacks ("Database-Attacks_20309.csv");
    loadFoes    ("Database-Foes_20311.csv");
    loadDragons ("Database-Dragons_20310.csv");
}

之后是一些 getter 和我应该实现的 4 种方法。 这些方法是loadCSV(String filePath),loadAttacks(String filePath),loadFoes(String filePath),loadDragons(String filePath)
我创建了loadCSV(String filePath),以便它在此处返回 String[] 的 ArrayList:

private ArrayList<String[]> loadCSV(String filePath) throws IOException{
    String currentLine          = ""; 
    ArrayList<String[]> result  = new ArrayList<String[]>();
    FileReader fileReader       = new FileReader(filePath); 
    BufferedReader br           = new BufferedReader(fileReader); 
    currentLine                 = br.readLine();
    while (currentLine != null){ 
        String[] split = currentLine.split(",");
        result.add(split);
    }
    br.close();
    return result;
}

然后我想加载一些攻击、敌人和龙,并将它们插入到适当的 ArrayList 中。
我在这里申请了loadAttacks(String filePath)

private void loadAttacks(String filePath) throws IOException{
    ArrayList<String[]> allAttacks = loadCSV(filePath);
    for(int i = 0; i < allAttacks.size(); i++){
        String[] current = allAttacks.get(i);
        Attack temp = null;
        switch(current[0]){
            case "SA": temp = new SuperAttack(current[1], 
                    Integer.parseInt(current[2]));
                    break;
            case "UA": temp = new UltimateAttack(current[1], 
                    Integer.parseInt(current[2]));
                    break;
            case "MC": temp = new MaximumCharge();
                    break;
            case "SS": temp = new SuperSaiyan();
                    break;
        }
        attacks.add(temp);
    }
}

我这样编写它,它采用从loadCSV(String filePath) 返回的 ArrayList,并使用开关在第一个 String 上的 ArrayList 中的每个 String[] 中搜索,从而创建适当的攻击并将其添加到攻击中。
然后我想为敌人读取另一个 CSV,并且 CSV 文件的结构使得第一行有一些属性,第二行有一些超级攻击类型的攻击,第三行有一些终极攻击类型的攻击。同样在每个敌人中都有一个布尔属性,用于确定它是强敌人还是弱敌人,从而将其放入正确的 Arraylist 中。这是loadFoes(String filePath)的代码:

private void loadFoes(String filePath) throws IOException{
    ArrayList<String[]> allFoes = loadCSV(filePath);
    for(int i = 0; i < allFoes.size(); i += 3){
        String[] current                            = allFoes.get(i);
        String[] supers                             = allFoes.get(i+1);
        String[] ultimates                          = allFoes.get(i+2);
        ArrayList<SuperAttack> superAttacks         = new ArrayList<SuperAttack>();
        ArrayList<UltimateAttack> ultimateAttacks   = new ArrayList<UltimateAttack>();
        NonPlayableFighter temp = null;
        for(int j = 0; i < supers.length; j++){
            int index = attacks.indexOf(supers[j]);
            if(index != -1){
                superAttacks.add((SuperAttack)attacks.get(index));
            }
            else break;
        }
        for(int j = 0; i < ultimates.length; j++){
            int index = attacks.indexOf(ultimates[j]);
            if(index != -1){
                ultimateAttacks.add((UltimateAttack)attacks.get(index));
            }
            else break;
        }
        if(current[7].equalsIgnoreCase("True")){
            temp = new NonPlayableFighter(current[0], Integer.parseInt(current[1]), 
                            Integer.parseInt(current[2]), Integer.parseInt(current[3]), 
                            Integer.parseInt(current[4]), Integer.parseInt(current[5]), 
                            Integer.parseInt(current[6]), true, superAttacks, ultimateAttacks);

            strongFoes.add(temp);
        }
        else{
            temp = new NonPlayableFighter(current[0], Integer.parseInt(current[1]), 
                            Integer.parseInt(current[2]), Integer.parseInt(current[3]), 
                            Integer.parseInt(current[4]), Integer.parseInt(current[5]), 
                            Integer.parseInt(current[6]), false, superAttacks, ultimateAttacks);

            weakFoes.add(temp);
        }
    }
}

首先,我得到从loadCSV(String filePath 返回的 ArrayList 中的前三个 String[] 并进行 2 个循环以检查攻击是否在先前加载的攻击 CSV 中,然后我检查确定它是强还是强的属性弱并相应地创建一个新的NonPlayableFighter 并将其添加到适当的列表中。

为这个作业运行 jUnit4 测试它给了我一个编译错误:未处理的异常类型 IOException。一般来说,代码有什么明显的问题吗?

【问题讨论】:

  • 您是否在主类或 main() 中处理了异常(使用 try/catch 或 throws)?
  • 进入 loadCSV() 方法,添加 currentLine = br.readLine();也进入while循环。

标签: java csv arraylist


【解决方案1】:

如果不是您任务的一部分,最好重用已经存在的 Java CSV 文件阅读器(例如 CVSReader)。

【讨论】:

  • 创建loadCSV方法是一个任务
  • @alimoenes 我明白了...在这种情况下,我宁愿将BufferedReader 作为loacCSV 方法的参数。这将使您的方法更加通用:您可以从任何来源(文件、内存、网络...)读取 CSV 数据。此外,您必须在读取数据循环中添加另一个 readLine 调用,以便不仅读取第一个 CSV 行。
  • 我无法理解有关缓冲阅读器的部分。我会尝试将 readline 放在循环中并给你反馈。谢谢
  • @alimoenes 最好更改:从您的 loadCSV(String filePath) 更改为 loadCSV(Reader reader)。在此更改之后,您可以同时调用您的方法loadCSV(new FileReader("Database-Attacks_20309.csv"))loadCSV(new StringReader(...string constant in memory...))(这很好,例如用于测试您的方法)和loadCSV(new URLReader(new URL("http://...")))(用于从网络读取)。这将使您的loadCSV 独立于数据源(文件、字符串、网络...)并且使用更加灵活。
【解决方案2】:

这会产生很多代码。我会回答你的编译错误。

在读取文件时,您必须将代码放入 try catch 中以避免此类错误。在您的 loadCSV 方法中,您必须设置一个 try catch 块。

完整教程请参考this site

try (BufferedReader br = new BufferedReader(new FileReader("C:\\testing.txt")))
    {

        String sCurrentLine;

        while ((sCurrentLine = br.readLine()) != null) {
            String[] split = currentLine.split(",");
            result.add(split);
        }

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

简而言之,访问文件的代码必须在 try catch 中以避免 IO 异常,或者在抛出异常的方法中(但必须在其他地方捕获)。

在该代码中,您有一个很好的资源尝试示例,是管理资源和内存的好方法。

【讨论】:

  • 谢谢,我们还没有使用异常,这个里程碑的目的是在不使用 try、catch、throw 等的情况下工作。我们给出了一个关于如何构建 csv 阅读器的示例,我们应该确定返回类型并进行调整。
  • 这种考虑不适用于语言 ^^ 一切都适用于语言。但是您是否想避免使用 try-catch(我建议您无论如何都要尝试一下:p),您必须确保您的主要方法具有 throws IOException 。堆栈的每个方法都应该有它来让异常消失。
【解决方案3】:

loadCSV(String filePath) 不是无限循环吗?至于 IOException,正如@RPresle 建议的那样,try/catch 可以解决 BufferedReader 的问题。

【讨论】:

    猜你喜欢
    • 2012-03-09
    • 2015-05-23
    • 2013-05-03
    • 1970-01-01
    • 1970-01-01
    • 2015-11-26
    • 2023-04-03
    • 1970-01-01
    相关资源
    最近更新 更多