user1836292
user1836292

Reputation: 99

how to stop array out of bounds error if csv file empty?

I am trying to read a csv file that contains the names and scores in one line. My code works fine if the csv has exactly 20values(10names and 10 scores). Im having a difficulty making it work if the csv file is empty or has less than 20 values. My code reads the csv in an array and then stores the names and scores in two different arrays. Then it compares if a new player has a score greater than ones already stored in the csv file, if it is then it replaces it and then stores all updated names and scores in one array. The csv file can have a maximum of 10 names and 10 scores and the minimum can be empty 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] + ",  ");

     }
  }
}

Upvotes: 1

Views: 844

Answers (3)

sleidig
sleidig

Reputation: 1390

It looks like you have all 10 user infos in one line of your CSV file, something like this?

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

Maybe you should consider changing that format and instead save one user info in each line, like

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

That way you can be sure that each line has exactly 2 items when you split it:

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

And your file reader automatically stops when you are done - no matter how many user info lines you have. This is because of your condition in the while loop, that stops the loop if there is no more line:

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

You can keep a count for the line number, like you started with your commented a counter and save userName and userScore in the array at index a.

Upvotes: 2

Benj
Benj

Reputation: 989

I wrote a CSV-Parser in C# a while ago. Even though it is not Java, the logic should be the same. Hope this helps

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;
    }
}

calling ParseCsvRecord leaves you with a String[] of the record's contents

Upvotes: 0

jp-jee
jp-jee

Reputation: 1523

You should check the length of your array instead of using a hardcoded value.

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

And since you are accessing the index j+1, you should subtract 1:

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

Upvotes: 1

Related Questions