How to find strings within a text file in JAVA - java

I'd like to just see an example with some explanation.
What string functions do I use to compare the objects and does it compare each character or the actual word without any additional letters to it?
Thanks

I tried doing something very similar to this question for a project awhile ago. There are numerous ways to do this in Java, but I used the Scanner class and the File class.
public static void main(String[] args)
{
Scanner input = new Scanner(System.in); //Just a normal scanner
System.out.println("Please enter in the pathname to the file you want to view.");
String pathname = input.nextLine(); //Pathname to text file
File book = new File(pathname); //Creating a new file using the pathname
if(book.canRead() == false) //If Java cant read the file, this will pop up
{
System.out.println("Your file cannot be read");
}
else if(book.canRead() == true) //If Java can read the file, then this asks for the word to search for
{
System.out.println("Please enter in the word you wish to search for.");
wordToSearchFor = input.nextLine();
wordCounter(book); //Calls the method
}
System.out.println(wordToSearchFor.toLowerCase() + " appeared " + numOfOccurrences + " times in " + pathname);
}
This is the main method where you use the File class to create a file based off of a pathname that you give it EX - C:\Users\alex\Downloads\mobydick.txt
I then check to see if you can read the file, and if you can, then I call a method to analyze the book itself
import java.io.*;
import java.util.Scanner;
public class TextReader
{
private static int numOfOccurrences; //Counter to keep track of the number of occurances
private static String wordToSearchFor; //String field so both methods can access it
/*
* This method takes in the file of the book so the scanner can look at it
* and then does all of the calculating to see if the desired word appears,
* and how many times it does appear if it does appear
*/
public static void wordCounter(File bookInput)
{
try
{
Scanner bookAnalyzer = new Scanner(bookInput); //Scanner for the book
while(bookAnalyzer.hasNext()) //While the scanner has something to look at next
{
String wordInLine = bookAnalyzer.next(); //Create a string for the next word
wordInLine = wordInLine.toLowerCase(); //Make it lowercase
String wordToSearchForLowerCase = wordToSearchFor.toLowerCase();
String wordToSearchForLowerCasePeriod = wordToSearchForLowerCase + ".";
if(wordInLine.indexOf(wordToSearchForLowerCase) != -1 && wordInLine.length() == wordToSearchFor.length())
{
numOfOccurrences++;
}
else if(wordInLine.indexOf(wordToSearchForLowerCasePeriod) != -1 && wordInLine.length() == wordToSearchForLowerCasePeriod.length())
{
numOfOccurrences++;
}
}
}
catch(FileNotFoundException e) //Self explanitory
{
System.out.println("The error is FileNotFoundException - " + e);
System.out.println("This should be impossible to get to because error checking is done before this step.");
}
}
Scanners in Java can be take a File object to analyze, which is the fist thing I do in this method. I then use a while loop and ask the Scanner if there is a word that follows the current word. As long as there is a word, this will continue to run. I then create a String of the current word that the scanner is on to use as a reference to compare against. I then use a method that comes with the String class to make everything lowercase because uppercase and lowercase letters matter.
The first if statement in this method checks if the current word that the scanner has matches what you are searching for using the indexOf method from the String class, which takes some string and looks to see if it exists in another string. The if statement comparison also makes sure that the desired word length is the same as the word length in the book in case you are looking up "the" and it doesnt mark "then" as a word since it contains "the". The second if statement does the same thing, just with your desired word with a period at the end. If you wanted to go the extra mile, you could also check for exclamation points, question marks, commas, and so forth, but I decided to just check for periods.
Every time one of these if statements is correct, I increment a variable by one, and after the scanner runs out of words to search for, I print out the total number of times that certain word appears in a text file.

Related

using patterns/delimiter to get String from Scanner

I have a .txt file that has information sorted as
information field; information field; information field; information field and so on. All fields are Strings.How do I make a method that gets next information field?
More information:
I exported the .txt file from Microsoft access with ";" as the delimiter. if my Scanner is named sc, how can I do an sc.nextField() kind of method? What I had originally done was have a while loop going through each word with sc.next() and adding the word to a String until it encounters a ";" but that method ignored my new lines inside fields.
private static String grabField(Scanner sc) {
String wordInFloat;
String wordsToPass = "";
while (true) {
wordInFloat = sc.next();
if (wordInFloat.endsWith(";"))
break;
else
wordsToPass += wordInFloat + " ";
}
return wordsToPass;
}
You can use the built in function sc.useDelimiter(";") and then go in a while loop to extract the information, such as:
while (sc.hasNext()) {
wordsToPass += sc.next(); // edited to change sc.nextLine() to sc.next()
}
Side Note: if you want to get rid of any leading and trailing space from a String, before adding it to wordsToPass you can use something like sc.nextLine().trim()
Edit: my answer was not quite right, use sc.next() instead of sc.nextLine().

Need Help Fixing An Exception Error in my Code

I am working on a Lab on the site Zybooks and I have completed the following code below:
import java.util.Scanner;
public class LabProgram {
public static void main(String[] args) {
Scanner scnr = new Scanner(System.in);
String firstName;
String middleName;
String lastName;
firstName = scnr.next();
middleName = scnr.next();
lastName = scnr.nextLine();
if (lastName.contains("")){
System.out.println(middleName + ", " + firstName.charAt(0) + ".");
}
else {
lastName = lastName.substring(1);
System.out.println(lastName + ", " + firstName.charAt(0) + "." + middleName.charAt(0) + ".");
}
}
}
The Exception Error that I receive is this:
Exception in thread "main" java.util.NoSuchElementException: No line found
at java.base/java.util.Scanner.nextLine(Scanner.java:1651)
at LabProgram.main(LabProgram.java:13)
When I run the following code in an IDE everything works just fine. However when I try running it in Zybooks I get an exception error. I've come to learn that this is because when I don't add a space after I enter two names that Zybooks gives an exception error. However when I add a space after the last name the code compiles as intended. For grading purposes I need the code to compile without a space from the keyboard, thus I am asking how I can get this code to compile. I've tried manually adding whitespace but nothing has worked.
Any help would be very much appreciated
Looking at the code it's obvious that you have three (3) specific User entry prompts to deal with. The User must supply a First Name, then the User needs to supply a Middle Name, and then finally the User needs to supply a Last Name. As with any input each of these names needs to be validated for proper context. This would include the rules for names, for example everyone has a First Name and Last Name but not everyone has a Middle Name also first and last names can contain two name words (ex: De Vanderholt).
When you have three specific prompts for the User to fill in then let them know exactly where they are at. Display on Screen what the User is expected to enter. It's always a good idea to place each prompt into a loop so that the input can be validated and if there is a problem the User is given the opportunity to provide actual valid data (in this case a valid name).
In your code you use the Scanner#next() method to retrieve the input for both First Name and Middle Name(s) however this method will not play well with multi word names since the next() method is token based. This means that if a two word name is supplied to the First Name prompt then only the first word is retrieved and the second word is automatically applied to the Middle Name prompt. You don't even get a chance to enter the middle name. This is no good unless special code is put in place to take car of this situation. It's just better not to use the next() method in this case and simply use the Scanner#nextLine() method for all your prompts. Keep in mind however that the Scanner#next() method will work just fine if you know that only a single name word will be provided by the User but this method is better used in conjunction with the Scanner#hasNext() method.
Look at your code. As said earlier, everyone has a Last Name but not everyone has a Middle Name so why have this line of code (unless your rules include the fact that last names can be nothing):
if (lastName.contains("")){
It should actually never be allowed to come to this scenario where the last name contains nothing, don't even accept the fact unless it's a middle name. If the supplied Last Name was validated then you would never need to worry about this situation unless of course your rules allow it. The example code below does not allow it.
Because there are three prompt which basically do the same thing and require the same basic validation a helper method (getName()) is used so as to eliminate the need for duplicate code:
public static void main(String[] args) {
Scanner scnr = new Scanner(System.in);
// First Name:
String firstName = getName(scnr, "First");
// Middle Name:
String middleName = getName(scnr, "Middle");
// Last Name:
String lastName = getName(scnr, "Last");
System.out.println(new StringBuilder("")
.append(lastName).append(", ")
.append(firstName.charAt(0))
.append(". ")
.append(middleName.isEmpty() ? "" : middleName.charAt(0))
.append(middleName.isEmpty() ? "" : ".").toString());
// O R
/*
System.out.println(new StringBuilder("")
.append(lastName).append(", ")
.append(firstName)
.append(" ")
.append(middleName)
.toString());
*/
// O R
/*
System.out.println(new StringBuilder("")
.append(firstName)
.append(" ")
.append(middleName)
.append(middleName.isEmpty() ? "" : " ")
.append(lastName)
.toString());
*/
}
The Helper Method (getName()):
private static String getName(final Scanner scnr, final String nameTitle) {
String name = "";
while (name.isEmpty()) {
System.out.print("Enter your " + nameTitle + " Name: --> ");
// Get input and trim off leading/trailing whitespaces, etc
name = scnr.nextLine().trim();
// Is this for a Middle Name?
if (nameTitle.equalsIgnoreCase("middle")) {
// If nothing was supplied then there is no
// middle name so break out of prompt loop.
if (name.isEmpty()) {
break;
}
}
// Validate name...
/* Does the supplied name only contain A to Z characters
in any letter case. Add characters to the regular
expression as you see fit. (?i) means any letter case. */
if (name.matches("(?i)[A-Z. ]+")) {
// Yes, it does...
/* Ensure 'first' character of each name word (if more than one)
is upper letter case. */
String[] tmp = name.split("\\s+");
StringBuilder nme = new StringBuilder("");
for (String str : tmp) {
if (!Character.isUpperCase(str.charAt(0))) {
str = str.substring(0, 1).toUpperCase() + str.substring(1).toLowerCase();
}
if (!nme.toString().isEmpty()) {
nme.append(" ");
}
nme.append(str);
}
name = nme.toString();
}
// No it doesn't so inform User of the mistake and to try again.
else {
System.err.println("Invalid " + nameTitle + " Name Supplied! (" + name + ") Try Again...");
name = ""; // Set to null string so as to re-prompt.
}
}
return name;
}

Find variable name and store it for later reference

I want to be able to find the variable name of an object that has already been checked for if it has been called. And then store this variable name inside either an array or other form of storage for later reference. Here is the code in it's unfinished state.
import java.util.*;
public class errorHelpImproved
{
//Needs Scanner to detect what's in the line
public static Scanner sc = new Scanner(System.in);
//Create a section that reads line by line and finds commands that aren't imported
public static void import1(File file)
{
/*logic note:
read line by line
IF a line contains the keyword Scanner
-Set a flag to check for the keyphrase import java.util.Scanner; OR import java.util.*;
-If neither keyphrase found before the first instance of a keyword public class
+Then Scanner has been called without the package being imported
-If either keyphrase found, stop searching and add this Scanner variable to an array of Scanner variables
*/
File fileStart = new File(file);
do
{
String line = file.nextLine();
if(line.contains(" Scanner "))
{
boolean flagTest=false;
String line2;
do
{
line2 = fileStart.nextLine;
if(line2.contains("import java.util.*;") || line2.contains("import java.util.Scanner;"))
{
flagTest=true;
break;
}
}while(!line2.contains("public class"))
if(flagTest == false)
{
System.out.println("Scanner class has been called without being imported.");
}
else if(flagTest == true)
{
//This is where it would find the word after scanner and store it
}
}
}while(file.hasNext());
}
//Main method gets name of file and passes it to the first check and then from there all other codes will use it
public static void main(Strings [] args)
{
System.out.println("");
}
}
Cause I've thought about this for almost a week and I have no idea how I would go about this.
Scanning .java files for declarations and reading the variable name is more complex than this. You can do it like this, but java code has no requirement for linebreaks. A java application is fine to be written in one line.
The same is true for adding linebreaks. You can add a linebreak wherever a whitespace is allowed in the code.
Scanner sVar;
Scanner
sVar2;
Are both legal java code. Your approach will also match text literals and comments:
/* This is a line with the Scanner variable */
String value = "I am fooling the Scanner code with this line and the comment above";
Reading your comments above: The java compiler does what your teacher asked you for. You can run the java compiler using the javax.tools package. See more information here http://docs.oracle.com/javase/8/docs/api/javax/tools/ToolProvider.html#getSystemJavaCompiler()
Having said that, you must accept restrictions to your approach: The code must be "well formatted" to match your search criteria, otherwise you will have false positives or bad matches.
consider that each line containing " Scanner " is in fact a variable definition or declaration.
The word after Scanner is not a comment and we suppose it to be the variable name.
There is only one Scanner defined per line. (No Scanner sA, sB; or Scanner sA; Scanner sB;)
Furthermore, you store the list of matches in a List for later processing (write to file).
Then the missing code could look like this:
else if(flagTest == true)
{
//This is where it would find the word after scanner and store it
int pos = line.indexOf("Scanner") + "Scanner ".length();
String varStart = line.substring(pos);
pos = varStart.indexOf(";");
String varName = varStart.substring(0, pos).trim();
variableNames.add(varName);
}
This will be less restrictive, if you run it with a regular expression matcher on the line, that has a match-group for the variable name. But I think this is maybe more confusing for your coding level.
A regular expression with a matching group should look like this: .*Scanner\s+([a-zA-Z_$][a-zA-Z_0-9$]*)[\s;].*

print even words from string input?

I am in a beginners course but am having difficulty with the approach for the following question: Write a program that asks the user to enter a line of input. The program should then display a line containing only the even numbered words.
For example, if the user entered
I had a dream that Jake ate a blue frog,
The output should be
had dream Jake a frog
I am not sure what method to use to solve this. I began with the following, but I know that will simply return the entire input:
import java.util.Scanner;
public class HW2Q1
{
public static void main(String[] args)
{
Scanner keyboard = new Scanner(System.in);
System.out.println("Enter a sentence");
String sentence = keyboard.next();
System.out.println();
System.out.println(sentence);
}
}
I dont want to give away the answer to the question (for the test, not here), but I suggest you look into
String.Split()
From there you would need to iterate through the results and combine in another string for output. Hope that helps.
While there will be more simpler and easier way to do this, I'll use the basic structure- for loop, if block and a while loop to achieve it. I hope you will be able to crack the code. Try running it and let me know if there is an error.
String newsent;
int i;
//declare these 2 variables
sentence.trim(); //this is important as our program runs on space
for(i=0;i<sentence.length;i++) //to skip the odd words
{
if(sentence.charAt(i)=" " && sentence.charAt(i+1)!=" ") //enters when a space is encountered after every odd word
{
i++;
while(i<sentence.length && sentence.charAt(i)!=" ") //adds the even word to the string newsent letter by letter unless a space is encountered
{
newsent=newsent + sentence.charAt(i);
i++;
}
newsent=newsent+" "; //add space at the end of even word added to the newsent
}
}
System.out.println(newsent.trim());
// removes the extra space at the end and prints newsent
you should use sentence.split(regex) the regular expression is going to describe what separate your worlds , in your case it is white space (' ') so the regex is going to be like this:
regex="[ ]+";
the [ ] means that a space will separate your words the + means that it can be a single or multiple successive white space (ie one space or more)
your code might look like this
Scanner sc= new Scanner(System.in);
String line=sc.nextLine();
String[] chunks=line.split("[ ]+");
String finalresult="";
int l=chunks.length/2;
for(int i=0;i<=l;i++){
finalresult+=chunks[i*2]+" ";//means finalresult= finalresult+chunks[i*2]+" "
}
System.out.println(finalresult);
Since you said you are a beginner, I'm going to try and use simple methods.
You could use the indexOf() method to find the indices of spaces. Then, using a while loop for the length of the sentence, go through the sentence adding every even word. To determine an even word, create an integer and add 1 to it for every iteration of the while loop. Use (integer you made)%2==0 to determine whether you are on an even or odd iteration. Concatenate the word on every even iteration (using an if statement).
If you get something like Index out of range -1, manipulate the input string by adding a space to the end.
Remember to structure the loop such that, regardless of the whether it is an even or odd iteration, the counter increases by 1.
You could alternatively remove the odd words instead of concatenation the even words, but that would be more difficult.
Not sure how you want to handle things like multiple spaces between words or weird non-alphabetically characters in the entry but this should take care of the main use case:
import java.util.Scanner;
public class HW2Q1 {
public static void main(String[] args)
{
System.out.println("Enter a sentence");
// get input and convert it to a list
Scanner keyboard = new Scanner(System.in);
String sentence = keyboard.nextLine();
String[] sentenceList = sentence.split(" ");
// iterate through the list and write elements with odd indices to a String
String returnVal = new String();
for (int i = 1; i < sentenceList.length; i+=2) {
returnVal += sentenceList[i] + " ";
}
// print the string to the console, and remove trailing whitespace.
System.out.println(returnVal.trim());
}
}

Scanner & .hasNext() issue

I am new to Java and very new to the Scanner class. I am writing a program which asks the user for a word and then this word is searched for within a file. Each time the word is found, it is printed on a new line in a JOptionPane, as well as the word before and after it. Everything is functioning as it should, with two exceptions:
If the word being searched for happens to be the last word in the file then a "NoSuchElementException" is thrown.
If the word being searched for appears twice in a row (unlikely, but still a problem I discovered), it only returns it once. For example, if the word being searched for was "had" and "He said that he had had enough. He had been up all night" were sentences in the file, then the output is:
he had had
He had been
whereas it should be:
he had had
had had enough.
He had been
I believe that my problem lies in the fact that I use a while(scan.hasNext()) and within this loop I use scan.next() twice. I cannot find a solution for this though, while still achieving what I would like the program to return.
Here is my code:
//WordSearch.java
/*
* Program which asks the user to enter a filename followed
* by a word to search for within the file. The program then
* returns every occurrence of this word as well as the
* previous and next word it appear with. Each of these
* occurrences are printed on a new line when displayed
* to the user.
*/
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.Scanner;
import javax.swing.JOptionPane;
public class WordSearch {
public static void main(String[] args) throws FileNotFoundException {
String fileName = JOptionPane.showInputDialog("Enter the name of the file to be searched:");
FileReader reader = new FileReader(fileName);
String searchWord = JOptionPane.showInputDialog("Enter the word to be searched for in \"" + fileName + "\":");
Scanner scan = new Scanner(reader);
int occurrenceNum = 0;
ArrayList<String> occurrenceList = new ArrayList<String>();
String word = "", previousWord, nextWord = "", message = "", occurrence, allOccurrences = "";
while(scan.hasNext()){
previousWord = word;
word = scan.next();
if(word.equalsIgnoreCase(searchWord)){
nextWord = scan.next();
if(previousWord.equals("")){
message = word + " is the first word of the file.\nHere are the occurrences of it:\n\n";
occurrence = word + " " + nextWord;
}
else{
occurrence = previousWord + " " + word + " " + nextWord;
}
occurrenceNum++;
occurrenceList.add(occurrence);
}
}
for(int i = 0; i < occurrenceNum; i++){
allOccurrences += occurrenceList.get(i) + "\n";
}
JOptionPane.showMessageDialog(null, message + allOccurrences);
scan.close();
}
}
Also, on a side note: How can I implement scan.useDelimeter() to ignore any, question marks, commas, periods, apostrophes etc?
If the word being searched for happens to be the last word in the file then a NoSuchElementException is thrown.
This is because of this line:
if(word.equalsIgnoreCase(searchWord)) {
nextWord = scan.next();
...
}
You do not check if the scan actually hasNext(), going straight for scan.next(). You can fix this by adding a conditional with a call to scan.hasNext()
If the word being searched for appears twice in a row (unlikely, but still a problem I discovered), it only returns it once.
That the same problem is in play here: when you find a word, you retrieve the next one right away.
Fixing this is a little tricky: you need to change your algorithm to look at one word at a time, and use previousWord (which you store anyway) for use of subsequent iterations of the while loop.
What you could do is just call hasNext before using next again.
while(scan.hasNext()){
previousWord = word;
word = scan.next();
if(word.equalsIgnoreCase(searchWord) && scan.hasNext()){ // this line change
nextWord = scan.next();
if(previousWord.equals("")){
message = word + " is the first word of the file.\nHere are the occurrences of it:\n\n";
occurrence = word + " " + nextWord;
}
else {
occurrence = previousWord + " " + word + " " + nextWord;
}
occurrenceNum++;
occurrenceList.add(occurrence);
}
}
You want to not use equals with ignore case. You want to just use .equals().
The solution would be to save two words the way you are currently saving previousWord. Something like:
while (scan.hasNext()) {
previousWord = word;
word = nextWord;
nextWord = scan.next();
Then you check word. If it matches what you need, then you can print it together with previousWord and nextWord. That is, in every iteration, you are checking the word you read in the previous iteration.
This way you only need one hasNext() and one next() in your loop.
Note that after the end of the loop, nextWord might actually be your word. This would mean your word is the last word in the file, and you should check for this and print it accordingly.

Categories

Resources