Parse Text using scanner useDelimiter - java

Looking to parse the following text file:
Sample text file:
<2008-10-07>text entered by user<Ted Parlor><2008-11-26>additional text entered by user<Ted Parlor>
I would like to parse the above text so that I can have three variables:
v1 = 2008-10-07
v2 = text entered by user
v3 = Ted Parlor
v1 = 2008-11-26
v2 = additional text entered by user
v3 = Ted Parlor
I attempted to use scanner and useDelimiter, however, I'm having issue on how to set this up to have the results as stated above. Here's my first attempt:
import java.io.*;
import java.util.Scanner;
public class ScanNotes {
public static void main(String[] args) throws IOException {
Scanner s = null;
try {
//String regex = "(?<=\\<)([^\\>>*)(?=\\>)";
s = new Scanner(new BufferedReader(new FileReader("cur_notes.txt")));
s.useDelimiter("[<]+");
while (s.hasNext()) {
String v1 = s.next();
String v2= s.next();
System.out.println("v1= " + v1 + " v2=" + v2);
}
} finally {
if (s != null) {
s.close();
}
}
}
}
The results is as follows:
v1= 2008-10-07>text entered by user v2=Ted Parlor>
What I desire is:
v1= 2008-10-07 v2=text entered by user v3=Ted Parlor
v1= 2008-11-26 v2=additional text entered by user v3=Ted Parlor
Any help that would allow me to extract all three strings separately would be greatly appreciated.

You can use \s*[<>]\s* as delimiter. That is, any of < or >, with any preceding and following whitespaces.
For this to work, there must not be any < or > in the input other than the ones used to mark the date and user fields in the input (i.e. no I <3 U!! in the message).
This delimiter allows empty string parts in an entry, but it also leaves empty string tokens between any two entries, so they must be discarded manually.
import java.util.Scanner;
public class UseDelim {
public static void main(String[] args) {
String content = " <2008-10-07>text entered by user <Ted Parlor>"
+ " <2008-11-26> additional text entered by user <Ted Parlor>"
+ " <2008-11-28><Parlor Ted> ";
Scanner sc = new Scanner(content).useDelimiter("\\s*[<>]\\s*");
while (sc.hasNext()) {
System.out.printf("[%s|%s|%s]%n",
sc.next(), sc.next(), sc.next());
// if there's a next entry, discard the empty string token
if (sc.hasNext()) sc.next();
}
}
}
This prints:
[2008-10-07|text entered by user|Ted Parlor]
[2008-11-26|additional text entered by user|Ted Parlor]
[2008-11-28||Parlor Ted]
See also
regular-expressions.info/Character classes
regular-expressions.info/Repetition

Related

Console.getLine and Console.getString not taking in all of user input - JAVA

I am trying to take in user input (the name of a country) to add to a list of countries that I display. However, it is not letting me enter the name of a country longer than 8 characters.
For example, when I input "Venezuela" the output is "Venezuel" and when I input "United States" the output is "United S"
Below is the method I used to accept the user input. I have tried Console.getString as well as Console.getLine and neither are working to accept more than 8 characters.
public static void addCountry() {
String name = Console.getString("Enter country name: ");
Country country = new Country();
country.setName(name);
countryDAO.add(country);
System.out.println();
System.out.println(name
+ " has been added.\n");
}
I also have these methods in the Console class
import java.util.Scanner;
public class Console {
private static Scanner sc = new Scanner(System.in);
public static String getLine(String prompt) {
System.out.print(prompt);
String s = sc.nextLine();
return s;
}
public static String getString(String prompt) {
System.out.print(prompt);
String s = sc.next();
sc.nextLine();
return s;
}
}
Use this to take input instead of sc.next():
String s = sc.nextLine();
and remove the next line where you have added sc.nextLine()
Hope that helps!

How do I return the number of items found after I do a search?

Please help me to figure out how I can get a count of the result when I do a search against a specific folder?
Also how can I ask the user if they want to perform another search?
// Importing utilities
import java.io.File;
import java.util.*;
public class FileListing
{
public static void main (String[] args)
{
// Creating a Scanner
Scanner keyboard = new Scanner(System.in);
// Specifying search location
File file = new File("D:/Music");
String[] content = file.list();
// Searching for a match
System.out.println("Enter the first few characters of the folder/file to do a lookup");
String userInput = keyboard.nextLine();
// Adding text to say what the user searched for
System.out.println("Below you will find the list of folders/files with a partial match to (" + userInput + ").");
System.out.println();
// Posting the contents
for(String folders : content)
{
if(folders.toUpperCase().startsWith(userInput.toUpperCase()))
{
System.out.println("Name: " + folders);
}
}
}
}
If you want to count your matches you can do the following
int i=0;
// Posting the contents
for(String folders : content)
{
if(folders.toUpperCase().startsWith(userInput.toUpperCase()))
{
System.out.println("Name: " + folders);
i++;
}
}
System.out.println("Total number of results: " + i);`
As for asking the user, consider using a do-while loop in the following format
do{
// your code
// ask user and read his answer on a string called userChoice
}while (userChoice.equals('y'))
Experiment with our suggestions and you will find the answer easily enough!
I would add a variable
int count = 0;
right before the for loop, and just increment it if it's a match.
This should get you started. I am incrementing the variable count each time a match is found. I am also looping forever so it keeps asking the user for more input.
// Importing utilities
import java.io.File;
import java.util.*;
public class FileListing
{
public static void main (String[] args)
{
// Creating a Scanner
Scanner keyboard = new Scanner(System.in);
// Specifying search location
File file = new File("D:/Music");
String[] content = file.list();
while(true){
// Searching for a match
System.out.println("Enter the first few characters of the folder/file to do a lookup");
String userInput = keyboard.nextLine();
// Adding text to say what the user searched for
System.out.println("Below you will find the list of folders/files with a partial match to (" + userInput + ").");
System.out.println();
// Posting the contents
int count=0;
for(String folders : content)
{
if(folders.toUpperCase().startsWith(userInput.toUpperCase()))
{
System.out.println("Name: " + folders);
count++;
}
}
}
}
}
Use a while loop and prompt the user to enter a phrase (such as 'exit') if they want to stop. After reading the user input, check the phrase and call a break if it matches the exit phrase.
Use a variable as Robert suggested to count the total number of files found.

I'm having problems with the .split() method using "," as the delimeter. Java

So for my current school project we have to read input from a file containing info on the periodic table of elements. Essentially I have to seperate bits of each line which has info on an element and put them into seperate string values.
Here the bit of code I'm having problems with.
for(int i=0;inputStream.hasNextLine();i++)
{
String line = inputStream.nextLine();
String[] info = line.split(",");
name=info[0];
atomicNumber=info[1];
symbol=info[2];
boilingPoint=info[3];
meltingPoint=info[4];
density=info[5];
molecularWeight=info[6];
elementInfo[i]= new Element(name,atomicNumber,symbol,boilingPoint,meltingPoint,density,molecularWeight);
It stores everything in the proper place except for the information for the density and the molecular Weight which i get null values for. I couldn't find any info why it isn't working for those last two Strings.
Example output:
Element Name: actinium
Atomic Number: 89
Symbol: Ac
Boiling Point: 3470
Melting Point: 1324
Density: null
Molecular Weight: null
Here's the constructor for the element object:
public Element(String name,String atomicNumber,String symbol, String boilingPoint, String meltingPoint, String density, String molecularWeight)
{
this.name=name;
this.atomicNumber=atomicNumber;
this.symbol=symbol;
this.boilingPoint=boilingPoint;
this.meltingPoint=meltingPoint;
this.density=density;
this.molecularWeight=molecularWeight;
}
You can try this,
// mean into file that info not exist, in that case take its default i.e. empty
info[5] == null ? "empty" : info[5];
info[6] == null ? "empty" : info[6];
Definitely the file you are reading contains 7 elements, else the following code will result in an error
density=info[5]; molecularWeight=info[6];
Example:
public static void main(String args[]) {
String line = "1,2,3,4,5,,";
String[] info = line.split(",");
System.out.println(info.length);
System.out.println(Arrays.deepToString(info));
}
The Output of the above snippet is 5 and [1, 2, 3, 4, 5]
Here we cannot use info[5] or info[6] as it will result in an error.
So your data is correct and you are capturing all the values.
I believe the problem is in printing the output, but you have not mentioned that code in your query to investigate deep.
Hope it helped.
String.split() never ever returns null (see here), which means the problem is not with split() method but, elsewhere. The split() method seem to return at least 7 chunks of data and this is because you are not getting ArrayIndexOutOfBoundException when you do this molecularWeight=info[6].
Then the problem is elsewhere and you can find out by reviewing your code and there must be something you are missing, something really really simple.
Let's assume you have the following input (2 elements):
actinium,89,Da,3470,1926,missing-x,missing-y
actinium,13,Gk,5480,1124,missing-z,missing-w
I used majority of your code, and developed a sample use cases to read the above two elements from file and store them in a list and print them back. I used List<Element> instead of your Element[] solution as well as overrided toString() in Element class to pretty-print the elements with Java 8's stream, see below and compare with your solution:
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class ReadFromFileElements {
public static void main(String... args) throws FileNotFoundException {
// You can use list instead of Element[] array
List<Element> elementInfo = new ArrayList<Element>();
//file containing the input
File file = new File("C:\\test_java\\elements.txt");
//open input stream to the file
Scanner input = new Scanner(file);
//as long as there is nextLine() keep looping
while(input.hasNextLine()) {
String line = input.nextLine();
String[] chunk = line.split(",");
Element e = new Element(chunk[0], chunk[1], chunk[2], chunk[3], chunk[4], chunk[5],
chunk[6]);
//add to the list of Element/s
elementInfo.add(e);
}
//close input stream
input.close();
//java 8 stream iterator through collection
elementInfo.stream().forEach((temp) -> {
//temp.toString() uses the overrided toString() of element class
System.out.println(temp.toString());
});
}
}
class Element {
String name;
String atomicNumber;
String symbol;
String boilingPoint;
String meltingPoint;
String density;
String molecularWeight;
public Element(String name, String atomicNumber, String symbol, String boilingPoint, String meltingPoint,
String density, String molecularWeight) {
this.name = name;
this.atomicNumber = atomicNumber;
this.symbol = symbol;
this.boilingPoint = boilingPoint;
this.meltingPoint = meltingPoint;
this.density = density;
this.molecularWeight = molecularWeight;
}
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("\n Element name: " + this.name);
builder.append("\n Atomic no: " + this.atomicNumber);
builder.append("\n Symobl : " + this.symbol);
builder.append("\n Boiling point : " + this.boilingPoint);
builder.append("\n Melting point : " + this.meltingPoint);
builder.append("\n Density : " + this.density);
builder.append("\n Molecular weight: " + this.molecularWeight);
return builder.toString();
}
}
And running the above code against the above two lines in the file, I get the following input:
Element name: actinium
Atomic no: 89
Symobl : Da
Boiling point : 3470
Melting point : 1926
Density : missing-x
Molecular weight: missing-y
Element name: actinium
Atomic no: 13
Symobl : Gk
Boiling point : 5480
Melting point : 1124
Density : missing-z
Molecular weight: missing-w
Use this
public static void readFileData(String filename) throws FileNotFoundException{
ArrayList<Element> list = new arrayList<>();
String split = ","; //split with comma
Scanner in = new Scanner(new File(filename));
String wordIn;
Element elem = new Element();
while (in.hasNextLine()) {
wordIn = in.nextLine();
String splitter[] = wordIn.split(split);
String name = splitter[0];
int atomicNumber = Integer.parseInt(splitter[1]);
String symbol = splitter[2];
String boilingPoint = splitter[3];
String meltingPoint = splitter[4];
String density = splitter[5];
String molecularWeight = splitter[6]
elem.setName(name);
elem.setAtomicNumber(atomicNumber);
elem.setSymbol(symbol);
elem.setBoilingPoint(boilingPoint);
elem.setMeltingPoint(meltingPoint);
elem.setDensity(density);
elem.setMolecularWeight(molecularWeight);
list.add(elem);
}
for(Element el : list){
sout(el.toString()) // if you have a to string method
}
}
public static void main(String [] args){
Scanner sc = new Scanner(System.in);
String file = sc.next();
readFileData(file);
}
Make sure you have those setters in your Element class. And a too String method would be handy but not necessary. If the variable is type int in your Element class the you can do Integer.parseInt() or Double.parseDouble which converts string to integer or float etc. sout is short for System.out.println(); type sout + tab and you get the full thing.

Replacing a particular word in a scanned in string and concatenating using substring() in Java

I'm brand new to all of this so I am trying to write a simple bit of code that allows the user to type in text (saved as a string) and then have the code search for the position of a word, replace it and join the string back together. I.e.:
'I like foo for lunch'
foo is found at position 7
The new input is: I like Foo for lunch
Here is what I have thus far:
import java.util.Scanner;
public class FooExample
{
public static void main(String[] args)
{
/** Create a scanner to read the input from the keyboard */
Scanner sc = new Scanner (System.in);
System.out.println("Enter a line of text with foo: ");
String input = sc.nextLine();
System.out.println();
System.out.println("The string read is: " + input);
/** Use indexOf() to position of 'foo' */
int position = input.indexOf("foo");
System.out.println("Found \'foo\' at pos: " + position);
/** Replace 'foo' with 'Foo' and print the string */
input = input.substring(0, position) + "Foo";
System.out.println("The new sentence is: " + input);
The problem is occurring at the end -- where I am stumped on how to tack the rest of the sentence on to the concatenation:
input = input.substring(0, position) + "Foo";
I can get the word to be replaced but I am scratching my head over how to get the rest of the string attached on.
input = input.substring(0,position) + "Foo" + input.substring(position+3 , input.length());
or simply you can use replace method.
input = input.replace("foo", "Foo");
Slight update to what Achintya posted, to take into account you don't want to include "foo" again:
input = input.substring(0, position) + "Foo" + input.substring(position + 3 , input.length());
This may be overkill, but if you are looking for words in sentences, you could easily use StringTokenizer
StringTokenizer st = new StringTokenizer(input);
String output="";
String temp = "";
while (st.hasMoreElements()) {
temp = st.nextElement();
if(temp.equals("foo"))
output+=" "+"Foo";
else
output +=" "+temp;
}

Java: 2 runtime errors I can't figure out

I am working on a homework assignment, and I am going a little "above and beyond" what is called for by the assignment. I am getting a run-time error in my code, and can not for the life of me figure out what it is that I have done wrong.
Here is the assignment:
Write a program that displays a simulated paycheck. The program should ask the user to enter the date, the payee’s name, and the amount of the check. It should then display a simulated check with the dollar amount spelled out.
Here is my code:
CheckWriter:
/* CheckWriter.java */
// Imported Dependencies
import java.util.InputMismatchException;
import java.util.Scanner;
public class CheckWriter {
public static void main(String args[]) {
Scanner keyboard = new Scanner(System.in);
// Try to get the name
String name = "";
NameValidator validateName = new NameValidator();
while (validateName.validate(name) == false) {
System.out.println("Enter the name: ");
name = keyboard.nextLine();
if (validateName.validate(name) == false) {
System.out.println("Not a valid name.");
}
}
// Get the date
String date = "";
DateValidator validateDate = new DateValidator();
while (!validateDate.validate(date)) {
System.out.println("Enter the date (dd/mm/yyyy): ");
date = keyboard.nextLine();
if (!validateDate.validate(date)) {
System.out.println("Not a valid date.");
}
}
// Try to get the amount of the check
String checkAmount = "";
CurrencyValidator validateCurrency = new CurrencyValidator();
while (!validateCurrency.validate(checkAmount)) {
System.out.print("Enter the Check Amount (XX.XX): $");
checkAmount = keyboard.nextLine();
if (!validateCurrency.validate(checkAmount)) {
System.out.println("Not a valid check amount.");
}
}
String checkWords = checkToWords(checkAmount); // ERROR! (48)
System.out
.println("------------------------------------------------------\n"
+ "Date: "
+ date
+ "\n"
+ "Pay to the Order of: "
+ name
+ " $"
+ checkAmount
+ "\n"
+ checkWords
+ "\n"
+ "------------------------------------------------------\n");
}
private static String checkToWords(String checkAmount) {
/**
* Here I will use the string.split() method to separate out
* the integer and decimal portions of the checkAmount.
*/
String delimiter = "\\.\\$";
/* Remove any commas from checkAmount */
checkAmount.replace(",", "");
/* Split the checkAmount string into an array */
String[] splitAmount = checkAmount.split(delimiter);
/* Convert the integer portion of checkAmount to words */
NumberToWords intToWord = new NumberToWords();
long intPortion = Long.parseLong(splitAmount[0]); // ERROR! (84)
intToWord.convert(intPortion);
String intAmount = intToWord.getString() + " dollars";
/* Convert the decimal portion of checkAmount to words */
String decAmount = "";
long decPortion = Long.parseLong(splitAmount[1]);
if (decPortion != 0) {
NumberToWords decToWord = new NumberToWords();
decToWord.convert(Long.parseLong(splitAmount[1]));
decAmount = " and " + decToWord.getString() + " cents.";
}
return (intAmount + decAmount);
}
}
Note that I am using external class files to handle validation of the name, date, currency, and conversion from numbers to words. These class files all work as intended.
The error I am getting is:
Exception in thread "main" java.lang.NumberFormatException: For input string: ""
at java.lang.NumberFormatException.forInputString(Unknown Source)
at java.lang.Long.parseLong(Unknown Source)
at java.lang.Long.parseLong(Unknown Source)
at CheckWriter.checkToWords(CheckWriter.java:82)
at CheckWriter.main(CheckWriter.java:46)
I have commented the lines in my code that are causing the errors that I am experiencing.
Could someone please assist me in figuring where my code is going wrong? I can include the other class files if you feel that it would be needed.
EDIT: When I run the code, it asks for the name and date. Before asking for the check amount is when it throws the error.
EDIT 2: A huge thank you to cotton.m! Thanks to his advice, I have changed the while statements to look like this:
while(!validateDate.validate(date) && date == "")
This has now fixed my issue. It would appear that when validating data with a regex expression, an empty string will return true.
The String you are trying to parse in an empty length string.
My suggestion would be to
1) Check the value of checkAmount at the start of checkToWords - if it is blank there's your problem
2) Don't do that split. Just replace the $ like you did the , (I think this is your real problem)
Also you are going to have another issue in that 10000.00 is not a long. I see you are splitting out the . but is that really what you want?
It is NumberFormatException, the value in checkAmount (method parameter) is not a valid Number.
You need to set checkAmount=checkAmount.replace(",", "");
Otherwise checkAmount will still have , inside and causes NumberFormatExcpetion.
Your issue is with your delimiter regex, currently you are using \.\$ which will split on a literal . followed by a literal $. I'm assuming that what you are actually intending to do is to split on either a . or a $, so change your delimiter to one of the following:
String delimiter = "\\.|\\$"
or
String delimiter = "[\\.\\$]"
As your code is now, checkAmount.split(delimiter) is not actually successfully splitting the string anywhere, so Long.parseLong(splitAmount[0]) is equivalent to Long.parseLong(checkAmount).
It should be:
String delimiter = "[\\.\\$]";
and then you have to check that splitWord[i] is not empty.

Categories