Reputation: 99
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
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
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
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