Highscore binary file - java

Hi!
I would like to maintain a high score system with a maximum of 5 binary scores for my school project game. If the new value is higher than what is already in the file, I want to replace it with the new value.
I've been at it for a long time, but I'm not really getting it out. It always adds new lines and my check that the value is already in the file does not work. I hope you can help me a step further.
thanks in advance
Here's my code:
private static final String HIGHSCORE_PATH = "highscore-" + LocalDate.now() + ".dat";
private static final Path filePath = Paths.get(HIGHSCORE_PATH);
private final ArrayList highscoreList = new ArrayList();
private final ArrayList highscoreFileWaardes = new ArrayList();
FileOutputStream fos = new FileOutputStream(HIGHSCORE_PATH, true);
int numberRulesInUse = 0;
int teller2 = 0;
int teller3 = 0;
public void writeHighscore(int highscore) throws IOException {
if (Files.exists(filePath)) {
try (Scanner fileScanner = new Scanner(filePath)) {
if (numberRulesInUse > 6) {
System.out.println("File is too long");
return;
} else if (numberRulesInUse == 0) {
for (int i = 0; i < 5; i++) {
highscoreList.add(0);
}
} else {
String highscoreBinair = fileScanner.nextLine();
highscoreList.set(teller2, (Integer.parseInt(highscoreBinair, 2)));
while (fileScanner.hasNext()) {
if (aantalRegelsInGebruik < 5) {
if (!highscoreList.get(teller3).equals(highscoreFileWaardes.get(teller3))) {
highscoreList.set(teller3, (Integer.parseInt(highscoreBinair, 2)));
teller3++;
numberRulesInUse++;
} else {
System.out.println("Already in file");
return;
}
} else {
System.out.println("FILE DOESN'T ALLOW MORE THAN 5 RULES");
return;
}
}
}
} catch (IOException ioException) {
throw new IOException("Error while reading file");
}
if ((Integer) highscoreList.get(teller3) < highscore && (Integer) highscoreList.get(teller3) != highscore) {
try {
highscoreList.set(teller3, Integer.parseInt(String.valueOf(highscore)));
fos.write(Integer.toBinaryString(Integer.parseInt(String.valueOf(highscoreList.get(teller3)))).getBytes());
fos.write("\n".getBytes());
teller3++;
numberRulesInUse++;
} catch (IOException e) {
throw new IOException("Error while writing to file");
}
} else {
System.out.println("No new highscore or highscore already exists");
}
}
fos.flush();
//fos.close();
}

Let's take a step back and think about what you are trying to do, and if there is an easier way to do it all.
Load the scores from the file to a list,
Add the new high score to the list if it is higher,
Save the top 5 new high scores,
Profit!
We start by reading each line of the file to an array and parsing it to an Integer existingHighScores.add(Integer.parseInt(line, 2));
The next step is to check if your score is higher or not, however, there is an far easier way to do this by simply adding the score to the end of the list existingHighScores.add(highscore);, and then we can sort the list in descending order Collections.sort(existingHighScores, Collections.reverseOrder()); that single line of code will cut out all your loops and if/else checks and give you some great readable code.
Finally, because we have a nicely sorted list we can just save the first 5 items in the list which are the 5 top scores to file, and as mentioned earlier, because the code is sorted it will remove the need to compare and remove lower scores:
for (int i = 0; i < 5; i++)
{
out.write(Integer.toBinaryString(existingHighScores.get(i)).getBytes());
out.write("\n".getBytes());
}
Now if we put it all together a fully working example might look something like this:
public void writeHighscore(int highscore) throws Exception {
//File path
Path file = Paths.get(HIGHSCORE_PATH);
//Fill arraylist with 5 0's to avoid issues if the list loaded from file is corrupt, or shorter than 5
ArrayList<Integer> existingHighScores = new ArrayList<>(Arrays.asList(0,0,0,0,0));
//Load the exising high scores
InputStream in = Files.newInputStream(file);
BufferedReader reader = new BufferedReader(new InputStreamReader(in)));
String line = null;
while ((line = reader.readLine()) != null)
{
//load score, of if there is an error default to 0
try{
existingHighScores.add(Integer.parseInt(line, 2));
}
catch (Exception e){
existingHighScores.add(0);
}
}
//Remember to close the file, otherwise we cant save the new scores below
reader.close();
in.close();
//Add the new high score to list
existingHighScores.add(highscore);
//Sort the scores
Collections.sort(existingHighScores, Collections.reverseOrder());
//Save the highscores to file
OutputStream out = new BufferedOutputStream(Files.newOutputStream(file)));
//Only write the first 5 scores
for (int i = 0; i < 5; i++)
{
out.write(Integer.toBinaryString(existingHighScores.get(i)).getBytes());
out.write("\n".getBytes());
}
}
Now you can add your exception handling and error checking if(Files.exists(file)) etc, and you can play with the code to get the file format working exactly as you want, but the logic itself remains simple and unchanged.

Related

Is there a faster way to use csv reader in Java?

I need to open a csv file in more parts, each one by 5,000 samples and then plot them. To go back and forward on the signal each time I click a button I have to instantiate a new reader and than I skip to the point I need. My signal is big, is about 135,000 samples so csvReader.skip() method is very slow when I work with last samples. But to go back I can't delete lines, so each time my iterator needs to be re-instantiated. I noticed that skip uses a for loop? Is there a better way to overtake this problem? Here is my code:
public void updateSign(int segmento) {
Log.d("segmento", Integer.toString(segmento));
//check if I am in the signal length
if (segmento>0 && (float)(segmento-1)<=(float)TOTAL/normaLen)
{
try {
reader = new CSVReader(new FileReader(new File(patty)));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
List<Integer> sign = new ArrayList<>();
//this is the point of the signal where i finish
int len = segmento * normaLen;
//check if i am at the end of the signal
if (len >= TOTAL) {
len = TOTAL;
segmento=0;
avanti.setValue(false);
System.out.println(avanti.getValue());
} else {
lines = TOTAL - len;
avanti.setValue(true);
System.out.println(avanti.getValue());
}
//the int to i need to skip
int skipper = (segmento-1)*normaLen;
try {
System.out.println("pre skip");
reader.skip(skipper);
System.out.println("post skip");
} catch (IOException e) {
e.printStackTrace();
}
//my iterator
it = reader.iterator();
System.out.println("iteratore fatto");
//loop to build my mini-signal to plot
//having only 5,000 sample it is fast enaugh
for (int i = skipper; i < len-1; i++) {
if (i>=(segmento-1)*normaLen) {
sign.add(Integer.parseInt(it.next()[0]));
}
else
{
it.next();
System.out.println("non ha funzionato lo skip");
}
}
System.out.println("ciclo for: too much fatica?");
//set sign to be plotted by my fragment
liveSign.setValue(sign);
}
}
Thanks in advance!

Need help reading file line by line

The current code that I have reads only the last line of the file. Can someone help me establish a way so that the code reads a file line by line?
import java.util.*;
import java.io.*;
public class Searcher extends File {
Scanner scn;
public Searcher(String filename) {
super(filename);
}
public void search(String input)
{
try {
scn = new Scanner(this);
String data = "";
while (scn.hasNext()) {
data = scn.nextLine();
}
int count = 0, fromIndex = 0;
while ((fromIndex = data.indexOf(input, fromIndex)) != -1) {
count++;
fromIndex++;
}
System.out.println("Total occurrences: " + count);
scn.close();
} catch (Exception e) {
System.out.println("Cant find file ");
}
}
public static void main(String[] args) {
Searcher search = new Searcher("src/ihaveadream.txt");
search.search("we");
}
}
appreciate any help !
while (scn.hasNext()) {
data = scn.nextLine();
}
You are replacing the value every time so you end up with the last value as that's what it gets set to in the end. Perhaps you wanted to append?
while (scn.hasNext()) {
data = data + scn.nextLine();
}
Good luck.
Your problem:
while (scn.hasNext()) {
data = scn.nextLine(); // right here
}
each next line replaces previous line.
Depending on what you need you can either:
make all lines as one String
data = data + scn.nextLine();
// another syntax to do the same:
data += scn.nextLine();
or use List to keep each line as separate element:
List<String> dataList = new ArrayList<>();
while (scn.hasNext()) {
dataList.add(scn.nextLine());
}
As everyone has already suggested, you are replacing the the data in your data variable in the while loop, and since the loop runs till the end of the file is reached, only the last line is stored in the data variable, and any further processing on data would get you results only from the last line, so what you can do is what everybody else here suggested, or you can try this as an alternative solution (close the while loop after you check for index values):
public void search(String input)
{
int count = 0, fromIndex = 0; //moved outside so that we don't reset it to 0 with every iteration of the loop
try {
scn = new Scanner(this);
String data = "";
while (scn.hasNext()) {
data = scn.nextLine();
//} instead of here
//int count = 0, fromIndex = 0; move these variables outside of the loop
while ((fromIndex = data.indexOf(input, fromIndex)) != -1) {
count++;
fromIndex++;
}
} //close it here
System.out.println("Total occurrences: " + count);
scn.close();
} catch (Exception e) {
System.out.println("Cant find file ");
}
}

Reading a text file into a 2D array

I need to read a text file into a 2D array, I can read files into the program perfectly fine (see my code below) however I cannot get my head around how to read them into a 2D array. The array the function is reading into is a global array hence why it's not in the function.
Also I won't know the amount of rows the array has at first (currently set at 300 as it won't be over this) and I know this could cause a problem, I've seen some people suggest using ArrayLists however I have to have a 2D array so I was also wondering if there was a way to change an ArrayList to a 2D array and if this would be more effective?
public static String readMaze(String fileName) {
String line = null;
try {
FileReader fileReader = new FileReader(fileName);
BufferedReader bufferedReader = new BufferedReader(fileReader);
while ((line = bufferedReader.readLine()) != null) {
System.out.println(line);
for (int i = 0; i < mazeNew.length; i++) {
for (int j = 0; j < mazeNew[i].length; j++) {
// mazeNew[i][j] = ; - this is where I think something needs to be added
}
}
}
bufferedReader.close();
}
catch (FileNotFoundException ex) {
System.out.println("Unable to open file: " + fileName);
}
catch (IOException ex) {
System.out.println("Error reading file: " + fileName);
}
return fileName;
}
example text file:
11 4
5 6
4 6
0 5
3 5
8 7
1 4
There's a few options here, but generally you'll want to use the Java Scanner class as it's designed for exactly this kind of thing. Alternatively, use an existing structured data format (like JSON or XML) and an existing parser to go with it - the advantage being you can make use of a vast amount of tools and libraries which deal with those formats and don't have to re-invent anything.
However, following through with the scanner approach, it would be like so:
public static ArrayList<int[]> readMaze(String fileName) {
// Number of ints per line:
int width=2;
// This will be the output - a list of rows, each with 'width' entries:
ArrayList<int[]> results=new ArrayList<int[]>();
String line = null;
try {
FileReader fileReader = new FileReader(fileName);
BufferedReader bufferedReader = new BufferedReader(fileReader);
Scanner mazeRunner = new Scanner(bufferedReader);
// While we've got another line..
while (mazeRunner.hasNextLine()) {
// Setup current row:
int[] row = new int[width];
// For each number..
for (int i = 0; i < width; i++) {
// Read the number and add it to the current row:
row[i] = mazeRunner.nextInt();
}
// Add the row to the results:
results.add(row);
// Go to the next line (optional, but helps deal with erroneous input files):
if ( mazeRunner.hasNextLine() ) {
// Go to the next line:
mazeRunner.nextLine();
}
}
mazeRunner.close();
}
catch (FileNotFoundException ex) {
System.out.println("Unable to open file: " + fileName);
}
catch (IOException ex) {
System.out.println("Error reading file: " + fileName);
}
return results;
}
If you have fixed no. of columns you can use this, but make sure input file must follow the same no of coulmns.
FileReader fileReader = new FileReader(fileName);
Scanner sc = new Scanner(fileReader);
int row=0, col=0;
while ((sc.hasNext()) != null) {
if(col < colSize){ //colSize is size of column
mazeNew[row][col]= sc.nextInt();
}
else{
col=0;
row++;
}
}
Below is the core logic, you would probably also like to to handle some errors, such as how many elements is a line split into, are there empty lines, etc.
List<String[]> list = new ArrayList<>();
Pattern pattern = Pattern.compile("\\s+");
while ((line = bufferedReader.readLine()) != null) {
list.add(pattern.split(line, -1));
}
String[][] mazeNew = list.toArray(new String[0][0]);
Something like this would work
it wont only read 2d text files .. it should work fine with any dimensions
public class Utile{
public static ArrayList<int[]> readMaze(String path){
ArrayList<int[]> result = new ArrayList<>();
try{
Scanner sc = new Scanner(new File(path));
String[] temp;
String line;
while(sc.hasNextLine()){
line = sc.nextLine();
if (line.length() != 0){ //if the line is empty it will cause NumberFormatException
temp = line.split(" ");
int[] val = new int[temp.length];
for(int i = 0;i < temp.length;i++){
val[i] = Integer.pareseInt(temp[i]);
}
result.add(val);
}
}
sc.close();
}catch(Exception e){
e.printStackTrace(); //just log it for now
}
return result;
}
}
I am not a java expert, but in PHP I would do it with explode(). But I found an example how to do the same in java using string.split(). The result is the same ... an 2D Array of the content. If possible you should try to add an delimiter to the rows inside that text document. But you could split the rows on the space character either.
Example:
String foo = "This,that,other";
String[] split = foo.split(",");
StringBuilder sb = new StringBuilder();
for (int i = 0; i < split.length; i++) {
sb.append(split[i]);
if (i != split.length - 1) {
sb.append(" ");
}
}
String joined = sb.toString();

Trying to save a clone of an array in a txt file but returns NULL

I am making an app that keeps username and scores from a game in a txt file. The concept is that when it writes a new username and score to the txt file it should open the .txt file, read it and then make a clone of it adding a new uername and score entry in the txt file.
I am thinking of making this with 2 object arrays. The first is the one that is read in and the new will be the one is writen which will have one more entry.
So if player[i] is readen player[i+1] should be writen with new entry.
I am giving u the code below!
private Player[] myplayer=null;
private Player[] mynewplayer=null;
//open Players.txt
int i;
int n;
String filename="players.txt";
try
{
FileReader fp=new FileReader(filename);
BufferedReader bf=new BufferedReader(fp);
n=Integer.parseInt(bf.readLine());
myplayer=new Player[n];
int x=n+1;
mynewplayer=new Player[x];
for(i=0;i<n;i++)
{
String s=bf.readLine();
String user="",score="";
user=s.substring(0,s.indexOf(","));
s=s.substring(s.indexOf(",")+1);
score=s;
myplayer[i]=new Player(user,Double.parseDouble(score));
for(i=0;i<n;i++)
{
mynewplayer[i]= myplayer[i];
}
mynewplayer[x]=new Player(Username,Double.parseDouble(score));
}
bf.close();
fp.close();
}catch(IOException e)
{
System.out.println("Exception was "+e.getMessage());
}
//----------------------------------WRITE mytxt!-------------
n=myplayer.length;
try
{
filename="players.txt";
FileWriter fp=new FileWriter(filename);
fp.write(""+n+"\n");
for(i=0;i<n+1;i++)
fp.write(""+mynewplayer[i]+"\n");
fp.close();
}catch(IOException e)
{
System.out.println("Exception was "+e.getMessage());
}
//----------------------------------WRITE mytxt!-----------
//Get on Message
String s="";
for(i=0;i<mynewplayer.length;i++)
s=s+mynewplayer[i]+"\n";
JOptionPane.showMessageDialog(null,"Players are \n "+s);
Problem is that when it's written, it returns null for mynewplayer.
I suppose the mynewplayer doesnt really take the entries of the "myplayer" but neither writes the new username.
Compile doesnt show any errors. Just writes NULL to the textfile.
Ask me if u want further info on the code writen!
Thanks in advance!
Here is an edited version of your code, with some improvements and there should be a comment around code that I changed, explaining what I did.
Player[] myPlayer = null; // first word uncapitalized, every
Player[] myNewPlayer = null; // other word begins with a capital
//open Players.txt
int i, n; // combine the variables into 1 line
String filename = "players.txt";
try {
FileReader fp = new FileReader(filename);
BufferedReader bf = new BufferedReader(fp);
n = Integer.parseInt(bf.readLine());
// not needed
//myPlayer = new Player[n];
// NOT NEEDED int x = n + 1;
myNewPlayer = new Player[n + 1];
for (i = 0; i < n; i++) {
String s = bf.readLine();
String user, score; // combine variables, doesnt need to initalize them
String[] items = s.split(","); // Splits the line into array elements on every delimiter -> ,
//user = s.substring(0, s.indexOf(","));
//s = s.substring(s.indexOf(",") + 1);
//score = s;
user = items[0];
score = items[1];
// this line below isnt actually needed
//myPlayer[i] = new Player(user, Double.parseDouble(score));
// Create a new player clone, dont copy the previous one
myNewPlayer[i] = new Player(user, Double.parseDouble(score));
}
// We've read all the variables from the text file, now we create the last one
// Since myNewPlayer is (n+1) size, the range of the array is
// 0 to n
// the last index will be n New Score Variable
myNewPlayer[n] = new Player("Username variable", Double.parseDouble("22"));
bf.close();
fp.close();
} catch (IOException e) {
System.out.println("Exception was " + e.getMessage());
}
//----------------------------------WRITE mytxt!-------------
// This is called a ternary operator
// it is a 1 line if statement
// the format is like so
// booleanLogic ? trueAnswer Execution : falseAnswer Execution;
// if () { true }else { false }
n = myNewPlayer != null ? myNewPlayer.length : 0;
// CHANGED HERE - was using the first array rather than second
// dont need the 1st array
try {
filename = "players.txt";
FileWriter fp = new FileWriter(filename);
// Dont need "" before the items
fp.write(n + "\n");
for (i = 0; i < n; i++) {
fp.write(myNewPlayer[i] + "\n");
}
fp.close();
} catch (IOException e) {
System.out.println("Exception was " + e.getMessage());
}
//----------------------------------WRITE mytxt!-----------
//Get on Message
String s = "";
for (i = 0; i < myNewPlayer.length; i++) {
// s += ""; is like doing s = s + "";
s += myNewPlayer[i] + "\n";
}
JOptionPane.showMessageDialog(null, "Players are \n " + s);
I believe that your problem is this:
for(i=0;i<n;i++)
{
String s=bf.readLine();
String user="",score="";
user=s.substring(0,s.indexOf(","));
s=s.substring(s.indexOf(",")+1);
score=s;
myplayer[i]=new Player(user,Double.parseDouble(score));
for(i=0;i<n;i++)
{
mynewplayer[i]= myplayer[i];
}
mynewplayer[x]=new Player(Username,Double.parseDouble(score));
}
You have nested loops, which is fine, but they use the same counter (the variable i ).
So what is happening is the first line of the file is read, and then added to myplayer[0]. However, instead of just also adding it to mynewplayer[0], you start another loop on i. This loop:
for(i=0;i<n;i++)
{
mynewplayer[i]= myplayer[i];
}
is going to copy the first player into mynewplayer[0]...and then null into every other entry (since myplayer only has the firsdt element filled.
The problem is that after that loop completes, i will equal n, so when you get back to the top of the outer loop, the check $i
Perhaps what you should do is this:
for(i=0;i<n;i++)
{
String s=bf.readLine();
String user="",score="";
user=s.substring(0,s.indexOf(","));
s=s.substring(s.indexOf(",")+1);
score=s;
myplayer[i]=new Player(user,Double.parseDouble(score));
mynewplayer[i]= new Player(user,Double.parseDouble(score));
}
mynewplayer[x]=new Player(<the new username>,Double.parseDouble(<the new score>));

Java Reading .csv file and getting java.lang.ArrayIndexOutOfBoundsException: 3 and don't know why

I'm banging my head against a wall about a program I'm trying to complete. I'm sure the answer is simple but I just can't figure out the solution.
When I write to the csv file it works but when reading from it, if there is more than 3 objects in the csv file, I get the ArrayIndex error but three or less and it throws no error.
Below is my code for writing to the file:
void saveDataToFile() {
String op = "";
try {
FileWriter fw = new FileWriter(filename);
for (int i =0 ; i< library.length ; i++)
if(library[i]!=null)
fw.write(library[i].getDetailsCSV().toString()+"\n");
fw.write(op.toString());
fw.close();
}
catch(Exception e) {
System.out.println("ERROR : "+e);
}
System.out.println("saveDataToFile()");
}
Below is the code for reading the file:
void loadDataFromFile() {
try{
File fi = new File(filename);
FileReader fr = new FileReader(fi);
char[] buffer = new char[(int)fi.length()];
fr.read(buffer);
fr.close();
String all = new String(buffer);
String[] ip = all.split("\n");
for (int i=0; i<ip.length; i++){
String[] op = ip[i].split(",");
String author = op[0];
String title = op[1];
int isbn = Integer.parseInt(op[2]);
String s = op[3];
boolean h = Boolean.parseBoolean(op[3]);
for(int j=0; j<op.length; j++){
if(author.equals("Dickens"))
library[i] = new title(author,isbn);
else if(author.equals("Lumas"))
library[i] = new title(author,isbn,s);
else if(author.equals("Orwell"))
library[i] = new title(author,isbn,h);
}
}
}
catch(Exception e) {
System.out.println("ERROR : "+e);
}
System.out.println("loadDataFromFile()");
}
The library[] array is size 10. I've tried a System.out.println(op.length); and System.out.println(ip.length); from the read method and ip.length is 10 and op.length is 3 (regardless of how many objects have actually been saved to the csv file i.e. even if it's full).
I'd really appreciate if anyone can see what I am obviously missing!
I'm guessing this loop is breaking it:
for(int j=0; j<op.length; j++){
if(make.equals("Ford"))
cars[i] = new Ford(model,year);
else if(make.equals("Mazda"))
cars[i] = new Mazda(model,year,colour);
else if(make.equals("Toyota"))
cars[i] = new Toyota(model,year,h);
}
If you have more than 3 lines this loop will fail since you are using i instead of j. Not sure what this loop is trying to do but that part will fail for sure.
Also, if op.length is 3, index 3 won't be there since Java arrays are indexed from 0 not 1.

Categories

Resources