Scanner hasNextLine() doesn't access last line in Java - java

I am using TreeMap structure in Java. The key contains character ':' in it and the values is a list of things. The problem is when i debug the program stops at this line (not working anymore...)
if (!string.isEmpty()) {
**string = jin.nextLine();**
}
I really have no idea what can be the problem. Here below is my code. Data(where I keep date variable) and ListOfBills (where I keep list of objects of the Bill Class) are two other Classes.
public void read(InputStream in) throws ParseException {
Scanner jin = new Scanner(in);
TreeMap<Date, ListOfBills> tree = new TreeMap<Date, ListOfBills>();
ListOfBills obBill = new ListOfBills();
Data data;
String string = jin.nextLine();
while (jin.hasNextLine()) {
if (string.contains(":")) {
data = new Data((string));
string = jin.nextLine();
while (!string.contains(":")) {
String[] parts1 = string.split(" ");
obBill.listOfBills.add(new Bill(Integer.parseInt(parts1[0]), Float.parseFloat(parts1[2]),
parts1[3], Float.parseFloat(parts1[5])));
if (!string.isEmpty()) {
string = jin.nextLine();
}
}
tree.put(data.date1, obBill);
}
}
for (Date date : tree.keySet()) {
System.out.println(date + "\n");
}
jin.close();
}

It keeps blocked because it is waiting an input ...
You need to enter a value in your stdin if your testing from console ...
Hope it helps

Related

Appending items from a txt file to an array

Hey I just started learning how to code. I am using netbeans and I want to transfer some data from a txt.file into an array in java. This might be a really simple fix but i just cant see whats wrong
This is the data in the txt.file:
58_hello_sad_happy
685_dhejdho_sahdfihsf_hasfi
544654_fhokdf_dasfjisod_fhdihds
This is the code I am using however smthg is wrong with the last line of code:
int points = 0;
String name = "";
String a = "";
String b = "";
public void ReadFiles() throws FileNotFoundException{
try (Scanner input = new Scanner(new File("questions.txt"))) {
String data;
while(input.hasNextLine()){
data = input.nextLine();
String[] Questions = data.split("_");
points = Integer.parseInt(Questions[0]);
name= Questions[1];
a = Questions[2];
b = Questions[3];
}
System.out.println(Arrays.toString(Questions));
}
}
This is the error I am getting:
error: cannot find symbol
System.out.println(Arrays.toString(Questions));
Thx soooo much guys.
You can also use the below code if you just want to print the data:
Files.readAllLines(Paths.get("questions.txt")).forEach(line -> {
System.out.println(Arrays.toString(line.split("_")));
});
Output is :
[58, hello, sad, happy]
[685, dhejdho, sahdfihsf, hasfi]
[544654, fhokdf, dasfjisod, fhdihds]
The correct version of your code should be like the below (you must access the variable Question in the declared scope by moving println into end of while loop) :
// definitions...
public void ReadFiles() throws FileNotFoundException{
try (Scanner input = new Scanner(new File("questions.txt"))) {
String data;
while(input.hasNextLine()){
data = input.nextLine();
String[] Questions = data.split("_");
points = Integer.parseInt(Questions[0]);
name= Questions[1];
a = Questions[2];
b = Questions[3];
System.out.println(Arrays.toString(Questions));
}
}
}

read txt file and store data in a hashtable in java

I am reading a txt file and store the data in a hashtable, but I couldn't get the correct output. the txt file like this (part) attached image
this is part of my data
And I want to store the column 1 and column 2 as the key(String type) in hashtable, and column 3 and column 4 as the value (ArrayList type) in hashtable.
My code below:
private Hashtable<String, ArrayList<String[]>> readData() throws Exception {
BufferedReader br = new BufferedReader (new FileReader("MyGridWorld.txt"));
br.readLine();
ArrayList<String[]> value = new ArrayList<String[]>();
String[] probDes = new String[2];
String key = "";
//read file line by line
String line = null;
while ((line = br.readLine()) != null && !line.equals(";;")) {
//System.out.println("line ="+line);
String source;
String action;
//split by tab
String [] splited = line.split("\\t");
source = splited[0];
action = splited[1];
key = source+","+action;
probDes[0] = splited[2];
probDes[1] = splited[3];
value.add(probDes);
hashTableForWorld.put(key, value);
System.out.println("hash table is like this:" +hashTableForWorld);
}
br.close();
return hashTableForWorld;
}
The output looks like this:
it's a very long long line
I think maybe the hashtable is broken, but I don't know why. Thank you for reading my problem.
The first thing we need to establish is that you have a really obvious XY-Problem, in that "what you need to do" and "how you're trying to solve it" are completely at odds with each other.
So let's go back to the original problem and try to work out what we need first.
As best as I can determine, source and action are connected, in that they represent queryable "keys" to your data structure, and probability, destination, and reward are queryable "outcomes" in your data structure. So we'll start by creating objects to represent those two concepts:
public class SourceAction implements Comparable<SourceAction>{
public final String source;
public final String action;
public SourceAction() {
this("", "");
}
public SourceAction(String source, String action) {
this.source = source;
this.action = action;
}
public int compareTo(SourceAction sa) {
int comp = source.compareTo(sa.source);
if(comp != 0) return comp;
return action.compareto(sa.action);
}
public boolean equals(SourceAction sa) {
return source.equals(sa.source) && action.equals(sa.action);
}
public String toString() {
return source + ',' + action;
}
}
public class Outcome {
public String probability; //You can use double if you've written code to parse the probability
public String destination;
public String reward; //you can use double if you're written code to parse the reward
public Outcome() {
this("", "", "");
}
public Outcome(String probability, String destination, String reward) {
this.probability = probability;
this.destination = destination;
this.reward = reward;
}
public boolean equals(Outcome o) {
return probability.equals(o.probability) && destination.equals(o.destination) && reward.equals(o.reward);
public String toString() {
return probability + ',' + destination + ',' + reward;
}
}
So then, given these objects, what sort of Data Structure can properly encapsulate the relationship between these objects, given that a SourceAction seems to have a One-To-Many relationship to Outcome objects? My suggestion is that a Map<SourceAction, List<Outcome>> represents this relationship.
private Map<SourceAction, List<Outcome>> readData() throws Exception {
It is possible to use a Hash Table (in this case, HashMap) to contain these objects, but I'm trying to keep the code as simple as possible, so we're going to stick to the more generic interface.
Then, we can reuse the logic you used in your original code to insert values into this data structure, with a few tweaks.
private Map<SourceAction, List<Outcome>> readData() {
//We're using a try-with-resources block to eliminate the later call to close the reader
try (BufferedReader br = new BufferedReader (new FileReader("MyGridWorld.txt"))) {
br.readLine();//Skip the first line because it's just a header
//I'm using a TreeMap because that makes the implementation simpler. If you absolutely
//need to use a HashMap, then make sure you implement a hash() function for SourceAction
Map<SourceAction, List<Outcome>> dataStructure = new TreeMap<>();
//read file line by line
String line = null;
while ((line = br.readLine()) != null && !line.equals(";;")) {
//split by tab
String [] splited = line.split("\\t");
SourceAction sourceAction = new SourceAction(splited[0], splited[1]);
Outcome outcome = new Outcome(splited[2], splited[3], splited[4]);
if(dataStructure.contains(sourceAction)) {
//Entry already found; we're just going to add this outcome to the already
//existing list.
dataStructure.get(sourceAction).add(outcome);
} else {
List<Outcome> outcomes = new ArrayList<>();
outcomes.add(outcome);
dataStructure.put(sourceAction, outcomes);
}
}
} catch (IOException e) {//Do whatever, or rethrow the exception}
return dataStructure;
}
Then, if you want to query for all the outcomes associated with a given source + action, you need only construct a SourceAction object and query the Map for it.
Map<SourceAction, List<Outcome>> actionMap = readData();
List<Outcome> outcomes = actionMap.get(new SourceAction("(1,1)", "Up"));
assert(outcomes != null);
assert(outcomes.size() == 3);
assert(outcomes.get(0).equals(new Outcome("0.8", "(1,2)", "-0.04")));
assert(outcomes.get(1).equals(new Outcome("0.1", "(2,1)", "-0.04")));
assert(outcomes.get(2).equals(new Outcome("0.1", "(1,1)", "-0.04")));
This should yield the functionality you need for your problem.
You should change your logic for adding to your hashtable to check for the key you create. If the key exists, then grab your array list of arrays that it maps to and add your array to it. Currently you will overwrite the data.
Try this
if(hashTableForWorld.containsKey(key))
{
value = hashTableForWorld.get(key);
value.add(probDes);
hashTableForWorld.put(key, value);
}
else
{
value = new ArrayList<String[]>();
value.add(probDes);
hashTableForWorld.put(key, value);
}
Then to print the contents try something like this
for (Map.Entry<String, ArrayList<String[]>> entry : hashTableForWorld.entrySet()) {
String key = entry.getKey();
ArrayList<String[]> value = entry.getValue();
System.out.println ("Key: " + key + " Value: ");
for(int i = 0; i < value.size(); i++)
{
System.out.print("Array " + i + ": ");
for(String val : value.get(i))
System.out.print(val + " :: ")
System.out.println();
}
}
Hashtable and ArrayList (and other collections) do not make a copy of key and value, and thus all values you are storing are the same probDes array you are allocating at the beginning (note that it is normal that the String[] appears in a cryptic form, you would have to make it pretty yourself, but you can still see that it is the very same cryptic thing all the time).
What is sure is that you should allocate a new probDes for each element inside the loop.
Based on your data you could work with an array as value in my opinion, there is no real use for the ArrayList
And the same applies to value, it has to be allocated separately upon encountering a new key:
private Hashtable<String, ArrayList<String[]>> readData() throws Exception {
try(BufferedReader br=new BufferedReader(new FileReader("MyGridWorld.txt"))) {
br.readLine();
Hashtable<String, ArrayList<String[]>> hashTableForWorld=new Hashtable<>();
//read file line by line
String line = null;
while ((line = br.readLine()) != null && !line.equals(";;")) {
//System.out.println("line ="+line);
String source;
String action;
//split by tab
String[] split = line.split("\\t");
source = split[0];
action = split[1];
String key = source+","+action;
String[] probDesRew = new String[3];
probDesRew[0] = split[2];
probDesRew[1] = split[3];
probDesRew[2] = split[4];
ArrayList<String[]> value = hashTableForWorld.get(key);
if(value == null){
value = new ArrayList<>();
hashTableForWorld.put(key, value);
}
value.add(probDesRew);
}
return hashTableForWorld;
}
}
Besides relocating the variables to their place of actual usage, the return value is also created locally, and the reader is wrapped into a try-with-resource construct which ensures that it is getting closed even if an exception occurs (see official tutorial here).

Parsing various values in Textfile (Java)

I have a textfile as such:
type = "Movie"
year = 2014
Producer = "John"
title = "The Movie"
type = "Magazine"
year = 2013
Writer = "Alfred"
title = "The Magazine"
What I'm trying to do is, first, search the file for the type, in this case "Movie" or "Magazine".
If it's a Movie, store all the values below it, i.e
Set the movie variable to be 2014, Producer to be "John" etc.
If it's a Magazine type, store all the variables below it as well separately.
What I have so far is this:
public static void Parse(String inPath) {
String value;
try {
Scanner sc = new Scanner(new FileInputStream("resources/input.txt"));
while(sc.hasNextLine()) {
String line = sc.nextLine();
if(line.startsWith("type")) {
value = line.substring(8-line.length()-1);
System.out.println(value);
}
}
} catch (FileNotFoundException ex) {
Logger.getLogger(LibrarySearch.class.getName()).log(Level.SEVERE, null, ex);
}
}
However, I'm already having an issue in simply printing out the first type, which is "Movie". My program seems to skip that one, and print out "Magazine" instead.
For this problem solely, is it because the line: line.startsWith("type")is checking if the current line in the file starts with type, but since the actual String called lineis set to the nextline, it skips the first "type"?
Also, what would be the best approach to parsing the actual values (right side of equal sign) below the type "Movie" and "Magazine" respectively?
I recommend you try the following:
BufferedReader reader = new BufferedReader(new FileReader(new File("resources/input.txt")));
String line;
while((line = reader.readLine()) != null) {
if (line.contains("=")) {
String[] bits = line.split("=");
String name = bits[0].trim();
String value = bits[1].trim();
if (name.equals("type")) {
// Make a new object
} else if (name.equals("year")) {
// Store in the current object
}
} else {
// It's a new line, so you should make a new object to store stuff in.
}
}
In your code, the substring looks suspect to me. If you do a split based on the equals sign, then that should be much more resilient.

Searching for a particular line of text in a text file

I am having issues with my synonym map. I want to be able to search a text file for a keyword or a related word in the textfile then outputting the found sentence. so my program searches for the answers to questions based on the keyword or sunonym. the way my program works is by searching a text file for a keyword in the question and then outputting the answer to the question which is the next line after then question in the text file. When i search for the main keyword in a question the program works. But when i try to ask a question with the related word the program does not recognize the input. So for example if i enter "how is the major?" the answer to that question is on the next line which is "the major is difficult" but if i enter "how is the focus" the program does not recognize the related word focus Can someone help me find the issue which lies in searching for a related word also. Here is my text file
what is the textbook name?
the textbook name is Java
how is the major?
the major is difficult
how much did the shoes cost?
the shoes cost two dollars
how is the major when cramer took it?
when cramer took it, it was okay
how is the major when jar took it?
jar said it was fine
what is the color of my bag?
the color of my bag is blue
and here is my code
public static class DicEntry {
String key;
String[] syns;
Pattern pattern;
public DicEntry(String key, String... syns) {
this.key = key;
this.syns = syns;
pattern = Pattern.compile(".*(?:"
+ Stream.concat(Stream.of(key), Stream.of(syns))
.map(x -> "\\b" + Pattern.quote(x) + "\\b")
.collect(Collectors.joining("|")) + ").*");
}
}
public static void parseFile(String s) throws IOException {
List<DicEntry> synonymMap = populateSynonymMap(); // populate the map
File file = new File("data.txt");
Scanner scanner = new Scanner(file);
Scanner forget = new Scanner(System.in);
int flag_found = 0;
while (scanner.hasNextLine()) {
final String lineFromFile = scanner.nextLine();
for (DicEntry entry : synonymMap) { // iterate over each word of the
// sentence.
if (entry.pattern.matcher(s).matches()) {
if (lineFromFile.contains(entry.key)) {
//String bat = entry.key;
if(lineFromFile.contains(s)) {
String temp = scanner.nextLine();
System.out.println(temp);
}
}
}
}
}
}
private static List<DicEntry> populateSynonymMap() {
List<DicEntry> responses = new ArrayList<>();
responses.add(new DicEntry("bag", "purse", "black"));
responses.add(new DicEntry("shoe", "heels", "gas"));
responses.add(new DicEntry("major", "discipline", "focus", "study"));
return responses;
}
public static void getinput() throws IOException {
Scanner scanner = new Scanner(System.in);
String input = null;
/* End Initialization */
System.out.println("Welcome ");
System.out.println("What would you like to know?");
System.out.print("> ");
input = scanner.nextLine().toLowerCase();
parseFile(input);
}
public static void main(String args[]) throws ParseException, IOException {
/* Initialization */
getinput();
}
}
It would seem that after you pass
if (lineFromFile.contains(entry.key))
in your parseFile(String s) method, you would want to know if your user entered input contains any of the entry.syns and replace the synonym with the key
// This is case sensitive
boolean synonymFound = false;
for (String synonym : entry.syns) {
if (s.contains(synonym)) {
s = s.replace(synonym, entry.key)
break;
}
}
Since you want to stop searching once you find a match (exact or synonym match), you'll want to have a return statement to kick out of the method or use a flag to kick out of the while (scanner.hasNextLine())
if (lineFromFile.contains(s)) {
String temp = scanner.nextLine();
System.out.println(temp);
flag_found = 1;
System.out
.println(" Would you like to update this information ? ");
String yellow = forget.nextLine();
if (yellow.equals("yes")) {
// String black = scanner.nextLine();
removedata(temp);
} else if (yellow.equals("no")) {
System.out.println("Have a good day");
// break;
}
// Add return statment to end the search
return;
}
Results:

Scanner - managing input from text file

I’m working with java Scanner trying to extract product information from a text file called Inventory.txt.
This file contains data on products in this format:
“Danelectro|Bass|D56BASS-AQUA|336177|395.00Orange|Amplifier|BT1000-H|319578|899.00Planet Waves|Superpicks|1ORD2-5|301075|4.50Korg|X50 Music Synthesizer|X50|241473|735.00Alpine|Alto Sax|AAS143|198490|795.00”
I am trying to parse the strings and add them into an arraylist such that each element in the arraylist would look something like this:
"Danelectro|Bass|D56BASS-AQUA|336177|395.00"
"Orange|Amplifier|BT1000-H|319578|899.00"
"KorPlanet Waves|Superpicks|1ORD2-5|301075|4.50"
"g|X50 Music Synthesizer|X50|241473|735.00"
"Alpine|Alto Sax|AAS143|198490|555.00”
Following is my code:
public class ItemDao {
public ItemDao() {
scanFile();
}
public void scanFile() {
Scanner scanner;
ArrayList <String> content = new ArrayList <String>();
try {
Pattern p1 = Pattern.compile("\\.[0-9]{2}$");
scanner = new Scanner(new File("Inventory.txt"));
while (scanner.hasNext(p1)) {
content.add(scanner.next(p1));
}
for (String item : content) {
System.out.println("Items:" + item);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
When I tested this code I found that the arraylist is empty. Any help would be much appreciated.
java -jar A00123456Lab5.jar
Create an ItemDAO class in a dao package
This class will contain an static inner class which implements Comparator
(DAO = Data Access Object)
You can define a Scanner on a String, and a delimiter.
Since the | is used in regex as OR combinator, you have to mask it with (double)-backslash:
sc = new java.util.Scanner ("Danelectro|Bass|D56BASS-AQUA|336177|395.00");
sc.useDelimiter ("\\|");
String name = sc.next ();
// name: java.lang.String = Danelectro
String typ = sc.next ();
// typ: java.lang.String = Bass
String model = sc.next
// model: java.lang.String = D56BASS-AQUA
int id = sc.nextInt ();
// id: Int = 336177
val d = sc.nextDouble ();
// d: Double = 395.0
I see you're using a pattern, those can come in handy--but I'd just take each line and substring it.
while(scanner.hasNextLine()){
String temp = scanner.nextLine();
while(temp.indexOf("|") != -1){
content.add(temp.substring(temp.indexOf("|"));
temp.substring(temp.indexOf("|")+1);
}
}
Just a thought--might be easier to debug with this way.

Categories