I'm currently trying to write a Java assignment that is supposed to, in order;
Read each line of a prewritten text file
Turn each line into a string
Turn each part of each line into its own individual string/int/double
Assign those variables in an object (Which is part of an array of objects) of a class which I have also created as part of this assignment
Print each variable of the object using one of the class' methods
However, I am repeatedly running into a runtime problem where I am getting this error message;
Exception in thread "main" java.util.NoSuchElementException
at java.util.Scanner.throwFor(Scanner.java:862)
at java.util.Scanner.next(Scanner.java:1371)
at Lab2.main(Lab2.java:27)
This leads me to believe I am probably reading the text file wrong. However, no matter what I do I can't seem to get it to read correctly. It's supposed to read a first name, a last name, three separate components of an address (which it concatenates into one string), a city, a state, a zip code (as an integer), a phone number (as a string) and a dollar amount (as a double).
I believe that the problem might arise from the city names, as some of them have a space between them. I thought I had solved this by setting the delimiter of the Scanner that reads each individual string to a tab (which is what every other element is separated by) but this has either not worked (And is thus trying to turn state names into an integer via the Integer.parseInt() static method) or is not the problem. As I said, I am out of ideas and would be greatly appreciative towards anyone who could help me out here!
I will list the code below. First here is the main file;
public class Lab2
{
public static void main(String[] args) throws IOException
{ String FirstName, LastName, Address1, Address2, Address3, AddressFull, City, State, Phone, ZipString, DonString, line = "blank";
int Zip;
double Donation;
Scanner fileScan = new Scanner(new File("Lab2.txt")), lineScan = new Scanner(line);
lineScan.useDelimiter("\t");
PersonStats[] Donators = new PersonStats[25];
for (int i = 0; i < Donators.length; i++)
{ line = fileScan.nextLine();
FirstName = lineScan.next();
LastName = lineScan.next();
Address1 = lineScan.next();
Address2 = lineScan.next();
Address3 = lineScan.next();
AddressFull = Address1 + " " + Address2 + " " + Address3;
City = lineScan.next();
State = lineScan.next();
ZipString = lineScan.next();
Zip = Integer.parseInt(ZipString);
Phone = lineScan.next();
DonString = lineScan.next();
Donation = Double.parseDouble(DonString);
Donators[i] = new PersonStats(FirstName, LastName, AddressFull, City, State, Zip, Phone, Donation);
Donators[i].PrintOut();
}
}
}
Next, the class file I've written up for the assignment;
public class PersonStats
{ private String FirstName, LastName, Address, City, State, Phone;
private int Zip;
private double Donation;
public PersonStats(String first, String last, String area, String town, String feifdom, int postcode, String telegraph, double given)
{ FirstName = first;
LastName = last;
Address = area;
City = town;
State = feifdom;
Zip = postcode;
Phone = telegraph;
Donation = given;
}
public void PrintOut()
{ System.out.println(FirstName + " " + LastName);
System.out.println(Address);
System.out.println(City + ", " + State + " " + Zip + "\n");
System.out.println(Phone + " " + Donation);
}
}
And then finally the text file the program is supposed to be reading from (Might be a little bit difficult to read, just remember each space except for the ones in city names is actually a tab);
Rick James 8276 Carlos Ave Las Vegas NV 87126 5553451567 23.95
John Gibson 9127 Oak Dr Corvallis OR 97330 5552812313 156.78
Ron Wills 1155 Ivy Pl Atlantic Ga 37339 5552123145 189.56
Rita Jones 1259 Chase Ave Las Vegas NV 87126 5554445671 2145.60
Jason Knight 7154 Pine Dr Gresjam OR 97380 5558124545 3157.44
Clara Swanson 1944 Main Pl Springfield OR 97339 5552123144 212.99
Robert Peck 1866 First Ave Las Vegas NV 87126 5553455425 250.00
Dora Garcia 2179 Fir Dr Corvallis OR 97330 5552812919 350.00
Peter Keck 1465 Circle Pl Gold Beach OR 97339 5552123256 2150.00
Stuart Smith 2387 Sweek Ave Las Vegas NV 87126 5553455489 650.99
Tyler Wild 1313 Spooky Ln Corvallis OR 97330 5552813213 587.45
Laretta Peters 2224 Chase Pl Monmouth OR 97361 5552124465 123.45
Kristi Emry 3465 Cerrito Ave Las Vegas NV 87126 5553455567 3212.65
Kelli Gard 1894 Elm Dr Corvallis OR 97330 5552816678 51.00
Jacob Andrews 8159 Rose Ct Mill City OR 97322 5552127879 64.00
Ryan Perkins 7546 Prince Ave Las Vegas NV 87126 5553451989 13.00
Joshua Gilbert 9278 Monroe Dr Corvallis OR 97330 5552832656 95.00
Miles Crain 4578 Chester Dr Corvallis OR 97331 5552345678 1544.00
Butch Cassidy 5498 Sutton Pl Gresham OR 97380 5416565797 1798.56
Perry Winkle 8185 Shaver Ave Las Vegas NV 87126 5553812346 195.66
Loni Day 4598 Holmen Dr Corvallis OR 97330 5555289741 1878.50
Nikita Benson 1787 Grant Pl Portland OR 97321 5553569898 1500.00
Rusty Krouger 8829 Simeon Ave Las Vegas NV 87126 5555677847 2100.00
Wally Wallace 2898 Wilson Blvd Jackson Center OH 23466 5552222222 2222.22
Joe Jones 1212 Water St Millersburg OR 97366 5555555555 55.55
Again, thanks in advance if there's anyone out there who can help me with this, your advice might save a life!... or at least the score of this lab :S
here is a tip: When using Scanner use the hasNextXXX method before invoking next methods to check if elements exists
https://docs.oracle.com/javase/7/docs/api/java/util/Scanner.html
No Such Element Exception?
Okay, here it is
import java.io.IOException;
import java.io.*;
import java.util.Scanner;
public class Lab2
{
public static void main(String[] args) throws IOException
{ String FirstName, LastName, Address1, Address2, Address3, AddressFull, City, State, Phone, ZipString, DonString, line = "blank";
int Zip;
double Donation;
Scanner fileScan = new Scanner(new File("F:/test.txt")).useDelimiter("\n");
PersonStats[] Donators = new PersonStats[5];
String tempVal="";
int i = 0;
while(fileScan.hasNext())
{
tempVal = fileScan.next(); //Storing person records one at a time in the string line by line
String tempArr[] = tempVal.split("\t"); //Splitting each person record string by tab and storing it in a String array
FirstName = tempArr[0];
LastName = tempArr[1];
Address1 = tempArr[2];
Address2 = tempArr[3];
Address3 = tempArr[4];
AddressFull = Address1 + " " + Address2 + " " + Address3;
City = tempArr[5];
State = tempArr[6];
ZipString = tempArr[7];
Zip = Integer.parseInt(ZipString);
Phone = tempArr[8];
DonString = tempArr[9];
Donation = Double.parseDouble(DonString);
Donators[i] = new PersonStats(FirstName, LastName, AddressFull, City, State, Zip, Phone, Donation);
Donators[i].PrintOut();
i++;
}
}
}
First of all, I would like to point out that your variable names should start with lower case. I did not edit them in the code since they were used in many places. Make an habit to declare String firstName instead of String FirstName
To the code, in your code you had used a "\t" delimter which I replaced with "\n" since in the text file each line holds entire Person details. You could have used "\t" if the donation of the first person and first name of the second person were separated by the same, but they are separated by "\n"
So now Scanner fileScan will read the file line by line which I will store in String tempVal and while(fileScan.hasNext()) assures that the Scanner will keep reading only as long as there are lines to be read.
Now, every line has different information separated by "\t". So I used tempVal.split("\t") to separate them. Also, used a counter int i and removed the for loop. I guess rest of the code is pretty basic and not much different from yours.
**EDIT****
Here is the output
Rick James
8276 Carlos Ave
Las Vegas, NV 87126
5553451567 23.95
John Gibson
9127 Oak Dr
Corvallis, OR 97330
5552812313 156.78
Ron Wills
1155 Ivy Pl
Atlantic, Ga 37339
5552123145 189.56
Rita Jones
1259 Chase Ave
Las Vegas, NV 87126
5554445671 2145.6
Jason Knight
7154 Pine Dr
Gresjam, OR 97380
5558124545 3157.44
And here is the sample text.file that I used.
Rick James 8276 Carlos Ave Las Vegas NV 87126 5553451567 23.95
John Gibson 9127 Oak Dr Corvallis OR 97330 5552812313 156.78
Ron Wills 1155 Ivy Pl Atlantic Ga 37339 5552123145 189.56
Rita Jones 1259 Chase Ave Las Vegas NV 87126 5554445671 2145.60
Jason Knight 7154 Pine Dr Gresjam OR 97380 5558124545 3157.44
Scanner fileScan = new Scanner(new File("Lab2.txt"));
//PersonStats[] Donators = new PersonStats[25];
while(fileScan.hasNext()) {
line = fileScan.nextLine();
String parts[] = line.split("\t");
if(parts.length == 10) {
FirstName = parts[0];
...
}
There are some problems in addion.
First: String ist immutable. So your lineScanner will created with an empty String. If you later change this string, nothing appens for this scanner, because you create a new string with this step.
Second you have to check for an next element. (see my while loop)
To parse your data it is easyer to split the string in parts and use this to fill your Class. But if you want to use the Scanner class, you have to create on instance per line in your file.(in the while loop)
Related
I read a txt with data in the following format: Name Address Hobbies
Example(Bob Smith ABC Street Swimming)
and Assigned it into String z
Then I used z.split to separate each field using " " as the delimiter(space) but it separated Bob Smith into two different strings while it should be as one field, same with the address. Is there a method I can use to get it in the particular format I want?
P.S Apologies if I explained it vaguely, English isn't my first language.
String z;
try {
BufferedReader br = new BufferedReader(new FileReader("desc.txt"));
z = br.readLine();
} catch(IOException io) {
io.printStackTrace();
}
String[] temp = z.split(" ");
If the format of name and address parts is fixed to consist of two parts, you could just join them:
String z = ""; // z must be initialized
// use try-with-resources to ensure the reader is closed properly
try (BufferedReader br = new BufferedReader(new FileReader("desc.txt"))) {
z = br.readLine();
} catch(IOException io) {
io.printStackTrace();
}
String[] temp = z.split(" ");
String name = String.join(" ", temp[0], temp[1]);
String address = String.join(" ", temp[2], temp[3]);
String hobby = temp[4];
Another option could be to create a format string as a regular expression and use it to parse the input line using named groups (?<group_name>capturing text):
// use named groups to define parts of the line
Pattern format = Pattern.compile("(?<name>\\w+\\s\\w+)\\s(?<address>\\w+\\s\\w+)\\s(?<hobby>\\w+)");
Matcher match = format.matcher(z);
if (match.matches()) {
String name = match.group("name");
String address = match.group("address");
String hobby = match.group("hobby");
System.out.printf("Input line matched: name=%s address=%s hobby=%s%n", name, address, hobby);
} else {
System.out.println("Input line not matching: " + z);
}
I can think of three solutions.
In order from best to worst:
Different delimiter
Enforce the format to always have two names, two address parts and one hobby
Have a dictionary with names and hobbies, check each word to determine which type it is and then group them together as needed.
(The 3rd option is not meant as a serious alternative.)
As others have mentioned, using spaces as both field delimiter and inside fields is problematic. You could use a regex pattern to split the line (paste (\w+ \w+) (\w+ \w+) (.+) in Regex101 for an explanation):
Pattern pattern = Pattern.compile("(\\w+ \\w+) (\\w+ \\w+) (.+)");
Matcher matcher = pattern.matcher("Bob Smith ABC Street Bowling Fishing Rollerblading");
System.out.println("matcher.matches() = " + matcher.matches());
for (int i = 0; i <= matcher.groupCount(); i++) {
System.out.println("matcher.group(" + i + ") = " + matcher.group(i));
}
This would give the following output:
matcher.matches() = true
matcher.group(0) = Bob Smith ABC Street Bowling Fishing Rollerblading
matcher.group(1) = Bob Smith
matcher.group(2) = ABC Street
matcher.group(3) = Bowling Fishing Rollerblading
However this only works for this exact format. If you get a line with three name parts for example:
John B Smith ABC Street Swimming
This will get split into John B as the name, Smith ABC as the address and Street Swimming as hobbies.
So either make 100% sure your input will always match this format or use a different delimiter.
The split() method majorly works on the 2 things:
Delimiter and
The String Object
Sometimes on limit too.
Whatever limit you will provide, the split() method will do its work according to that.
It doesn't understand whether the left substring is a name or not, same as for the right substring.
Have a look at this code snippet:
String assets = "Gold:Stocks:Fixed Income:Commodity:Interest Rates";
String[] splits = assets.split(":");
System.out.println("splits.size: " + splits.length);
for(String asset: splits){
System.out.println(assets);
}
OutPut
splits.size: 5
Gold
Stocks
Fixed Income // with space
Commodity
Interest Rates // with space
The output came with spaces because I provided the ; as a delimiter.
This probably helped you to get your answer.
Find Detailed Information on Split():
Top 5 Use cases of Split()
Java Docs : Split()
It depends on the data you're dealing with. Will the name always consist of a first and last name? Then you can simply combine the first two elements from the resulting array into a new string.
Otherwise, you might have to find a different way to separate out the different pieces within the txt file. Possibly a comma? Some character that you know won't ever be used in your normal data.
Assuming that every line follows the format
Bob Smith ABC Street Swimming
ie, name surname.... this code can manually manipulate the data for you:
String[] temp = z.split(" ");
String[] temp2 = new String[temp.length - 1];
temp2[0] = temp[0] + " " + temp[1];
for (int i = 2; i < temp.length; i++) {
temp2[i] = temp2[i];
}
temp = temp2;
I'm new to parsing (and new to Java), so I just want to be sure I'm conceptualizing this correctly.
I've written a program that allows the user to paste text into a text field, then click the "parse data" button. This button parses the text for two pieces of data: a name and a number.
The text data is generally pasted by the user in this form:
john 48915
beth 10431
frank 10112
anne 34887
taserface 90090
bill 56448
I'm using the regular expression "^\d+\t.*\d+$" to detect the pattern, and after the pattern is confirmed, my parse data code does the following:
Scanner parser = new Scanner(inputText);
parser.useDelimiter("\\n");
while (parser.hasNext()) {
String nextToken = parser.next();
String name = nextToken.trim();
// how do I get the number?
You'll notice the \n delimiter, which parses data at the new line character. This breaks the data up into rows, but does not break each row into two separate data points. I need to grab both the name and the number separately.
I believe I should be using a space delimiter, but I'm not sure if I should be doing this in one or two different steps. The confusion, I believe, stems from my limited understanding of how the Scanner does its work. But after a review of the Java documentation, I'm still not really sure.
Current output:
john 48915
beth 10431
frank 10112
etc.
Expected output:
john
48915
beth
10431
etc.
Should I be doing two different loops of parsing, or can I get the work done in the same pass?
Your problem is that you are usimg \n as delimiter.
This leads to the behavior that the input you are passing to your scanner is only delimited at linebreaks and not as you are expecting also at whitespaces.
One solution would that would work is to simply delete the following line: parser.useDelimiter("\\n");
A solution that would also work is the following:
try (Scanner parser = new Scanner(inputText)) {
while (parser.hasNextLine()) {
String nextLine = parser.nextLine();
String[] strings = nextLine.split("\\s");
// Here you can use any pattern to split the line
String name = strings[0];
String number = strings[1];
System.out.printf("%s%n%s%n", name, number);
}
}
This leads to the following output:
john
48915
beth
10431
frank
10112
anne
34887
taserface
90090
bill
56448
The solution gives you some more controll over the lines and how to parse the name and number.
Here is an example implementation for your case, which offers more control and flexibility to accommodate change of delimiters -
import java.util.Arrays;
public class StringSplitExample {
public static void main(String []args){
String content = "john 48915\n"
+ "beth 10431\n"
+ "frank 10112\n"
+ "anne 34887\n"
+ "taserface 90090\n"
+ "bill 56448";
String[] dataset = content.split("\\n|\\s");
for (String value : dataset) {
System.out.println(value);
}
}
}
And, following is the output for the above code snippet -
john
48915
beth
10431
frank
10112
anne
34887
taserface
90090
bill
56448
You can achieve this functionality with String spilt method, below is same program and output as you desire.
I think without space user can not go next line while filling form.
public class ParseLineText {
public static void main(String[] args) {
String textData = "john 48915 " +
"beth 10431 " +
"frank 10112 " +
"anne 34887 " +
"taserface 90090 " +
"bill 56448 ";
String[] data = textData.split("\\s");
for (String text : data) {
System.out.println(text);
}
}
}
Output:
john
48915
beth
10431
frank
10112
anne
34887
taserface
90090
bill
56448
Assuming there is a file:
Virginia Tyler Taylor Wilson
Ohio Grant Hayes Garfield Harrison_B McKinley Taft Harding
Massachusetts Kennedy Bush_GHW
New_York VanBuren Fillmore Roosevelt_T Roosevelt_F
I need to sort it in order, and below is my code:
TreeMap<String, String> map = new TreeMap<String, String>();
while (infile1.ready()){
String line = infile1.readLine();
String s = line.substring(0, line.indexOf(" "));
String p = line.substring(line.indexOf(" "));
map.put(s, p);
}
for (String p : map.keySet()){
System.out.println(p + " " + map.get(p));
}
My output is:
Massachusetts Kennedy Bush_GHW
New_York VanBuren Fillmore Roosevelt_T Roosevelt_F
Ohio Grant Hayes Garfield Harrison_B McKinley Taft Harding
Virginia Tyler Taylor Wilson
The expected output is:
Massachusetts **Bush_GHW Kennedy**
New_York **Fillmore Roosevelt_F Roosevelt_T VanBuren**
Ohio **Garfield Grant Harding Harrison_B Hayes McKinley Taft**
Virginia **Taylor Tyler Wilson**
The only difference is the order in the value, where I bold it in the expected output.
Is there a fast way to sort String p and puts it into the map?
you can write in short way
Arrays.sort(line.substring(line.indexOf(" ")).split(" "));
try this
String[] ps = line.substring(line.indexOf(" ")).split(" ");
Arrays.sort(ps);
then try combine ps to p with " ";
Massachusetts **Bush_GHW Kennedy**
New_York **Fillmore Roosevelt_F Roosevelt_T VanBuren**
Ohio **Garfield Grant Harding Harrison_B Hayes McKinley Taft**
Virginia **Taylor Tyler Wilson**
In your above expected output how Bush Comes after mass..
So please explore output correctly.
So , im having a piece of trouble here , tried with tutorials to fix it but nothing really helped me out saw something about printout string 0,1 etc but didnt work eather.
What the program does atm : Asks user for first/last name and prints it out first +last name
what i want it to do is print out the intisials of the users first and last name, any ideas how to fix this? Please help , Thanks in advance!
My code looks like this atm
package com.example.sträng.main;
import java.util.Scanner;
public class Application {
public static void main(String[] args) {
String firstName,
lastName;
//Create scanner to obtain user input
Scanner scanner1 = new Scanner( System.in );
//obtain user input
System.out.print("Enter your first name: ");
firstName = scanner1.nextLine();
System.out.print("Enter your last name: ");
lastName = scanner1.nextLine();
//output information
System.out.print("Your first name is " + firstName + " and your last name is "+ lastName);
}
}
You get the 21st character from a String using String.charAt(21).
How to get the initials, I leave as an excercise for you.
Please note, that char is a strange datatype in Java. It represents a character, but works like a number, that's why you get a strange number if you "concatenate" two chars. If you want to create a String out of chars, you have some options, such as:
char c1;
char c2;
String str = "" + c1 + c2;
or
char c1;
char c2;
String str = new String(new char[] {c1, c2});
String firstInitial = firstName.substring(0,1);
String secondInitial = lastName.substring(0,1);
I deal with a file problem.
IBM 7918 Ayse Durlanik 7600 Computer
------------------------------------
Gama 2342 Mehmet Guzel 8300 Civil
------------------------------------
Lafarge 3242 Ahmet Bilir 4700 Chemical
------------------------------------
Intel 3255 Serhan Atmaca 9200 Electrical
------------------------------------
Bilkent 3452 Fatma Guler 2500 Computer
------------------------------------
Public 1020 Aysen Durmaz 1500 Mechanical
------------------------------------
Havelsan 2454 Sule Dilbaz 2800 Electrical
------------------------------------
Tai 3473 Fethi Oktam 3600 Computer
------------------------------------
Nurol 4973 Ayhan Ak 4100 Civil
------------------------------------
Pfizer 3000 Fusun Ot 2650 Chemical
------------------------------------
This is the text file and I don't want to read this =
"------------------------------------ "
Here is the method:
Scanner scn = null;
File fp = new File("C:/Users/Efe/Desktop/engineers.txt");
try {
scn = new Scanner(fp);
while (scn.hasNextLine()) {
{
if (!scn.next().equals("------------------------------------")) {
String comp = scn.next();
int id = Integer.parseInt(scn.next());
String name = scn.next();
String surname = scn.next();
double sal = Double.parseDouble(scn.next());
String area = scn.next();
Engineer e = new Engineer(comp, id, name, surname, sal, area);
list.add(e);
}
}
scn.close();
}
This is the code where I get an exception at run-time:
Exception in thread "AWT-EventQueue-0" java.lang.NumberFormatException:
For input string: "Ayse" at
java.lang.NumberFormatException.forInputString(NumberFormatException.java:48)
What is wrong with the code?
You're off by one...in the line
if (!scn.next().equals("------------------------------------")) {
if the next token is not the dashed line, then it is lost. Consider assigning it to a temporary variable.
In your case, "IBM" is lost, comp == 7918, and parseInt is called with an argument of "Ayse", leading to the runtime exception.
This is when application trying to convert string to one of the numeric types, but that string does have the appropriate format to convert.
Can you show further "IBM 7918 Ayse Durlanik 7600 Computer"