使用java解析csv,然后保存在2D数组中

使用java解析csv,然后保存在2D数组中,java,arrays,csv,multidimensional-array,Java,Arrays,Csv,Multidimensional Array,好的,我正在开发一个基于java的交易卡游戏的游戏。我将所有游戏peice的“信息”刮到一个csv文件中,其中每一行都是游戏peice,每一列都是该peice的一种属性。我花了好几个小时用缓冲读取器等编写代码,试图将csv文件中的信息提取到2d数组中,但没有成功。我的csv文件链接在这里:我有一年的计算机科学经验,但我仍然不知道如何做到这一点 因此,我的主要问题是如何将其放入2D数组中,以便保留行和列?我正在研究一个类似的问题,以便在机器学习中使用,因此,让我分享一下我在这个主题上所做的工作 1

好的,我正在开发一个基于java的交易卡游戏的游戏。我将所有游戏peice的“信息”刮到一个csv文件中,其中每一行都是游戏peice,每一列都是该peice的一种属性。我花了好几个小时用缓冲读取器等编写代码,试图将csv文件中的信息提取到2d数组中,但没有成功。我的csv文件链接在这里:我有一年的计算机科学经验,但我仍然不知道如何做到这一点


因此,我的主要问题是如何将其放入2D数组中,以便保留行和列?

我正在研究一个类似的问题,以便在机器学习中使用,因此,让我分享一下我在这个主题上所做的工作

1) 如果您在开始解析行之前知道(无论它是硬编码到您的程序中的还是您的文件中是否有提供此信息的头文件(强烈建议)-每行将有多少个属性,您可以用逗号合理地拆分它,例如,第一个属性将是RowString.substring(0,RowString.indexOf(',')),第二个属性将是从第一个逗号到下一个逗号的子字符串(编写一个函数来查找逗号的第n个实例,或者在遍历时简单地切掉字符串的一些位,应该是相当简单的),最后一个属性将是RowString.substring(RowString.lastIndexOf(',')),RowString.length())。字符串类的方法在这里是您的朋友

2) 如果无法区分用于分隔值的逗号和作为字符串格式属性一部分的逗号,则(如果文件足够小,可以手动重新格式化)执行Java所做的操作—用“\”表示字符串中具有特殊含义的字符,而不只是“,”。这样,您就可以搜索“,”而不是“\”的索引,这样您就有了一些区分字符的方法

3) 作为2)的替代方案,CSV(在我看来)不适合字符串,因为字符串通常包含逗号。CSV没有真正的通用格式,所以为什么不让它们使用冒号分隔的值、破折号分隔的值,甚至三个安培和分隔的值呢?用逗号分隔值的目的是使它们易于区分,如果逗号不起作用,就没有理由保留它们。同样,这仅适用于文件小到可以手动编辑的情况

4) 查看您的文件不仅仅是查看格式,很明显您无法手动完成。此外,有些字符串似乎被三个双引号(“字符串”)包围,有些字符串被单双引号(“字符串”)包围。如果我不得不猜测的话,我会说引号中包含的任何内容都是单个属性——例如,没有以一个属性开头、以另一个属性结尾的引号对。所以我想说你可以: 使用一个方法创建一个类,将字符串拆分为每个逗号分隔的字段。
编写该方法,使其忽略前面带有奇数个双引号的逗号(这样,如果引号对尚未关闭,则它知道它位于字符串内部,并且逗号不是值分隔符)。但是,如果文件的创建者使用双引号(““string”)将一些字符串括起来,则此策略将失败,因此您可能需要更全面的方法。

正如前面提到的,您的一些字符串包含逗号,因此最初您的起点不好,但我有一个解决方案,它是这样的:

  • ---------如果可能,请重新扫描站点,但在执行此操作时,请执行简单的编码操作。您将需要做一些类似于您将注意到的事情,这些事情往往是在包含HTML的自动生成的XML文件中完成的;保留一个“控制字符”(出于调试和…嗯…理智的原因,这里的可打印字符效果最好),它一旦编码,就永远不能作为自身的实例直接读取。我喜欢使用符号,因为它很少见,但仍然可以打印,但真正想使用的字符取决于您。我要做的是编写程序,以便在每个“,”实例中,在写入CSV之前,逗号将替换为“&c”,在站点上的每个实际的“与”实例中,将“&”替换为“&a”。这样,你就不会有在CSV中意外地将一个值分成两个的问题,你可以简单地在用我将在中概述的方法将每个值分开后对它们进行解码

  • --------假设您知道每行中有多少列,您可以使用StringTokenizer类(查找-它很棒,内置于Java中。与往常一样,查找信息的好地方是Java教程)以数组的形式自动为您提供所需的值

    • 它的工作原理是传入一个字符串和一个分隔符(在本例中,分隔符是“,”),并输出所有由逗号分隔的子字符串。如果您从一开始就知道总共有多少块,那么可以在开始时实例化一个2D数组,只需插入StringTokenizer提供给您的每一行。如果不这样做,也没关系,因为可以使用ArrayList。ArrayList很好,因为它是数组的高级抽象,可以自动请求更多内存,这样您就可以继续添加到它中,并且知道检索时间始终是恒定的。但是,如果您计划动态添加片段,并且这样做的频率比检索片段的频率更高,那么您可能希望使用LinkedList,因为它具有线性检索时间,但是对于添加-删除时间,它的关系比ArrayList好得多。或者,如果你很棒的话,你可以用一个技工来代替。我不知道它们是否默认用Java实现,但它们非常棒。不过,这是一个公平的警告;可再生能源的速度成本
      R1C1|R1C2|R1C3|R1C4|R1C5|R1C6|R1C7|R1C8
      R2C1|R2C2|R2C3|R2C4|R2C5|R2C6|R2C7|R3C8
      R3C1|R3C2|R3C3|R3C4|R3C5|R3C6|R3C7|R3C8
      R4C1|R4C2|R4C3|R4C4|R4C5|R4C6|R4C7|R4C8
      A/D Changer|DREV-EN005|Effect Monster|Light|Warrior|100|100|You can remove from play this card in your Graveyard to select 1 monster on the field. Change its battle position.
      
          BufferedReader br = new BufferedReader(new FileReader(new File("MonstersFinal.csv")));
          String line = "";
      
          ArrayList<String[]> cardList = new ArrayList<String[]>(); // Use an arraylist because we might not know how many cards we need to parse.
      
          while((line = br.readLine()) != null) { // Read a single line from the file until there are no more lines to read
              StringTokenizer st = new StringTokenizer(line, "|"); // "|" is the delimiter of our input file.
              String[] card = new String[8]; // Each card has 8 fields, so we need room for the 8 tokens.
              for(int i = 0; i < 8; i++) { // For each token in the line that we've read:
                  String value = st.nextToken(); // Read the token
                  card[i] = value; // Place the token into the ith "column"
              }
              cardList.add(card); // Add the card's info to the list of cards.
          }
      
          for(int i = 0; i < cardList.size(); i++) {
              for(int x = 0; x < cardList.get(i).length; x++) {
                  System.out.printf("card[%d][%d]: ", i, x);
                  System.out.println(cardList.get(i)[x]);
              }
          }
      
      card[0][0]: R1C1
      card[0][1]: R1C2
      card[0][2]: R1C3
      card[0][3]: R1C4
      card[0][4]: R1C5
      card[0][5]: R1C6
      card[0][6]: R1C7
      card[0][7]: R1C8
      card[1][0]: R2C1
      card[1][1]: R2C2
      card[1][2]: R2C3
      card[1][3]: R2C4
      card[1][4]: R2C5
      card[1][5]: R2C6
      card[1][6]: R2C7
      card[1][7]: R3C8
      card[2][0]: R3C1
      card[2][1]: R3C2
      card[2][2]: R3C3
      card[2][3]: R3C4
      card[2][4]: R3C5
      card[2][5]: R3C6
      card[2][6]: R3C7
      card[2][7]: R4C8
      card[3][0]: R4C1
      card[3][1]: R4C2
      card[3][2]: R4C3
      card[3][3]: R4C4
      card[3][4]: R4C5
      card[3][5]: R4C6
      card[3][6]: R4C7
      card[3][7]: R4C8
      card[4][0]: A/D Changer
      card[4][1]: DREV-EN005
      card[4][2]: Effect Monster
      card[4][3]: Light
      card[4][4]: Warrior
      card[4][5]: 100
      card[4][6]: 100
      card[4][7]: You can remove from play this card in your Graveyard to select 1 monster on the field. Change its battle position.