Duplicate local variable error with Scanner object and while loop - java

When passing in a Scanner object in java and using a while loop to access each line, an error says I have a duplicate local variable ("fileContents" in the very first line).
static Map<String, Integer> countCategories(Scanner fileContents) {
HashMap<String, Integer> categoryCount = new HashMap<String, Integer>();
while (fileContents.hasNext()) {
String line = fileContents.nextLine();
String[] lineItems = line.split(",");
String category = lineItems[2]; // specified position in CSV file
if (categoryCount.get(category) == null) {
categoryCount.put(category, 1);
} else {
categoryCount.put(category, categoryCount.get(category) + 1);
}
}
To further expound on this, I'm just organizing information from a file, and I'm new to Java. Am I even doing this HashMap right, or should I be formatting this method and/or the hash map created inside in an entirely different way?
As requested, the rest of my main:
public class PA2Main {
public static void main(String[] args) {
try {
String fileName = args[0];
Scanner fileContents = new Scanner(new File(fileName)); // temp var
} catch (FileNotFoundException e) {
e.printStackTrace();
}
// recreate fileContents to use outside of try/catch
String fileName = args[0];
Scanner fileContents = new Scanner(new File(fileName));
HashMap<String, Integer> organizedCategories = countCategories(fileContents); // call function
if (args.length > 1) {
if (!"LOCATION".equals(args[1]) || !"CATCOUNT".equals(args[1])) {
System.out.println("Invalid Command");
} else {
//process commands
if (args[1].equals("CATCOUNT")) {
}
if (args[1].equals("LOCATION")) {
// organize info in fi
}
}
}
}
Formatting is a little weird, but I hope that makes sense. Obviously, I haven't done a lot with the rest of the program and this isn't very clean. The error message just states: Duplicate local variable fileContents
And a "quick fix" is renaming it.

You can't have two variables with the same name in a class most of the time, and especially if the scope of them is the same like it is here with both in the same method. Even if the type of the object was different, the compiler would have no way to differentiate and pick which one you want to use so it won't compile.
In the code you provided, we can see that you used declared 2 Scanner objects with the same name which will cause the error every single time you try this.
public static void main(String[] args) {
try {
String fileName = args[0];
*** Scanner fileContents = new Scanner(new File(fileName));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
String fileName = args[0];
*** Scanner fileContents = new Scanner(new File(fileName));
HashMap<String, Integer> organizedCategories = countCategories(fileContents);
if (args.length > 1) {
if (!"LOCATION".equals(args[1]) || !"CATCOUNT".equals(args[1])) {
System.out.println("Invalid Command");
} else {
if (args[1].equals("CATCOUNT")) {
}
if (args[1].equals("LOCATION")) {
}
}
}
To fix this error generally, you could just rename one of the variables, but in your case, I don't think that having 2 Scanner objects is even necessary.
The try-catch clause should be used specifically for the lines of your code that have an actual possibility of throwing an exception, in this case initializing the scanner.
A cleaner way to write your code with this in mind would be
public static void main (String[] args) {
String fileName = args[0];
Scanner fileContents;
try {
fileContents = new Scanner(new File(fileName));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
HashMap<String, Integer> organizedCategories = countCategories(fileContents);
if (args.length > 1) {
if (!"LOCATION".equals(args[1]) || !"CATCOUNT".equals(args[1])) {
System.out.println("Invalid Command");
} else {
if (args[1].equals("CATCOUNT")) {
}
if (args[1].equals("LOCATION")) {
}
}
}
}

Related

Returning Strings from a file between 2 specified strings in java

I've been searching the web and I can't seem to find a working solution.
I have a file containing theses lines:
Room 1
Coffee
Iron
Microwave
Room_end
Room 2
Coffee
Iron
Room_end
I want to print all Strings between Room 1 and Room_end. I want my code to start when it find Room 1, print line after Room 1 and stop when it get to the first Room_end it find.
private static String LoadRoom(String fileName) {
List<String> result = new ArrayList<>();
try (BufferedReader reader = new BufferedReader(new FileReader(fileName))) {
result = reader.lines()
.dropWhile(line -> !line.equals("Room 1"))
.skip(1)
.takeWhile(line -> !line.equals("Room_end"))
.collect(Collectors.toList());
} catch (IOException ie) {
System.out.println("Unable to create " + fileName + ": " + ie.getMessage());
ie.printStackTrace();
}
for (int i = 0; i < result.size(); i++) {
System.out.println(result.get(i).getname());//error on getname because it cant work with Strings
}
}
class Model {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
I am able to get a method to print all Strings of the file but not specific range of Strings. I also tried to work with Stream. My code feel quite messy, but I've been working on it for a while an it seems it only get messier.
I think there is a problem if you want to use lambda expression here:
lambda expressions are functional programming, and functional programming requires immutability, that means there should not be state related issue, you can call the function and give it same parameters and the result always will be the same, but in your case, there should be a state indicating whether you should print the line or not.
can you try this solution? I write it in python, but mainly it is just about a variable should_print that located outside of the scope
should_print = False
result = reader.lines()
for line in result:
if line == "Room end":
break
if should_print:
print(line)
if line == "Room 1":
should_print = True
keep a boolean value outside of the iteration, and check/update the value in each iteration
public static Map<String, List<String>> getRooms(String path) throws IOException {
Map<String, List<String>> result = new HashMap<>();
try (Scanner sc = new Scanner(new File(path))) {
sc.useDelimiter("(?=Room \\d+)|Room_end");
while (sc.hasNext()) {
Scanner lines = new Scanner(sc.next());
String room = lines.nextLine().trim();
List<String> roomFeatures = new ArrayList<>();
while (lines.hasNextLine()) {
roomFeatures.add(lines.nextLine());
}
if (room.length() > 0) {
result.put(room, roomFeatures);
}
}
}
return result;
}
is one way of doing it for your 'rooms file' though it should really be made more OO by making a Room bean to hold the data. Output with your file: {Room 2=[Coffee, Iron ], Room 1=[Coffee, Iron, Microwave]}
Switched my code and used this:
private static String loadRoom(String fileName) {
BufferedReader reader = null;
StringBuilder stringBuilder = new StringBuilder();
try {
reader = new BufferedReader(new FileReader(fileName));
String line = null; //we start with empty info
String ls = System.getProperty("line.separator"); //make a new line
while ((line = reader.readLine()) != null) { //consider if the line is empty or not
if (line.equals("Room 1")) { //condition start on the first line being "Room 1"
line = reader.readLine(); // read the next line, "Room 1" not added to stringBuilder
while (!line.equals("Room_end")) { //check if line String is "Room_end"
stringBuilder.append(line);//add line to stringBuilder
stringBuilder.append(ls);//Change Line in stringBuilder
line = reader.readLine();// read next line
}
}
}
stringBuilder.deleteCharAt(stringBuilder.length() - 1);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null)
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return stringBuilder.toString();
}
Here's a solution that uses a scanner and a flag. You may choose to break the loop when it reads "Room_end"
import java.util.Scanner;
import java.io.*;
public class Main{
private static String loadRoom(String fileName) throws IOException {
Scanner s = new Scanner(new File(fileName));
StringBuilder sb = new StringBuilder();
boolean print = false;
while(s.hasNextLine()){
String line = s.nextLine();
if (line.equals("Room 1")) print = true;
else if (line.equals("Room_end")) print = false;
else if (print) sb.append(line).append("\n");
}
return sb.toString();
}
public static void main(String[] args) {
try {
String content = loadRoom("content.txt");
System.out.println(content);
}catch(IOException e){
System.out.println(e.getMessage());
}
}
}

How to check for duplicate String in a java String array

I am trying to find duplicates values from the first column 0 in array that's been loaded in a string and split, and then throw an exception when this is found.
Here is my code.
public void loadTrueFalseQuestions() throws Exception {
try {
Scanner input = new Scanner(new FileInputStream(TRUE_FALSE_FILE));
while (input.hasNextLine()) {
line = input.nextLine();
String[] split = line.split(",");
int chapterNumber = Integer.parseInt(split[1]);
String correctAnswer = (split[3]);
String questionID = (split[0]);
if (split.length != TRUE_FALSE_FIELDS) {
throw new Exception();
} else if ((!correctAnswer.matches("TRUE")) & (!correctAnswer.matches("FALSE"))) { //throw new Exception();
} else if (true) {
}
}
} catch (FileNotFoundException e) {
System.out.println("Could not open a file.");
System.exit(0);
}
}
This is the CSV file.
TF001,8,Java allows an instance of an abstract class to be instantiated.,FALSE
TF001,8,Downcasting should be used only in situations where it makes sense.,TRUE
TF003,9,The throw operator causes a change in the flow of control.,TRUE
TF004,9,When an exception is thrown the code in the surrounding try block continues executing
and then the catch block begins execution.,FALSE
I'm not sure how to go about it. I cannot get past the logic. I'm trying an if statement and contains(questionID) string method, but not sure how to combine these two. (if that makes sense).
Appreciate any advice.
I use a hash map and put the key field as the key in the hash map. You can check if you already put the key in the hash and if so do something because you already have it.
public void loadTrueFalseQuestions() throws Exception {
try {
Scanner input = new Scanner(new FileInputStream(TRUE_FALSE_FILE));
Map<String, String> myHash = new HashMap<>();
while (input.hasNextLine()) {
line = input.nextLine();
String[] split = line.split(",");
int chapterNumber = Integer.parseInt(split[1]);
String correctAnswer = (split[3]);
String questionID = (split[0]);
if (myHash.containsKey(questionID)) {
// what to do here?
} else {
myHash.put(questionID, line);
}
}
} catch (FileNotFoundException e) {
System.out.println("Could not open a file.");
System.exit(0);
}
}

how to read file and return string and its value

i have file containing words and its value. i want to create parameters that returns the words and its value but I'm not sure how to do this and my code doesn't work.
this is my code;
public static void main(String[] args)throws IOException {
Scanner scan = new Scanner("/..../file.txt");
String word = scan.next();
while(scan.hasNextLine()){
scan.nextLine();
System.out.println(word);
}
scan.close();
}
this is what is in the file, there are lots of data;
{hi=2, bye=5, school=3, went=2, going=1, yesss=1, etc..}
any help on how to do this please?
The scanner class scans the value provided in the constructor.
If that value is a string it simply scans that string.
If you want it to scan a file you should use a file object as the argument e.g.:
Scanner scan = new Scanner(new File("/..../file.txt"));
The way you pass you are passing your file path in Scanner constructor is wrong ,you can pass your file path in this way
Scanner scan = new Scanner(new File("/..../file.txt"));
hope this may help .
try doing following
public static void main(String[] args) {
BufferedReader br = null;
try {
String sCurrentLine;
br = new BufferedReader(new FileReader("D:/abc.txt"));
while ((sCurrentLine = br.readLine()) != null) {
String trimmedStr = sCurrentLine.replace(" ", "");
String mainStr = trimmedStr.substring(1,trimmedStr.length()-1);
String[] arr = mainStr.split(",");
Map<String, String> mainMap = new HashMap<String, String>();
for(String pair : arr){
String[] kvArr = pair.split("=");
mainMap.put(kvArr[0], kvArr[1]);
}
System.out.println(mainMap.get("hi"));
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (br != null)br.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
your file should contain following
{hi=2, bye=5, school=3, went=2, going=1, yesss=1}
OP:
2

Java: adding to a string array in a while loop using a file reader

I have been making a little program that needs to read a list of golf courses that could be changeing and needs to be called when ever. Here is the code:
public class Courses {
public String[] courselist;
public void loadCourses() throws IOException{
int count = 0;
int counter = 0;
File f = new File("src//courses//courses.txt");
BufferedReader reader = new BufferedReader(new FileReader(f));
while(count<1){
String s = reader.readLine();
if(s.equalsIgnoreCase("*stop*")){
reader.close();
count = 5;
}else{
courselist[counter] = s;
counter++;
}
s = "";
}
}
}
And now this is what is in the txt file.
RiverChase
Steward Peninsula
Lake Park
Coyote Ridge
*stop*
Now when ever i start to run the program because i call the method instantly it gives me a throw exeption and it is because of the array. And i need to stay and array because i use it in a JComboBox. If you can help or fix the problem. Most likely im just doing it wrong, im a noob. Just help. Thanks in advance.
I know all the file reader and stuff works because it prints out to the system correct, i just need help writing it to the array repetedly.
You should initialize your array before using it
public static final MAX_SIZE = 100;
public String[] courselist = new String[MAX_SIZE];
Change your code to assign a new array during loadCourses(), and add a call to loadCourses() to your constructor:
public class Courses {
public String[] courselist;
public Courses() throws IOException { // <-- Added constructor
loadCourses(); // <-- Added call to loadCourses
}
public void loadCourses() throws IOException {
int count = 0;
int counter = 0;
File f = new File("src//courses//courses.txt");
BufferedReader reader = new BufferedReader(new FileReader(f));
List<String> courses = new ArrayList<String>(); // <-- A List can grow
while(true){
String s = reader.readLine();
if (s.equalsIgnoreCase("*stop*")){
break;
}
courses.add(s);
}
courseList = courses.toArray(new String[0]); // <-- assign it here
}
}
This ensures that when you create an instance, it starts out life with the array initialised. Not only will you not get an error, but the data will always be correct (unlike other answers that simply create an empty (ie useless) array.
Note that this code will work with any number of course names in the file (not just 5).
You'd better create a List that is easier to manipulate and convert it as an array at the end of the process :
List<String> list = new ArrayList<String>();
String [] array = list.toArray(new String [] {});
Here is a possible implementation of the loading using a List :
public static String [] loadCourses() throws IOException {
File f = new File("src//courses.txt");
BufferedReader reader = new BufferedReader(new FileReader(f));
List<String> courses = new ArrayList<String>();
while (true){
String s = reader.readLine();
if (s == null || s.trim().equalsIgnoreCase("*stop*")){
break;
} else{
courses.add(s);
}
}
return courses.toArray(new String [] {});
}
Also why use a stop keyword ? You could simply stop the process when you reach the end of the file (when s is null).
Here some example, without using the *stop*:
public class ReadFile {
public static void main(String[] args) {
BufferedReader reader = null;
List<String> coursesList = new ArrayList<>();
String[] courses;
try {
File file = new File("courses.txt");
reader = new BufferedReader(new FileReader(file));
String readLine;
do {
readLine = reader.readLine();
if(readLine == null)
break;
coursesList.add(readLine);
} while (true);
} catch (IOException ex) {
Logger.getLogger(ReadFile.class.getName()).log(Level.SEVERE, null, ex);
} finally {
try {
reader.close();
} catch (IOException ex) {
Logger.getLogger(ReadFile.class.getName()).log(Level.SEVERE, null, ex);
}
}
courses = coursesList.toArray(new String[coursesList.size()]);
for(int i = 0; i < courses.length; i++) {
System.out.println(courses[i]);
}
}
}

Method to find string inside of the text file. Then getting the following lines up to a certain limit

So this is what I have so far :
public String[] findStudentInfo(String studentNumber) {
Student student = new Student();
Scanner scanner = new Scanner("Student.txt");
// Find the line that contains student Id
// If not found keep on going through the file
// If it finds it stop
// Call parseStudentInfoFromLine get the number of courses
// Create an array (lines) of size of the number of courses plus one
// assign the line that the student Id was found to the first index value of the array
//assign each next line to the following index of the array up to the amount of classes - 1
// return string array
}
I know how to find if a file contains the string I am trying to find but I don't know how to retrieve the whole line that its in.
This is my first time posting so If I have done anything wrong please let me know.
You can do something like this:
File file = new File("Student.txt");
try {
Scanner scanner = new Scanner(file);
//now read the file line by line...
int lineNum = 0;
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
lineNum++;
if(<some condition is met for the line>) {
System.out.println("ho hum, i found it on line " +lineNum);
}
}
} catch(FileNotFoundException e) {
//handle this
}
Using the Apache Commons IO API https://commons.apache.org/proper/commons-io/ I was able to establish this using FileUtils.readFileToString(file).contains(stringToFind)
The documentation for this function is at https://commons.apache.org/proper/commons-io/javadocs/api-2.4/org/apache/commons/io/FileUtils.html#readFileToString(java.io.File)
Here is a java 8 method to find a string in a text file:
for (String toFindUrl : urlsToTest) {
streamService(toFindUrl);
}
private void streamService(String item) {
try (Stream<String> stream = Files.lines(Paths.get(fileName))) {
stream.filter(lines -> lines.contains(item))
.forEach(System.out::println);
} catch (IOException e) {
e.printStackTrace();
}
}
When you are reading the file, have you considered reading it line by line? This would allow you to check if your line contains the file as your are reading, and you could then perform whatever logic you needed based on that?
Scanner scanner = new Scanner("Student.txt");
String currentLine;
while((currentLine = scanner.readLine()) != null)
{
if(currentLine.indexOf("Your String"))
{
//Perform logic
}
}
You could use a variable to hold the line number, or you could also have a boolean indicating if you have passed the line that contains your string:
Scanner scanner = new Scanner("Student.txt");
String currentLine;
int lineNumber = 0;
Boolean passedLine = false;
while((currentLine = scanner.readLine()) != null)
{
if(currentLine.indexOf("Your String"))
{
//Do task
passedLine = true;
}
if(passedLine)
{
//Do other task after passing the line.
}
lineNumber++;
}
This will find "Mark Sagal" in Student.txt. Assuming Student.txt contains
Student.txt
Amir Amiri
Mark Sagal
Juan Delacruz
Main.java
import java.io.BufferedReader;
import java.io.FileReader;
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
final String file = "Student.txt";
String line = null;
ArrayList<String> fileContents = new ArrayList<>();
try {
FileReader fReader = new FileReader(file);
BufferedReader fileBuff = new BufferedReader(fReader);
while ((line = fileBuff.readLine()) != null) {
fileContents.add(line);
}
fileBuff.close();
} catch (Exception e) {
System.out.println(e.getMessage());
}
System.out.println(fileContents.contains("Mark Sagal"));
}
}
I am doing something similar but in C++. What you need to do is read the lines in one at a time and parse them (go over the words one by one). I have an outter loop that goes over all the lines and inside that is another loop that goes over all the words. Once the word you need is found, just exit the loop and return a counter or whatever you want.
This is my code. It basically parses out all the words and adds them to the "index". The line that word was in is then added to a vector and used to reference the line (contains the name of the file, the entire line and the line number) from the indexed words.
ifstream txtFile;
txtFile.open(path, ifstream::in);
char line[200];
//if path is valid AND is not already in the list then add it
if(txtFile.is_open() && (find(textFilePaths.begin(), textFilePaths.end(), path) == textFilePaths.end())) //the path is valid
{
//Add the path to the list of file paths
textFilePaths.push_back(path);
int lineNumber = 1;
while(!txtFile.eof())
{
txtFile.getline(line, 200);
Line * ln = new Line(line, path, lineNumber);
lineNumber++;
myList.push_back(ln);
vector<string> words = lineParser(ln);
for(unsigned int i = 0; i < words.size(); i++)
{
index->addWord(words[i], ln);
}
}
result = true;
}
Here is the code of TextScanner
public class TextScanner {
private static void readFile(String fileName) {
try {
File file = new File("/opt/pol/data22/ds_data118/0001/0025090290/2014/12/12/0029057983.ds");
Scanner scanner = new Scanner(file);
while (scanner.hasNext()) {
System.out.println(scanner.next());
}
scanner.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
if (args.length != 1) {
System.err.println("usage: java TextScanner1"
+ "file location");
System.exit(0);
}
readFile(args[0]);
}
}
It will print text with delimeters

Categories