2014-11-23 66 views
1

我想读取包含一行中的名称和分数的csv文件。我的代码工作正常,如果csv恰好有20个值(10个名称和10个分数)。如果csv文件为空或者值小于20,Im有困难。我的代码读取数组中的csv,然后将名称和分数存储在两个不同的数组中。然后比较新玩家的分数是否大于已存储在csv文件中的分数,如果是,则替换它,然后将所有更新的名称和分数存储在一个数组中。 csv文件最多可以有10个名字和10个分数,最小值可以是空的csv。如果csv文件为空,如何停止数组越界?

public class CompareLeaderboard { 

    public static void main(String[] args) { 

    CompareLeaderboard user = new CompareLeaderboard(); 
    user.run(); 
    } 

    public void run() { 

    String csvFileLoc = "/Documents/leaderboard.csv"; 
    BufferedReader br = null; 
    String line = ""; 
    String commaSeparator = ","; 
    int[] userScore = new int[10]; 
    String[] userName = new String[10]; 
    String[] userInfo = new String[20]; 
    int k = 0; 
    int h =0; 
    int z = 10; 
    int tempS; 
    String tempN; 
    int playerScore = 50; 
    String playerName = "Matt"; 
    boolean breaking = false; 

    try { 
    //int a = 1; 
    br = new BufferedReader(new FileReader(csvFileLoc)); 
    while ((line = br.readLine()) != null) { 

     // use comma as separator 
     //if(a==1){ 
    String[] userDetails = line.split(commaSeparator); 

    for(int j =0; j<20; j = j+2){ 
    userName[k] = userDetails[j]; 
    int foo = Integer.parseInt(userDetails[j+1]); 
    userScore[k] = foo; 
    k++; 
    } 

    // } 
    } 
    //a++; 
    } 



    catch (FileNotFoundException e) { 
    e.printStackTrace(); 
    } catch (IOException e) { 
    e.printStackTrace(); 
    } finally { 
     if (br != null) { 
     try { 
     br.close(); 
     } catch (IOException e) { 
    e.printStackTrace(); 
    } 
    } 
    } 


//checking 

for(int i = 0; i <10 ; i++){ 
    if(userScore[i] < playerScore) { 
    if(breaking == false){ 
    z = i; 
    breaking = true; 
    } 
    } 
    //else if(i==9 && userScore[i] > playerScore){ 
    //} 
} 
//storing 
if(z<10) { 
    for(int j = z; j< userName.length; j++){ 
     tempN = userName[j]; 
     tempS = userScore[j]; 
     userName[j] = playerName; 
     userScore[j] = playerScore; 
     playerName = tempN; 
     playerScore = tempS; 
    } 


    } 
    for(int i = 0; i < userName.length; i++){ 
    System.out.println(userName[i] + " = " + userScore[i]); 

    } 
    for(int s = 0; s<20; s = s+2) { 
    userInfo[s] = userName[h]; 
    String foo = String.valueOf(userScore[h]); 
    userInfo[s+1] = foo; 
    h++; 
    } 
    for(int i = 0; i < userInfo.length; i++){ 
    System.out.println(userInfo[i] + ", "); 

    } 
    } 
} 
+0

简单的答案,使用一个真正的CSV解析库。例如,[OpenCSV](http://opencsv.sourceforge.net/)非常出色。 – 2014-11-23 10:53:55

回答

1

您应该检查数组的长度而不是使用硬编码值。

for(int j = 0; j < userDetails.length; j = j+2)

而且因为你在访问索引j+1,你应减去1

for(int j = 0; j < userDetails.length -1; j = j+2)

0

我在C#写了一个CSV分析器前一阵子。即使它不是Java,逻辑也应该是一样的。希望这有助于

public static class CSV 
{ 
    public static String[] ParseCsvRecord(String csv, Char delimiter = ',', Char escape = '\"') 
    { 
     // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
     // Initialisierung 
     List<String> l = new List<String>(); 
     Char[] record = csv.ToCharArray(); 

     String property = ""; 
     Char c; 

     Boolean escaping = false; 

     // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
     // Betrachte jeden Buchstaben einzeln und interpretiere ihn 
     for (Int32 i = 0; i < record.Length; i++) 
     { 
      c = record[i]; 

      // Escape-Character: Einfach -> Escape; Doppelt -> Anhängen 
      if (c == escape) 
      { 
       if (i == record.Length - 1) 
       { 
        escaping = !escaping; 
       } 
       else if (escape == record[1 + i]) 
       { 
        property += c; 
        i++; 
       } 
       else 
       { 
        escaping = !escaping; 
       } 

      } 

      // Delimiter: Escaping -> Anhängen; Sonst Datensatz speichern 
      else if (c == delimiter) 
      { 
       if (escaping) 
       { 
        property += c; 
       } 
       else 
       { 
        l.Add(property.Trim()); 
        property = ""; 
       } 
      } 

      // Jeder andere Buchstabe: Anhängen 
      else 
      { 
       property += c; 
      } 
     } 

     l.Add(property);         // Letzten Datensatz speichern 

     // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
     // Konsistenzprüfung und Rückgabe der Datensätze 
     if (escaping) throw new FormatException();   // CSV wohlgeformt? 

     return l.ToArray<String>(); 
    } 
    public static String CreateCsvRecord(Char delimiter, Char escape, params String[] p) 
    { 
     String record = ""; 
     String tmp; 

     for (Int32 i = 0; i < p.Length; i++) 
     { 
      if (0 != i) record += delimiter; 

      tmp = p[i].Replace(new String(escape, 1), new String(escape, 2)); 
      if (tmp.Contains(delimiter)) tmp = escape + tmp + escape; 

      record += tmp; 
     } 

     return record; 
    } 
} 

调用ParseCsvRecord给你留下的记录的内容的String []

2

它看起来你有所有10个用户的相关信息在CSV文件中的一行,这样的事情?

user1,100, user2,96, user3,55, [...] 

也许你应该考虑改变这种格式,而是保存一个用户信息中的每一行,像

user1,100 
user2,96 
user3,55 
[...] 

这样,你可以肯定的是每一行都有,当你把它分解正好2项:

String[] userDetails = line.split(commaSeparator); 
userName = userDetails[0]; 
userScore = userDetails[1]; 

当你完成你的文件阅读器自动停止 - 不管你有多少用户信息线都有。这是因为在while循环的条件,即停止,如果没有更多的线环:

while ((line = br.readLine()) != null) { 

你可以保持一个计数的行号,就像你开始使用您的评论一个计数器将索引处的userName和userScore保存在数组中