Simple issue about possible to re use java Scanner? - java

I am still new to java and is it possible to re use the Scanner object?
The below example is I am reading a file to do characters, words and lines count. I know there must be a better way to do counting with one scanner object only but that is not the main point. I just wonder why there is input.close() but no input.open() or input.reset etc.. Since I am actually reading the same file, is it possible to create only one Scanner object and pass for 3 methods to use? Thanks
public class Test {
/**
* #throws java.io.FileNotFoundException
*/
public static void main(String[] args) throws FileNotFoundException {
File file = new File("demo.java");
Scanner input = new Scanner(file);
Scanner input2 = new Scanner(file);
Scanner input3 = new Scanner(file);
int lines = 0;
int words = 0;
int characters = 0;
checkCharacters(input3);
checkLines(input);
checkwords(input2);
}
private static void checkLines(Scanner input) {
int count = 0;
while (input.hasNext()) {
String temp = input.nextLine();
String result = temp;
count++;
}
System.out.printf("%d lines \n", count);
}
private static void checkwords(Scanner input2) {
int count = 0;
while (input2.hasNext()) {
String temp = input2.next();
String result = temp;
count++;
}
System.out.printf("%d words \n", count);
}
private static void checkCharacters(Scanner input3) {
int count = 0;
while (input3.hasNext()) {
String temp = input3.nextLine();
String result = temp;
count += temp.length();
}
System.out.printf("%d characters \n", count);
}
}

No, there's no way to reset the Scanner from a method on the Scanner. You might be able to do it if you passed in an InputStream into the scanner and then reset the stream directly but I don't think it's worth it.
You seem to be parsing the same file 3 times and processing the same input 3 times. That seems like a waste of processing. Couldn't you perform all 3 counts at once?
private static int[] getCounts(Scanner input) {
int[] counts = new int[3];
while(input.hasNextLine()){
String line = input.nextLine();
counts[0]++; // lines
counts[2]+=line.length(); //chars
//count words
//for simplicity make a new scanner could probably be better
//using regex or StringTokenizer
try(Scanner wordScanner = new Scanner(line)){
while (wordScanner.hasNext()) {
wordScanner.next();
count[1] ++; //words
}
}
}
return counts;
}
Of course the Object Oriented way would be to return a new object named something like Counts with methods to getNumLines(), getNumChars() etc.
EDIT
One thing to note, I kept the calculations the same as you had in the original question. I'm not sure if the counts will always be accurate especially characters since Scanner may not return all end of line characters so the chars count may be off and the number of lines may be off if there are consecutive blank lines? You would need to test this.

No it is not possible because as the documentation says
void close()
throws IOException
Closes this stream and releases any system resources associated with
it. If the stream is already closed then invoking this method has no
effect.
Once a resource is relaesed there is no way to get it back, untill you have a reference to it , which is actually closed

Related

how do i detect a double line break in a data file

I have a data file that consists of a calorie count.
the calorie count it separated by each elf that owns it and how many calories are in each fruit.
so this represents 3 elves
4323
4004
4070
1780
5899
1912
2796
5743
3008
1703
4870
5048
2485
1204
30180
33734
19662
all the numbers next to each other are the same elf. the separated ones are seperate.
i tried to detect the double line break like so
import java.util.*;
import java.io.*;
public class Main
{
public static void main(String [] args) throws FileNotFoundException
{
int[] elf = new int[100000];
int cnt = 0;
Scanner input = new Scanner(new File("Elf.dat"));
while(input.hasNext())
{
elf[cnt] += input.nextInt();
if (input.next().equals("\n\n"));
{
cnt++;
}
}
int big = elf[0];
for (int lcv = 0; lcv < elf.length; lcv++)
{
if (big < elf[lcv])
{
big = elf[lcv];
}
}
System.out.println(big);
}
}
I'm trying this to detect the double line break
if (input.next().equals("\n\n"));
but its giving me errors. how would i detect it
Here is another alternative way to do this sort of thing. read comments in code:
public static void main(String[] args) throws FileNotFoundException {
List<Integer> elfSums; // Can grow dynamically whereas an Array can not.
int sum;
// 'Try With Resources' used here to auto close the reader and free resources.
try (Scanner input = new Scanner(new File("Elf.dat"))) {
elfSums = new ArrayList<>();
String line;
sum = 0;
while (input.hasNextLine()) {
line = input.nextLine();
if (line.trim().isEmpty()) {
elfSums.add(sum);
sum = 0; // Reset sum to 0 (new elf comming up)
}
// Does the line contain a string representation of a integer numerical value?
if (line.matches("\\d+")) {
// Yes...add to current sum value.
sum += Integer.parseInt(line);
}
}
}
if (sum > 0) {
elfSums.add(sum);
}
// Convert List to int[] Array (There are shorter ways to do this)
int[] elf = new int[elfSums.size()];
for (int i = 0; i < elfSums.size(); i++) {
elf[i] = elfSums.get(i);
// For the heck of it, display the total sum for this current Elf
System.out.println("Elf #" + (i+1) + " Sum: -> " + elf[i]);
}
/* The elf[] int array now holds the data you need WITHOUT
all those empty elements with the array. */
}
Welcome to Advent of Code 22.
As a good rule, never mix nextXXX methods with any other next.
To break up the Blocks you have 2 good options:
Read line by line and fill a new list when you encounter a empty/blank line
Read the whole text fully, then split by the \n\n Combination

How to scan a file for a specific letter in Java

I need to take a file that a user chooses and scan that file for a letter that a user chooses, and then output how many times the user's letter appeared in the file.
I know how to get the user input and get the user to select a file, as well as scanning the file, but I cannot figure out a way to check each character within a file for a specific letter. The closest I have been able to come is this:
public class FileLetterCounter
{
public static void main(String[] args) throws IOException
{
int count = 0, stringLength;
String file, a = "a";
Scanner fileScanner, letterScan;
ArrayList<String> line = new ArrayList<String>();
fileScanner = new Scanner(new File("lab6.txt"));
while (fileScanner.hasNext())
{
line.add(fileScanner.next());
for (int index = 0; index < line.length(); index ++)
{
if (line.get(index).contains(a));
{
count++;
}
}
}
}
}
This doesn't work because the length() method does not work on an ArrayList, and I am unsure of how to approach the problem. I am asking this question because I found a similar one, but the recommended solution was to use what I have right now in my for loop (line.length()), but this won't work.
Instead of adding it to the list, just scan the text into a string, iterate each character of the string to check if the character matches with the search character, and increase the value of count for each match.
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class Main {
public static void main(String[] args) throws FileNotFoundException {
int count = 0;
Scanner keyboard = new Scanner(System.in);
System.out.println("Enter the char to search: ");
char searchChar = keyboard.next().charAt(0);
Scanner fileScanner = new Scanner(new File("lab6.txt"));
while (fileScanner.hasNext()) {
String text = fileScanner.next();
for (int index = 0; index < text.length(); index++) {
if (text.charAt(index) == searchChar) {
count++;
}
}
}
System.out.println("The character " + searchChar + " appears " + count + " times in the file.");
fileScanner.close();
}
}
Look at this implementation with Streams. Looks pretty nice to me. Additionally do not forget to provide Charset, otherwise you could get unexpected results.
public static long countCharacterInFile(Path file, char ch, Charset charset) throws IOException {
try (Stream<String> stream = Files.lines(file, charset)) {
return stream.map(String::codePoints)
.flatMap(IntStream::boxed)
.filter(c -> c == ch)
.count();
}
}
Output:
Path file = Paths.get("lab6.txt");
System.out.println(countCharacterInFile(file, 'e', StandardCharsets.UTF_8)); // 666
Assuming you are trying to search a character in the whole file. Modified the code by removing all those unnecessary variables. Also I don't see any use of adding each line to a list of strings.
Idea is to scan through each line and increment count if the current character character matches your character
public class FileLetterCounter
{
public static void main(String[] args) throws IOException
{
int count = 0;
char targetLetter = 'a'; //define whatever you want or take it from user input
Scanner fileScanner = new Scanner(new File("lab6.txt"));
while (fileScanner.hasNext()) {
String line = fileScanner.nextLine();
for(int i=0; i<line.length(); i++) {
if(line.charAt(i) == targetLetter) {
count++;
}
}
}
System.out.println(count);
}
}

Reading a file with Strings and floats and assigning them to arrays

I want to design a code that can read a file that looks like this:
Jake 12.00 13.24 6
Sarah 11.23 24.01 8
Alex 10.65 19.45 4
I need to make separate arrays for the Strings, the first float, the second float, and the int.
How do I go about doing this?
This is what I have so far: I'm not sure how to make separate arrays for the two floats. I also keep getting an exception IndexOutOfBoundsException: 0 at EmployeePay.main..
import java.util.Scanner;
import java.io.*;
public class EmployeePay {
public static void main(String[] args) throws FileNotFoundException {
if (args.length != 1) {
final String msg = "Usage: EmployeePay name_of_input file";
System.err.println(msg);
throw new IllegalArgumentException(msg);
}
final String inputFileName = args[0];
final File input = new File (inputFileName);
final Scanner scanner = new Scanner(new BufferedReader(new FileReader(input)));
String Id = "Employee Id:";
String Hours = "Hours worked:";
String WageRate = "Wage Rate:";
String Deductions = "Deductions:";
System.out.printf("%s %-10s %-20s %-30s", Id, Hours, WageRate, Deductions);
int lineNumber = 0;
while (scanner.hasNextLine()){
lineNumber =lineNumber +1;
String [] Identification= new String [lineNumber-1];
int [] TotalDeductions = new int [lineNumber-1];
float [] WorkTime = new float[lineNumber-1];
if(scanner.hasNextInt()){
TotalDeductions[lineNumber-1] = scanner.nextInt();
System.out.println(TotalDeductions[lineNumber-1]);
}
else if (scanner.hasNextFloat()){
WorkTime[lineNumber-1]= scanner.nextFloat();
}
else {
Identification[lineNumber-1] = scanner.next();
System.out.println(Identification[lineNumber-1]);
}
}
}
}
I will assume your String value doesn't contain space. This is kind of pseudo code, Try yourself and explore each line why I did so:
String s[] = new String[size];
float f1[] = new float[size];
float f2[] = new float[size];
for(int i=0; i<numberOfLines;i++) {
String x = "Jake 12.00 13.24 6";
String[] arr = x.split(" ");
s[i] = arr[0];
f1[i] = Float.valueOf(arr[1]);
f2[i] = Float.valueOf(arr[2]);
}
This error exception IndexOutOfBoundsException: 0 at EmployeePay.main. is occuring due to this statement if (args.length != 1).
It should be if(args.length!=0)
If no arguements are passed at command prompt then args.length is 0. So, this statement will throw an exception final String inputFileName = args[0];
Thus, you need to check for args.length
If your data file is indeed as you show in your post with blank lines between the data lines then you will need to take care of those as well while reading the file and processing the information obtained. You obviously want to skip past those particular lines. If this isn't the case then it only goes to show you how important it is to provide full and accurate information when asking a question here. No one here wants to really assume anything.
When creating arrays it's always nice to know how big an array needs to be beforehand so that you can properly initialize it to its required size. This is where List or ArrayList is better, you can just add to them when needed. Never the less, to properly initialize all your different arrays (String[], float[], float[], and int[]) you need to know how many valid data line are contained within your data file. By valid data lines I mean lines that actually contain data, not blank lines. So the first natural step would be to count those lines. Once you have the count then you can initialize all your arrays to that line count.
Now all you need to do is re-read the file data line by line, split each line to acquire the data segments , then convert each numerical segment to its respective Array data type. Once you have all your arrays filled from the file you can then do whatever you like with the data contained within those arrays. The code to carry out this task might look something like this:
String inputFileName = "MyDataFile.txt";
Scanner scanner;
int linesCount = 0;
try {
// Count the total number of valid data lines
// within the file (blank line are skipped).
scanner = new Scanner(new File(inputFileName));
while (scanner.hasNextLine()) {
String strg = scanner.nextLine().trim();
if (!strg.equals("")) { linesCount++; }
}
// Declare our different Arrays and size them to
// the valid number of data lines in file.
String[] employeeID = new String[linesCount];
float[] hours = new float[linesCount];
float[] wageRate = new float[linesCount];
int[] deductions = new int[linesCount];
// Read through the file again and place the data
// into their respective arrays.
scanner = new Scanner(new File(inputFileName));
int counter = 0;
while (scanner.hasNextLine()){
// Get the next line in file...
String strg = scanner.nextLine().trim();
// If the file line is blank then skip it.
if (strg.equals("")) { continue; }
// otherwise split the line by its space
// delimiter ("\\s+" takes care of 1 OR more
// spaces just in case).
String[] values = strg.split("\\s+");
// Add to the employeeID string array.
employeeID[counter] = values[0];
// Control what is placed into the elements of each
// float or integer array. If there is no value data
// supplied in file for the employee Name then make
// sure 0.0 (for floats) or 0 (for integers) is placed
// there after all, you can't parse a null string ("").
if (values.length >= 2) { hours[counter] = Float.parseFloat(values[1]); }
else { hours[counter] = 0.0f; }
if (values.length >= 3) { wageRate[counter] = Float.parseFloat(values[2]); }
else { wageRate[counter] = 0.0f; }
if (values.length == 4) { deductions[counter] = Integer.parseInt(values[3]); }
else { deductions[counter] = 0; }
counter++;
}
scanner.close();
// Now that you have all your arrays you can
// do whatever you like with the data contained
// within them:
String Id = "Employee Id:";
String Hours = "Hours worked:";
String WageRate = "Wage Rate:";
String Deductions = "Deductions:";
System.out.printf("%-15s %-15s %-15s %-15s%n", Id, Hours, WageRate, Deductions);
for (int i = 0; i < employeeID.length; i++) {
System.out.printf("%-15s %-15s %-15s %-15s%n", employeeID[i], hours[i], wageRate[i], deductions[i]);
}
}
catch (FileNotFoundException ex) { ex.printStackTrace(); }

Reading text File and putting it in a array

I am trying to take a set of 25 numbers from a text file and convert it into a array. But I am lost.
I have read some other questions similar to this, but all of them used imports and extras, and I don't want to use any imports besides import java.io.*; nor any list.
Also the for loop within this is method is me just messing with it, because I couldn't figure it out.
public static int[] processFile (String filename) throws IOException, FileNotFoundException {
BufferedReader inputReader = new BufferedReader (new InputStreamReader(new FileInputStream(filename)));
String line;
int[] a = new int[25];
while (( line = inputReader.readLine()) != null){
int intValue = Integer.parseInt(line); //converts string into int
for (int i = 0; i < a.length; i++){
a[intValue]++;
}
}
return a;
}
public static void printArray (int[] a) {
for (int i = 0; i<a.length; i++) {
System.out.println (a[i]);
}
}
public static void main(String[] args) throws IOException, FileNotFoundException {
int [] array = processFile("C:\Users\griff_000\Desktop\TestWeek13.txt");
printArray(array);
}
I'm unclear about your whole import restriction, why exactly are you trying to limit the number of imports you have?
Anyway, looking at your code, it seems like the concept of arrays isn't all that clear with you.
Arrays are accessed under the syntax:
array[index] = value;
looking at your code, the line a[intValue]++; is actually finding the array index intValue (the number read from file) and incrementing it by one. Not only is this not what you want, numbers over the array length will cause an ArrayIndexOutOfBoundsException.
Making said amendments we get:
public static int[] processFile (String filename) throws IOException, FileNotFoundException{
BufferedReader inputReader = new BufferedReader (new InputStreamReader(new FileInputStream(filename)));
String line;
int[] a = new int[25];
int i = 0; // We need to maintain our own iterator when using a while loop
while((line = inputReader.readLine()) != null){
int intValue = Integer.parseInt(line); //converts string into int
a[i] = intValue; // Store intValue into the array at index i
i++; // Increment i
}
return a;
}
note the additional variable i being used in this context to facilitate the incrementing index number being used to access the array. If you examine this method carefully, a input file longer than 25 elements would also throw ArrayIndexOutOfBoundsException due to the variable i becoming 25 (beyond the limits of the array). To fix, I'd suggest changing the loop structure to a for-loop (assuming your input array is of fixed size) as follows:
public static int[] processFile (String filename) throws IOException, FileNotFoundException{
BufferedReader inputReader = new BufferedReader (new InputStreamReader(new FileInputStream(filename)));
String line;
int[] a = new int[25];
for(int i = 0; i < a.length; i++){
String line = inputReader.readLine(); // Move the readline code inside the loop
if(line == null){
// We hit EOF before we read 25 numbers, deal appropriately
}else{
a[i] = Integer.parseInt(line);
}
}
return a;
}
Note how the for loop integrates the iterator variable into one nice elegant line, keeping the rest of the code neat and readable.
Your mistake is in the line a[intValue]++;. You are telling Java to find the element at [intValue] and add 1 to it's current value. From your question, I understood that you want to put intValue as the array element.
Since you are using i as the iterator, to add the element simply use:
a[i] = intValue;
What you are doing here:
a[intValue]++;
is increasing the array position of the read value by one. If the number read is 2000 you are increasing a[2000]
you might want to do this
a[i]=intValue;

Counting numbers in a text file using Java

This has been troubling me for a while now. I normally don't tend to ask help and do my research, but I couldn't find an answer.
How do I write a program that reads a text file, and calculate how many times a certain number shows up?
I'm a huge beginner in Java, and also programming in general.
Here's my code.
This code generates a text file that has 100 random numbers
import java.io.*;
public class Rolling
{
public static void main (String[] args) throws IOException
{
int randomNum;
PrintWriter fileout = new PrintWriter (new FileWriter ("randumnums.txt"));
for (int i= 0; i < 101; i++)
{
randomNum = (int) (Math.random() * 100);
fileout.println (randomNum);
}
fileout.close();
}
}
Now the trouble I'm having is that I need to read the file and write a code saying X number was rolled 3 times. e.g the number 4 appeared 5 times in the text file, so I would need it to print "the number 4 was rolled 5 times".
import java.io.*;
public class Reading
{
public static void main (String[] args) throws IOException
{
BufferedReader readFile = new BufferedReader (new FileReader ("randumnums.txt"));
int number = 0;
int inMarks [] = new int [100];
for (int i = 0; i < 100; i++)
{
inMarks [i] = Integer.parseInt(readFile.readLine());
}
}
}
You're actually pretty close. It's clear that you're going to have to keep track of your counts in some kind of list, and an array will do quite nicely here.
First, after instantiating inMarks, initialize every value in it to 0:
int inMarks [] = new int [100];
for (int i = 0; i < 100; i++)
{
inMarks [i] = 0;
}
Then change the loop below to this:
String nextLine = null;
while ((nextLine = readFile.readLine()) != null)
{
int thisInt = Integer.parseInt(nextLine);
inMarks[thisInt] = inMarks[thisInt] + 1;
}
inMarks now perfectly tracks how many times each distinct int was rolled in the file. I'm going to let you implement the print-out part of the assignment, since that will give you a better understanding of how this solution works.
I have the feeling you are looking for something like this (I haven't tested this code)
import java.io.*;
public class Reading {
public static void main (String[] args) throws IOException {
BufferedReader readFile = new BufferedReader (new FileReader("randumnums.txt"));
int number = 0;
int inMarks [] = new int [100];
String readNumber = "";
while ((readNumber = readFile.readline()) != null) {
number = Integer.parseInt(readNumber);
inMarks[number]++;
}
}
}
The code above basically has an array of 100 integers. We then start reading the file until nothing can be read anymore. Everytime we read a line, we parse into an integer (which normally you should wrap around a try...catch). We then increase by 1 the number of times we have read this number by increasing the corresponding index in the array. So if you want to know how many times the number '32' appeared, you would do System.print.out(inMarks[32]);

Categories

Resources