Parser using Scanner not working for "#" sign - java

Im trying to parse an input file as follows:
#*Nonmonotonic logic - context-dependent reasoning.
##Victor W. Marek,Miroslaw Truszczynski
#t1993
#cArtificial Intelligence
#index3003478
#%3005567
#%3005568
#%3005569
#!abstracst
#*Wissensrepräsentation und Inferenz - eine grundlegende Einführung.
##Wolfgang Bibel,Steffen Hölldobler,Torsten Schaub
#t1993
#cArtificial Intelligence
#index3005557
#%3005567
#!abstracts2
Im creating the parser for this file and Im looking for an output as follows:
Title: Nonmonotonic logic - context-dependent reasoning.
Author: Victor W. Marek,Miroslaw Truszczynski
Year: 1993
Domain: Artificial Intelligence
Index: 3003478
Citation: 3005567
Citation: 3005568
Citation: 3005569
Abstract: Abstract
Title: Wissensrepräsentation und Inferenz - eine grundlegende Einführung.
Author: Wolfgang Bibel,Steffen Hölldobler,Torsten Schaub
Year: 1993
Domain: Artificial Intelligence
Index: 3005557
Citation: 3005567
Abstract: Abstract2
The code that I create so far is below but it produced a totally different output that what I expected and I could not figure out why the scanner reads it the wrong way. It seems to only read the first character of each line as title, not the first line of every part.
Im thinking that maybe the scanner would not read the "#" sign but I guess I might be wrong as well. To make it clear whats wrong, for example, if I only wanna print out the title, the output I got is
Title:*
Title:#
Title:t
Title:c
Title:i
Title:%
Title:!
Title:
Title:*
Title:#
Title:t
Title:c
Title:i
Title:i
Title:%
Title:!
Title:
Done.
And if I tried to print out title and author the output I got is as follows:
Title:*
Author:Nonmonotonic logic - context-dependent reasoning.
Title:#
Author:Victor W. Marek,Miroslaw Truszczynski
Title:t
Author:1993
Title:c
Author:Artificial Intelligence
Title:i
Author:ndex3003478
Title:%
Author:
Title:!
Title:
Author:
Title:*
Author:Wissensrepr?sentation und Inferenz - eine grundlegende Einf?hrung.
Title:#
Author:Wolfgang Bibel,Steffen H?lldobler,Torsten Schaub
Title:t
Author:1993
Title:c
Author:Artificial Intelligence
Title:i
Author:ndex3005557
Title:i
Author:ndex3005557
Title:%
Author:
Title:!
Title:
Author:
Done.
The code is as follows:
import java.sql.*;
import java.util.Scanner;
import java.io.*;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.nio.file.Paths;
public class Citation{
public static void main (String[] args) throws SQLException,
ClassNotFoundException, IOException{
Citation parser = new Citation("D:/test.txt");
parser.processLineByLine();
log("Done.");
}
public Citation(String aFileName){
fFilePath = Paths.get(aFileName);
}
public final void processLineByLine() throws IOException {
try (Scanner scanner = new Scanner(fFilePath, ENCODING.name())){
while (scanner.hasNextLine()){
processLine(scanner.nextLine());
}
}
}
protected void processLine(String aLine){
Scanner scanner = new Scanner(aLine);
scanner.useDelimiter("\n");
while(scanner.hasNext()){
// Scanner scanner = new Scanner(aLine);
scanner.useDelimiter("#*");
if(scanner.hasNext()){
String title = scanner.next();
System.out.println("Title:" + title);
}
// Scanner scanner3 = new Scanner(aLine);
scanner.useDelimiter("##");
if(scanner.hasNext()){
String author = scanner.next();
// System.out.println(author);
}
// Scanner scanner4 = new Scanner(aLine);
scanner.useDelimiter("#t");
if(scanner.hasNext()){
String year = scanner.next();
// System.out.println(year);
}
// Scanner scanner5 = new Scanner(aLine);
scanner.useDelimiter("#c");
if(scanner.hasNext()){
String domain = scanner.next();
// System.out.println(domain);
}
// Scanner scanner6 = new Scanner(aLine);
scanner.useDelimiter("#index");
if(scanner.hasNext()){
String index = scanner.next();
// System.out.println(index);
}
// Scanner scanner7 = new Scanner(aLine);
scanner.useDelimiter("#%");
if(scanner.hasNext()){
String cite = scanner.next();
// System.out.println(cite);
}
// Scanner scanner8 = new Scanner(aLine);
scanner.useDelimiter("#!");
if(scanner.hasNext()){
String abstracts = scanner.next();
// System.out.println(abstracts);
}
}
}
// PRIVATE
private final Path fFilePath;
private final static Charset ENCODING = StandardCharsets.UTF_8;
private static void log(Object aObject){
System.out.println(String.valueOf(aObject));
}
}
When I changed the "#*" delimiter as "#//*" delimiter, the title read, but then every line is read as titles as well. It does not detect my other delimiters. The output I got is as follows:
Title:Nonmonotonic logic - context-dependent reasoning.
Title:##Victor W. Marek,Miroslaw Truszczynski
Title:#t1993
Title:#cArtificial Intelligence
Title:#index3003478
Title:#%
Title:#!
Title:
Title:Wissensrepr?sentation und Inferenz - eine grundlegende Einf?hrung.
Title:##Wolfgang Bibel,Steffen H?lldobler,Torsten Schaub
Title:#t1993
Title:#cArtificial Intelligence
Title:#index3005557
Title:#index3005557
Title:#%
Title:#!
Title:

Assuming the file format isn't changing soon, modify as below
protected void processLine(String aLine) {
if (aLine.trim().equals("")) {
System.out.println();//executed when an empty line is read
}
else if (aLine.startsWith("#*")) {
System.out.println("Title:" + aLine.substring(2)); //or, you can also do
//System.out.println("Title:" + aLine.substring("#*".length()));
} else if (aLine.startsWith("otherCases") {
//proceed for other cases in similar fashion.
}
.
.
.
}

The problem is that you are using scanner.useDelimiter("#*");. This method requires a regular expression, where * symbol means zero ore more occurencies of symbol(in your case #). So, use scanner.useDelimiter("#\\*"); in your case.

Related

Could I get some help understating what is causing my "NoSuchElementException"?

I am currently going through the Helsinki MOOC for Java OOP and I have hit a snag on one of the questions. I am working on Week 7 Exercise 8 and when I run my code manually I am getting everything to work out okay. However when I run their automated tests I am getting the "NoSuchElementException" error.
It is my understanding from the JavaDoc on this particular error that it is most likely caused by .nextLine() not finding a line to read. What confuses me though is based on the error message, and the location of the exceptions, my use of .nextLine() is working in some places and not others while I am using it in the same manner. I included my class that I am using below. Thanks for the help everyone, and if I overlooked a previous post similar to this I apologize.
import java.util.Scanner;
import java.util.ArrayList;
public class AirportPanel {
private Scanner reader;
private ArrayList<Airplane> airplanes;
private ArrayList<Flight> flights;
public AirportPanel(Scanner reader){
this.reader = reader;
this.airplanes = new ArrayList<Airplane>();
this.flights = new ArrayList<Flight>();
}
public void start(){
System.out.println("Airport panel");
System.out.println("--------------------\n");
while(true){
printMenu();
String input = readString();
if(input.toLowerCase().equals("x")){
break;
}else{
chooseOperation(input);
}
}
}
private void printMenu(){
System.out.println("Choose operation:");
System.out.println("[1] Add airplane" + "\n[2] Add flight" + "\n[x] Exit");
System.out.print("> ");
}
private void chooseOperation(String input){
if(input.equals("1")){
addPlane();
}else{
addFlight();
}
}
private void addPlane(){
System.out.print("Give plane ID: ");
String planeID = readString();
System.out.print("Give plane capacity: ");
String planeCap = readString();
this.airplanes.add(new Airplane(planeID, planeCap));
}
private void addFlight(){
System.out.print("Give plane ID: ");
String planeID = readString();
System.out.print("Give departure airport code: ");
String airport1 = readString();
System.out.print("Give destination airport code: ");
String airport2 = readString();
String airports = airport1 + "-" + airport2;
for(Airplane ap : this.airplanes){
if(ap.getID().equals(planeID)){
this.flights.add(new Flight(ap, airports));
}
}
}
private String readString(){
return this.reader.nextLine();
}
EDIT: Here is a screenshot of the stack trace. I also made a github repo with all of my files in the event that would help more. I am pretty new to coding so excuse the mess I surely made of these files.
EDIT 2: I went to my readString() method and changed my call of .nextLine() to .next() and it fixed my issue. I'm not entirely sure how or why but it is now submitting correctly.

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!

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.

Exception in thread "main" java.util.NoSuchElementException: No line found

details:
Exception in thread "main" java.util.NoSuchElementException: No line found
at java.util.Scanner.nextLine<Scanner.java:1540>
at CarReader2.main<CarReader2.java:30>
that's the entirety of the error.
My code:
import java.io.File;
import java.io.FileNotFoundException;
import java.util.*;
public class CarReader2 {
String name, speed, acc;
public CarReader2(String carName, String carSpeed, String carAcc){
name = carName;
speed = carSpeed;
acc = carAcc;
}
public String toString(){
return "Name of car: " +name+ "\nSpeed of car: " +speed+"\nAcceleration of car: " +acc+"\n";
}
public static void main(String[] args) {
File file = new File("carlist.txt");
try {
Scanner sc = new Scanner(file);
while (sc.hasNextLine()) {
String c1Name = sc.nextLine();
String c1Speed = sc.nextLine();
String c1Acc = sc.nextLine();
CarReader2 car1 = new CarReader2(c1Name,c1Speed,c1Acc);
car1.speed = c1Speed;
car1.acc = c1Acc;
String c2Name = sc.nextLine();
String c2Speed = sc.nextLine();
String c2Acc = sc.nextLine();
CarReader2 car2 = new CarReader2(c2Name,c1Speed,c1Acc);
car2.speed = c2Speed;
car2.acc = c2Acc;
System.out.println("Information on both cars");
System.out.println("First car:");
System.out.println(car1.toString());
System.out.println("Second car:");
System.out.println(car2.toString());
}
sc.close();
}
catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
It's supposed to read data of 2 cars from a file called carlist.txt, then print the data of both cars in the correct format.
carlist.txt is a text file containing:
jonathan 3 7
dio 8 2
And the program is supposed to print out,
Information on both cars
First car:
Name of car: jonathan
Speed of car: 3
Acceleration of car: 7
Second car:
Name of car: dio
Speed of car: 8
Acceleration of car: 2
The program compiles but doesn't run correctly and shows the error i posted at the very top.
You're using nextLine method wrong. Name, speed and acceleration are in the same line, but you're using 3 nextLine methods to read them. That's what happens when you try to read 6 lines from a file that only has 2 lines in it. use sc.next() instead of sc.nextLine().
You are reading too many lines. There are only two lines in your file, but you are trying to read 6. You can change your text file to:
jonathan
3
7
dio
8
2
or you can read one line and split out the information you want.

Parse Text using scanner useDelimiter

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

Categories