Writing a file in Java - java

Good day!
I have a project (game) that needs to be presented tomorrow morning. But I discovered a bug when writing in the high scores. I am trying to create a text file and write the SCORE NAME in descending order using score as the basis.
FOR EXAMPLE:
SCORE NAME RANK
230 God
111 Galaxian
10 Gorilla
5 Monkey
5 Monkey
5 Monkey
NOTE THERE'S ALSO A RANK
My code is as follows:
public void addHighScore() throws IOException{
boolean inserted=false;
File fScores=new File("highscores.txt");
fScores.createNewFile();
BufferedReader brScores=new BufferedReader(new FileReader(fScores));
ArrayList vScores=new ArrayList();
String sScores=brScores.readLine();
while (sScores!=null){
if (Integer.parseInt(sScores.substring(0, 2).trim()) < score && inserted==false){
vScores.add(score+"\t"+player+"\t"+rank);
inserted=true;
}
vScores.add(sScores);
sScores=brScores.readLine();
}
if (inserted==false){
vScores.add(score+"\t"+player+"\t"+rank);
inserted=true;
}
brScores.close();
BufferedWriter bwScores=new BufferedWriter(new FileWriter(fScores));
for (int i=0; i<vScores.size(); i++){
bwScores.write((String)vScores.get(i), 0, ((String)vScores.get(i)).length());
bwScores.newLine();
}
bwScores.flush();
bwScores.close();
}
But if i input three numbers: 60 Manny, the file would be like this:
60 Manny
230 God
111 Galaxian
10 Gorilla
5 Monkey
5 Monkey
5 Monkey
The problem is it can only read 2 numbers because I use sScores.substring(0, 2).trim()).
I tried changing it to sScores.substring(0, 3).trim()). but becomes an error because it read upto the character part. Can anyone help me in revising my code so that I can read upto 4 numbers? Your help will be highly appreciated.

What you should use is:
String[] parts = sScrores.trim().split("\\s+", 2);
Then you will have an array with the number at index 0, and the name in index 1.
int theNumber = Integer.parseInt(parts[0].trim();
String theName = parts[1].trim();
You could re-write the while-loop like so:
String sScores=brScores.readLine().trim();
while (sScores!=null){
String[] parts = sScrores.trim().split(" +");
int theNumber = Integer.parseInt(parts[0].trim();
if (theNumber < score && inserted==false){
vScores.add(score+"\t"+player+"\t"+rank);
inserted=true;
}
vScores.add(sScores);
sScores=brScores.readLine();
}
Personally, I would add a new HighScore class to aid in parsing the file.
class HighScore {
public final int score;
public final String name;
private HighScore(int scoreP, int nameP) {
score = scoreP;
name = nameP;
}
public String toString() {
return score + " " + name;
}
public static HighScore fromLine(String line) {
String[] parts = line.split(" +");
return new HighScore(Integer.parseInt(parts[0].trim()), parts[1].trim());
}
}

The format of each line is always the same : an integer, followed by a tab, followed by the player name.
Just find the index of the the tab character in each line, and substring from 0 (inclusive) to this index (exclusive), before parsing the score.
The player name can be obtained by taking the substring from the tab index +1 (inclusive) up the the length of the line (exclusive).

if above mentioned table is a file.
for first two score it will be fine but for 5 it start reading character. Might be that is causing problem.

Related

reading a file with mixed data with java

Hello I was wondering if I could get some help. I've been tasked with reading from a file and storing the information into arrays. I have three arrays meant to pick up the data, which for example looks like this:
Smith Jr., Joe
111-22-3333 100 90 80 70 60 88
Jones, Bill
111-11-1111 90 90 87 88 100 66
Brown, Nancy
222-11-1111 100 100 100 100 100 100
My code for reading the data is this so far:
public static void readFile(String[] studentList, String[] idList, int[] scoreList) throws IOException {
String fileName;
System.out.println("Enter file name and location if necessary: ");
fileName = KB.nextLine();
File f1= new File(fileName); // "C:\Users\User\Desktop\final.txt"
Scanner fileIn = new Scanner(f1);
int i = 0 ;
if (f1.length() == 0) {
System.out.println("File is empty");
}
while(fileIn.hasNext() && i < studentList.length){
studentList[i] = fileIn.nextLine();
idList[i] = fileIn.nextLine();
scoreList[i] = fileIn.nextInt();
i++;
}
}
When I go to output the code though, I get this error:
Exception in thread "main" java.util.InputMismatchException
at java.util.Scanner.throwFor(Scanner.java:864)
at java.util.Scanner.next(Scanner.java:1485)
at java.util.Scanner.nextInt(Scanner.java:2117)
at java.util.Scanner.nextInt(Scanner.java:2076)
at managestudent.ManageStudent.readFile(ManageStudent.java:88)
at managestudent.ManageStudent.main(ManageStudent.java:36)
I've tried troubleshooting and what seems to be happening is that my second array stores the entire line and that my integers aren't getting read and stored into my third array.
I tried to set my second array as a long to pick up the numbers like 111-111-111 and differentiate from the integers but that gave me another error which seemed to be that my long array wasn't picking up anything from the second lines at all.
Any suggestions?
Thank you kindly for your time.
You need to make the following changes to your code
studentList[i] = fileIn.nextLine();
String id_score = fileIn.nextLine();
String[] split = id_score.split(" ",2);
idList[i] = split[0];
scoreList[i] = split[1];
.split() will separate the id and score in the second line.
Look at this code:
studentList[i] = fileIn.nextLine();
idList[i] = fileIn.nextLine();
scoreList[i] = fileIn.nextInt();
You are reading line by line.
But 111-22-3333 100 90 80 70 60 88 is a single line (which is read into idList[i]).
You need to change your code in a way, that you read 111-22-3333 100 90 80 70 60 88 as a line, and then split the line into two (or more, that's up to you) segments, that you process further to get ID and scores.
As an alternate to Moritz Petersens answer, for minimal changes to your code, you can use the next() method instead of nextLine() method to get the idList() by changing your while loop as follows;
studentList[i] = fileIn.nextLine();
idList[i] = fileIn.next();
scoreList[i] = fileIn.nextLine();
i++;
This will store the first token (Your ID) into the idList array and the remaining part of that line into the scoreList array. Which I assume you are expecting to happen here.
Refer: https://www.tutorialspoint.com/java/util/scanner_next.htm
Hope this helps!
UPDATE
I just observed that your scoreList array is of type int[].
Based on that, above fix will not work.
You will need to create a temporary string which takes all scores and then split it to put the appropriate integers into the score array.
Also, create a new integer for tracking index of the scoreList array.
Something like;
int scoreIndex = 0;
while(fileIn.hasNext() && i < studentList.length){
studentList[i] = fileIn.nextLine();
idList[i] = fileIn.next();
String scores = fileIn.nextLine();
String[] splitScores = scores.trim.split(" ");
for (String a : splitScores) {
scoreList[scoreIndex] = Integer.parseInt(a);
scoreIndex++;
}
i++;
}
Also, since you are using a primitive array dataType for scoreList array, make sure that the size of the array is number_of_subjects*number_of_students.
In your example, 6*3.

Calling methods within methods, Calling methods with multiple parameters to main. Mixing String and double

I'm struggling with an assignment. I need help figuring out how to call the right methods within each other and eventually in main. My whole code might need work at this point, what am I doing wrong? I've been stuck on this for a week.. (Guidelines at the bottom) Thanks!
import java.util.Scanner;
public class AverageWithMethods {
static Scanner in = new Scanner(System.in);
public static void main(String[]args)
{
userPrompt(); //Can't figure out how I'm supposed to set this up.
}
public static String userPrompt()
{
System.out.println("Enter 5 to 10 numbers separated by spaces, then press enter: ");
String num = in.nextLine();
return num; //I think I'm supposed to call the averager method here somehow?
}
public static double averager(String userPrompt)
{
double nums = Double.parseDouble(userPrompt);
double average = 0;
int counter = 0;
char c = ' ';
for (int i = 0; i < userPrompt.length(); i++)
{
if(userPrompt.charAt(i) == c)
{
counter++;
}
average = nums / counter;
}
return average;
}
public static void result(double average, String userPrompt)
{
System.out.println("The average of the numbers" + userPrompt + "is" + average);
}
}
GUIDELINES:
The program prompts the user for five to ten numbers, all on one line, and separated by spaces. Then the user calculates the average of those numbers, and displays the numbers and their average to the user.
The program uses methods to:
Get the numbers entered by the user Calculate the average of the numbers entered by the user Print the results with the whole number, a decimal, and two decimal positions The first method should take no arguments and return a String of numbers separated by spaces.
The second method should take a String as its only argument and return a double (the average).
The third method should take a String and a double as arguments but have no return value.
For example, if the user input is... 20 40 60 80 100
...the program should give as output... The average of the numbers 20 40 60 80 100 is 60.00.
I will not exactly provide complete solution to your questions but guide you in solving the problem:
User input : 1 2 3 4 5
Thus, now you need to read it in a String which you are already doing in your userPrompt() method.
Post that you need to call your averager() method to get the average
of the numbers. In that averager method you can need to split the
String to get the numbers. Check : String.split() method
documentation on how to achieve that. Then, you need to call
Double.parseDouble() for your String array of numbers.
Finally , you need to make a call to result method in you main()
method.
I hope it helps you on how to approach the problems and has sufficient hints to get the correct solution

How to use a Movie Review file to print out sentiment averages for words in another file?

I am working on a project that has many different parts and methods. For this one specific part I need to ask the user for the name of a file that contains a set of words, one per line. (see attached) Then I need to compute the average score/sentiment of the word by comparing it to a movieReview file that scores the sentiment of words. (see attached)
[Edit] : I have not gotten my code to take the first line of the wordList file, search through the movieReview file for the word, and find the average score of the word. And after the search is complete, move onto the next word. However, it is printing NaN for the rest of the words after the first, "mechanical"
Example: The first word in the wordList file is "mechanical". Mechanical is found in the movieReview file 6 times and the total score is 4. The average sentiment for the word "mechanical" is .666666666.
How can I make my code so the loop continues and finds the average for every single word and prints it out? Sorry if this sound confusing, let me know if I need to clarify. Also, I am a very beginner coder so please try to not use difficult concepts. (Also, it was said using an array or buffer wasn't needed)
Movie Review File :
http://nifty.stanford.edu/2016/manley-urness-movie-review-sentiment/movieReviews.txt
Content of Word List file(txt):
mechanical
car
soulless
style
family
wonderful
historical
nor
strong
slapstick
complicated
provoking
interest
cast
witty
muted
sentiment
narrative
refreshing
preachy
horrible
resolutely
terrible
dialogue
incoherent
spend
words
moving
devoid
indulgent
dull
value
barely
always
dog
tale
hardly
unfocused
formulaic
eccentric
quirky
unpredictable
tears
writing
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class methodThree {
public static void main (String [] args) throws FileNotFoundException {
Scanner in = new Scanner(System.in);
System.out.println("Enter the name of the file with words you want to score: ");
String inputFileName = in.next();
File inputFile = new File(inputFileName);
while(!inputFile.exists())
{
System.out.println("Please enter a valid file name:");
inputFile = new File(in.next());
}
Scanner wordFile = new Scanner (inputFile);
File inputMovie = new File("movieReviews.txt");
Scanner movieReview = new Scanner (inputMovie);
String reviewText;
int reviewScore;
while (wordFile.hasNextLine())
{
int count = 0;
double total = 0;
String word = wordFile.nextLine();
while (movieReview.hasNext()) {
reviewScore = movieReview.nextInt();
reviewText = movieReview.nextLine();
if (reviewText.contains(word)) {
count++;
total = total + reviewScore;
}
}
double average = (total / count);
System.out.println (word + " " + average);
}
}
}
So what you basically want to do is repeat this code for every line in the wordfile?
int count = 0;
double total = 0;
String word = wordFile.nextLine();
while(movieReview.hasNext()){
reviewScore = movieReview.nextInt();
reviewText = movieReview.nextLine();
if (reviewText.contains(word)) {
count++;
total = total + reviewScore;
}
}
double average = (total / count);
System.out.println(average);
if thats the case you could surround it with another while loop. The loop must run for every line in wordFile, so it's more or less the same loop as your movieReview.hasNext() loop.
while(wordFile.hasNext()){
int count = 0;
...
}
The loop runs as long as wordFile has another word to score.

JAVA My two-dimensional array scanned from a text file prints without the first column

I am working on a lab for school so any help would be appreciated, but I do not want this solved for me. I am working in NetBeans and my main goal is to create a "two-dimensional" array by scanning in integers from a text file. So far, my program runs with no errors, but I am missing the first column of my array. My input looks like:
6
3
0 0 45
1 1 9
2 2 569
3 2 17
2 3 -17
5 3 9999
-1
where 6 is the number of rows, 3 is the number of columns, and -1 is the sentinel. My output looks like:
0 45
1 9
2 569
2 17
3 -17
3 9999
End of file detected.
BUILD SUCCESSFUL (total time: 0 seconds)
As you can see, everything prints correctly except for the missing first column.
Here is my program:
import java.io.*;
import java.util.Scanner;
public class Lab3
{
public static void main(String[] arg) throws IOException
{
File inputFile = new File("C:\\Users\\weebaby\\Documents\\NetBeansProjects\\Lab3\\src\\input.txt");
Scanner scan = new Scanner (inputFile);
final int SENT = -1;
int R=0, C=0;
int [][] rcArray;
//Reads in two values R and C, providing dimensions for the rows and columns.
R = scan.nextInt();
C = scan.nextInt();
//Creates two-dimensional array of size R and C.
rcArray = new int [R][C];
while (scan.nextInt() != SENT)
{
String line = scan.nextLine();
String[] numbers = line.split(" ");
int newArray[] = new int[numbers.length];
for (int i = 1; i < numbers.length; i++)
{
newArray[i] = Integer.parseInt(numbers[i]);
System.out.print(newArray[i]+" ");
}
System.out.println();
}
System.out.println("End of file detected.");
}
}
Clearly, there is a logical error here. Could someone please explain why the first column is invisible? Is there a way I can only use my rcArray or do I have to keep both my rcArray and newArray? Also, how I can get my file path to just read "input.txt" so that my file path isn't so long? The file "input.txt" is located in my Lab3 src folder (same folder as my program), so I thought I could just use File inputFile = new File("input.txt"); to locate the file, but I can't.
//Edit
Okay I have changed this part of my code:
for (int i = 0; i < numbers[0].length(); i++)
{
newArray[i] = Integer.parseInt(numbers[i]);
if (newArray[i]==SENT)
break;
System.out.print(newArray[i]+" ");
}
System.out.println();
Running the program (starting at 0 instead of 1) now gives the output:
0
1
2
3
2
5
which happens to be the first column. :) I'm getting somewhere!
//Edit 2
In case anyone cares, I figured everything out. :) Thanks for all of your help and feedback.
Since you do not want this solved for you, I will leave you with a hint:
Arrays in Java are 0 based, not 1 based.
As well as Jeffrey's point around the 0-based nature of arrays, look at this:
while (scan.nextInt() != SENT)
{
String line = scan.nextLine();
...
You're consuming an integer (using nextInt()) but all you're doing with that value is checking that it's not SENT. You probably want something like:
int firstNumber;
while ((firstNumber = scan.nextInt()) != SENT)
{
String line = scan.nextLine();
...
// Use line *and* firstNumber here
Or alternatively (and more cleanly IMO):
while (scan.hasNextLine())
{
String line = scan.nextLine();
// Now split the line... and use a break statement if the parsed first
// value is SENT.

Reading statistics from a file

One of the homework assignments my instructor gave me was a baseball statistics program. It reads from a file called stats.dat, which contains the name of a baseball player's name and a list of what happened when they were at the bat. It reads and prints their name and the amount of outs(o), hits(h), walks(w), and sacrifice flies(s) that they have. This is what the file contains:
Willy Wonk,o,o,h,o,o,o,o,h,w,o,o,o,o,s,h,o,h
Shari Jones,h,o,o,s,s,h,o,o,o,h,o,o,o
Barry Bands,h,h,w,o,o,o,w,h,o,o,h,h,o,o,w,w,w,h,o,o
Sally Slugger,o,h,h,o,o,h,h,w
Missy Lots,o,o,s,o,o,w,o,o,o
Joe Jones,o,h,o,o,o,o,h,h,o,o,o,o,w,o,o,o,h,o,h,h
Larry Loop,w,s,o,o,o,h,o,o,h,s,o,o,o,h,h
Sarah Swift,o,o,o,o,h,h,w,o,o,o
Bill Bird,h,o,h,o,h,w,o,o,o,h,s,s,h,o,o,o,o,o,o
Don Daring,o,o,h,h,o,o,h,o,h,o,o,o,o,o,o,h
Jill Jet,o,s,s,h,o,o,h,h,o,o,o,h,o,h,w,o,o,h,h,o
So far I have the basic idea down, even though I don't quite understand what each line is doing(I modified some code of a program in the book my class is reading that prints a URL that's in a text file and then prints out each part of the url that's separated by a /). I have it so that the program prints out the player's name, but I'm stumped on how to print out the amount of hits, outs, walks, and sacrifice flies they get. So far it's reading 1 character out of the line, then it goes down to the next player and prints out 2, then 3, etc. Here's the code I have for it so far:
import java.util.Scanner;
import java.io.*;
public class BaseballStats
{
public static void main(String [] args) throws IOException
{
int hit = 0, walk = 0, sac = 0, out = 0, length = 0, wholeLength = 0;
Scanner fileScan, lineScan, statScan;
String fileName, playerName, line, stats, playerStats;
Scanner scan = new Scanner(System.in);
System.out.println("Enter the name of the file: ");
fileName = scan.nextLine();
fileScan = new Scanner(new File(fileName));
while (fileScan.hasNext())
{
System.out.println();
line = ("Player: " + fileScan.nextLine());
wholeLength = line.length();
lineScan = new Scanner(line);
lineScan.useDelimiter(",");
stats = lineScan.next();
statScan = new Scanner(stats);
statScan.useDelimiter(",");
while (statScan.hasNext())
{
System.out.println(statScan.next());
length = stats.length() - 1;
for (int i = 0; i < length; i++)
{
if (stats.charAt(i) == 'h')
hit++;
else if (stats.charAt(i) == 'o')
out++;
else if (stats.charAt(i) == 'w')
walk++;
else if (stats.charAt(i) == 's')
sac++;
}
}
System.out.println("Hits: " + hit + "\nOuts: " + out + "\nWalks: " + walk + "\nSacrifice flies: " + sac);
}
}
}
(I'm having a hard time getting the last part of the last statement in my code to appear correctly in the editor, sorry if it looks a bit weird) I have been wondering what's wrong and I can't figure it out so far. Is there anything to get me on the right track?
If looks like you're creating one Scanner instance too many:
You use the first Scanner: fileScan to read one line at a time and assign this to line.
You then create a Scanner: lineScan to read over the line one field at a time.
However, you only read the first token from lineScan and then create a third Scanner instance: statsScan. Rather than do this, you simply need to read all the tokens from lineScan, storing the first as the person's name and processing the subsequent tokens as statistics.
One other thing I'd advise is to create a dedicated class to hold the person's name and statistics and implement toString() on this class to produce a sensible String representation; e.g.
public class Player {
private final String name;
private int hit, out, walk, sac;
public int getNumHits() {
return hit;
}
public int incrementNumHits() {
return ++hit;
}
// TODO: Implement other getter and increment methods.
public String toString() {
return String.format("%s. Hits: %d, Outs: %d, Walks: %d, Sacrifice flies: %d",
name, hit, out, walk, sac);
}
}
By implementing toString() you simply need to create and populate your Player class with statistics and then print it out; e.g.
Player player = new Player("Jim");
player.incrementNumHits();
// etc.
System.out.println(player);

Categories