How to get test questions from txt file with specific structure? - java

I want to make a program which get questions and their answers from file with specific structure and let the user give answers to them. The program also have to count right answers and show them to the user.
Here is the sample of the text file structure:
What year is it right now?
2
1) 1900
2) 2014
3) 3200
---
Which is the biggest country in the world?
1
1) Russia
2) United States of America
3) United Kingdom
---
That's the code I wrote, but there something wrong and I can't see what exactly is:
public class testLoader {
private static BufferedReader br;
private static int answerCounter;
public static void main(String[] args) {
try {
br = new BufferedReader(new FileReader("D:/test.txt"));
StringBuilder sb = new StringBuilder();
String line = br.readLine();
while (line != null) {
String answer=null;
if(line.startsWith("*")){
answer = line;
}
while (line != "---") {
line = br.readLine();
sb.append(line);
sb.append(System.lineSeparator());
}
System.out.println(sb.toString());
answerCheck(answer);
line = br.readLine();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
System.out.println("You have " + answerCounter + "correct answers");
}
public static void answerCheck(String rightAnswer) {
System.out.println("What's your answer?");
Scanner input = new Scanner(System.in);
String answer = input.nextLine();
answerCounter = 0;
if (answer == rightAnswer){
answerCounter++;
System.out.println("Correct!");
} else {
System.out.println("Wrong!");
}
}
}
I'll apreciate any help you can give. If there are any better way to complete the task, I'll be glad to see it.
Thanks in advance!

Here is the corrected version of your program.
You had a few bugs in there.
My program works OK on the file format you posted
here (without the asterisks that is).
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.Scanner;
public class testLoader {
private static BufferedReader br;
private static int answerCounter = 0;
public static void main(String[] args) {
try {
br = new BufferedReader(new FileReader("C:/Various/test.txt"));
StringBuilder sb = new StringBuilder();
String line = null;
do {
line = br.readLine();
if (line != null) {
sb.append(line);
sb.append(System.getProperty("line.separator"));
} else {
break;
}
String answer = br.readLine().trim();
while (!"---".equals(line)) {
line = br.readLine();
sb.append(line);
sb.append(System.getProperty("line.separator"));
}
System.out.println(sb.toString());
answerCheck(answer);
sb.setLength(0);
} while (true);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
System.out.println("You have " + answerCounter + " correct answers");
}
public static void answerCheck(String rightAnswer) {
System.out.println("What's your answer?");
Scanner input = new Scanner(System.in);
String answer = input.nextLine();
// answerCounter = 0;
if (answer.equals(rightAnswer)) {
answerCounter++;
System.out.println("Correct!");
} else {
System.out.println("Wrong!");
}
}
}

You want to seperate right answer from wrong ones with * sign but you are not providing it on your text file.
Even if you add * sign to the head of right answer, you won't make right answer value assigned to answer string variable.
Besides all of above, why do you want to check right answer with a * sign if you write the right answer's number below the question?
You have to compare strings with equals() method since you are dealing with values of strings, not memory addresses of them.
You have declared a StringBuilder object to append questions/answers and print them to screen but with this code, you will always add previous questions/answers to the current question. (i.e you are printing 2. question with first one above of it)
answerCounter variable will not hold user's total correct answers as you always assign it to 0 whenever you call the method.
So with all of these are corrected, I think you want to achieve something like below:
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.Scanner;
public class testLoader
{
private static BufferedReader br;
private static int answerCounter = 0;
public static void main(String[] args)
{
try
{
br = new BufferedReader(new FileReader("C:/test.txt"));
StringBuilder sb;
String line, answer = null;
while((line = br.readLine()) != null)
{
sb = new StringBuilder();
do
{
if(line.length() == 1) //This is a bad choice of digit comparison but it will work with your case (lol)
{
answer = line;
line = br.readLine();
continue;
}
sb.append(line);
sb.append(System.lineSeparator());
line = br.readLine();
}
while(!line.equals("---"));
System.out.println(sb.toString());
answerCheck(answer);
}
}
catch(IOException e)
{
e.printStackTrace();
}
finally
{
try
{
br.close();
}
catch(IOException e)
{
e.printStackTrace();
}
}
System.out.println("You have " + answerCounter + "correct answers");
}
public static void answerCheck(String rightAnswer)
{
System.out.println("What's your answer?");
Scanner input = new Scanner(System.in);
String answer = input.nextLine();
if(answer.equals(rightAnswer))
{
answerCounter++;
System.out.println("Correct!");
}
else
{
System.out.println("Wrong!");
}
}
}

Related

REGEX to check data text file if last two digits is greater than 70

Introduction
Hi guys, I am new to Java programming. Forgive me if I may have ask a repeated
question. Have tried to look around for similar answers on stack but cant.
Have been stuck on this for few days.
I want to read the last two digits of a text file and validate using regex. If its greater than 70
System should print "They are speeding.";
This would be the draft of the the text file.
AB12345-60
AB22345-60
AB32345-80
Sample Java code:
import java.io.*;
class Main {
private final int LinesToRead = 3;
private final String REGEX = ".{2}\d{5}[-]\d{2}";
public void testFile(String fileName) {
int lineCounter = 1;
try {
BufferedReader br = new BufferedReader(new FileReader(fileName));
String line = br.readLine();
while ((line != null) && (lineCounter <= LinesToRead)) {
if (line.matches(REGEX)) {
System.out.println("They are not speeding");
}
else {
System.out.println("They are speeding");
}
line = br.readLine();
lineCounter++;
}
} catch (Exception ex) {
System.out.println("Exception occurred: " + ex.toString());
}
}
public static void main(String[] args) {
Main vtf = new Main();
vtf.testFile("Data.txt");
} }
I suggest just doing a string split to isolate the final speed number, and then check it via an inequality:
while ((line != null) && (lineCounter <= LinesToRead)) {
int speed = Integer.parseInt(line.split("-")[1]);
if (speed > 70) {
System.out.println("They are speeding");
}
else {
System.out.println("They are not speeding");
}
line = br.readLine();
lineCounter++;
}

Create a class that displays the content of the text file to console with some changes

Changes: delete the first two characters of each word with the length of 4 and more characters
example: original 'qwerty', new 'erty'
A 'word' should be considered a continuous sequence of Cyrillic or Latin characters.
I wrote something like this, but output string is in line, but I need input text with indent characters.
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.Scanner;
public class Part1 {
// getting input string from the file
public static String getInput(String fileName) {
StringBuilder sb = new StringBuilder();
try {
Scanner scanner = new Scanner(new File(fileName), "UTF-8");
while (scanner.hasNextLine()) {
sb.append(scanner.nextLine()).append(System.lineSeparator());
}
scanner.close();
return sb.toString().trim();
} catch (IOException ex) {
ex.printStackTrace();
}
return sb.toString();
}
// deleting the first two characters of each word with the length of 4 and more characters
public static void convert() {
try (BufferedReader in = new BufferedReader(new FileReader("part1.txt"))) {
String line;
StringBuilder result = new StringBuilder();
while ((line = in.readLine()) != null) {
String[] wordsInLine = line.split("[.,!?\\-\\s\\n]+");
for (String string : wordsInLine) {
if (isLongerThanFour(string) && defineLocale(string) == "latn") {
result.append(string.substring(2) + " ");
} else if (isLongerThanFour(string) && defineLocale(string) == "cyrl") {
result.append(string.substring(4) + " ");
} else {
result.append(string + " ");
}
}
}
System.out.println(result);
}catch(IOException e){
e.getMessage();
}
}
// checking for right length of current word
public static boolean isLongerThanFour(String string){
return string.length() >= 4;
}
// define language of input word(one of cyrillic of latin languages)
private static String defineLocale(String string) {
char ch = string.charAt(0);
if (Character.isAlphabetic(ch)) {
if (Character.UnicodeBlock.of(ch).equals(Character.UnicodeBlock.CYRILLIC)) {
return "cyrl";
} else if (Character.UnicodeBlock.of(ch).equals(Character.UnicodeBlock.BASIC_LATIN)){
return "latn";
}
}
return "none";
}
public static void main(String[] args){
Part1.convert();
}
}
Can you point on my mistakes or suggest cleaner solution.
Thank you in advance.
public class Converter {
//helper enum
enum Language {
cyr,
lat,
none
}
// if you have to return more that two types of values then use enum
private static Language defineLocale(String string) {
char ch = string.charAt(0);
if (Character.isAlphabetic(ch)) {
if (Character.UnicodeBlock.of(ch).equals(Character.UnicodeBlock.CYRILLIC)) {
return Language.cyr;
} else if (Character.UnicodeBlock.of(ch).equals(Character.UnicodeBlock.BASIC_LATIN)){
return Language.lat;
}
}
return Language.none;
}
public void convert() {
try (BufferedReader in = new BufferedReader(new FileReader("part1.txt"))) {
String line;
StringBuilder result = new StringBuilder();
while ((line = in.readLine()) != null) {
String[] wordsInLine = line.split(" ");
for (String s : wordsInLine) {
if (s.length() > 3) {
switch (defineLocale(s)) {
case cyr:
result.append(s.substring(4));
break;
case lat:
result.append(s.substring(2));
break;
default:
result.append(s);
}
} else result.append(s);
result.append(" ");
}
result.append("\n");//all you were missing
}
System.out.println(result);
}catch(IOException e){
e.getMessage();
}
}
public static void main(String[] args){
new Converter().convert();
}
}
I hope this does not need any further explanation but dont be shy to ask if you dont understand something.

Read, and then split a text file into different arrays

So I'm trying to use a BufferedReader to split a text file into 2 different arrays, I've written some code but I'm not sure where to go from here.
I know how to populate an array, but i just cant seem to get the specific lines.
So, one array for NEW_OFFICE containing only the numbers, and one for MAIN_ADDRESS containing only the numbers below it.
BufferedReader in = null;
try {
in = new BufferedReader(new FileReader("myDelivery.txt"));
String read = null;
while ((read = in.readLine()) != null) {
String words = read.split("NEW_OFFICE")[0];
}
} catch (IOException e) {
System.out.println("There was a problem: " + e);
e.printStackTrace();
} finally {
try {
in.close();
} catch (Exception ignored) { }
}
This is the text file:
NEW_OFFICE
-92.48392883 52.96531732
-2.483984994 92.48392883
MAIN_ADDRESS
-1.207614869 52.98908196
NEW_OFFICE always is the first line, and always has two lines below
it, the same goes for MAIN_ADDRESS it always has one line below it.
NEW_OFFICE & MAIN_ADDRESS can't appear more than once.
Based on your comment mentioned above, given below is the solution:
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.Arrays;
public class Main {
public static void main(String[] args) throws IOException {
String[][] office = new String[2][2];
String[][] main = new String[1][2];
try (BufferedReader in = new BufferedReader(new FileReader("myDelivery.txt"))) {
String read;
while ((read = in.readLine()) != null) {
if (read.equalsIgnoreCase("NEW_OFFICE")) {
// Read next two lines
for (int i = 0; i < 2; i++) {
if ((read = in.readLine()) != null) {
office[i] = read.split("\\s+");
}
}
} else if (read.equalsIgnoreCase("MAIN_ADDRESS")) {
// Read next line
if ((read = in.readLine()) != null) {
main[0] = read.split("\\s+");
}
}
}
}
// Display office[][]
System.out.println("Displaying office:");
for (String[] officeData : office) {
System.out.println(Arrays.toString(officeData));
}
// Display main[][]
System.out.println("Displaying main:");
for (String[] mainData : main) {
System.out.println(Arrays.toString(mainData));
}
}
}
Output:
Displaying office:
[-92.48392883, 52.96531732]
[-2.483984994, 92.48392883]
Displaying main:
[-1.207614869, 52.98908196]
Notes:
\\s+ is for splitting the line on space(s).
Use try-with-resources syntax to simplify your code.
.split() does take a string, but it should be a regex, not the substring that you want to split it on. You want to change your code like this:
try (BufferedReader in = new BufferedReader(new FileReader("x.txt"))) {
String read;
String office = "";
while ((read = in.readLine()) != null) {
if (read.contains("NEW_OFFICE")) {
office = "NEW_OFFICE";
} else if (read.contains("MAIN_ADDRESS")) {
office = "MAIN_ADDRESS";
} else {
System.out.println(office + " : " + read);
}
}
} catch (IOException e) {
e.printStackTrace();
}
I have also changed your try with try-with-resources so you don't have to worry about closing the resource.
I´d go with somethin like this.
Please be aware that I don´t have an IDE right now so this is basically pseudo code:
try (BufferedReader in = new BufferedReader(new FileReader("x.txt"))) {
String line = null;
boolean isOffice = false;
ArrayList<double> officeInts = new ArrayList<double>();
ArrayList<double> addressInts = new ArrayList<double>();
while ((line = in.readLine()) != null) {
if (line.contains("NEW_OFFICE")) {
isOffice = true;
continue;
} else if (line.contains("MAIN_ADDRESS")) {
isOffice = false;
continue;
}
for(String s : line.split(" "){
double num = Double.parseDouble(s);
if(isOffice) {
officeInts.add(num);
} else {
addressInts.add(num);
}
}
}
} catch (IOException e) {
e.printStackTrace();
}

Press any key with BufferedReader

I created a java file called Product.java. I also created a text file called Items.txt. Basically when the user enter the word using sequential search to search the data what they are looking from Items.txt. My main problem is when I enter 3 to display all the records or enter x to exit the program, it keeps on looping. But I don't how to resolve this problem. Can anyone solved this for me?
Items.txt
1000|Cream of Wheat|Normal Size|Breakfast|NTUC|5|3.00
1001|Ayam Brand|Small Size|Canned|NTUC|4|4.00
Product.java
import java.io.*;
import java.util.*;
public class Product {
public static void main(String[] args) {
ArrayList<Item> prdct = new ArrayList<Item>();
String inFile = "items.txt";
String line = "";
FileReader fr = null;
BufferedReader br = null;
StringTokenizer tokenizer;
int quantity;
String id, brandname, desc, category, supplier;
float price;
try{
fr = new FileReader(inFile);
br = new BufferedReader(fr);
line = br.readLine();
while(line!=null)
{
tokenizer = new StringTokenizer(line,"|");
id = tokenizer.nextToken();
brandname = tokenizer.nextToken();
desc = tokenizer.nextToken();
category = tokenizer.nextToken();
supplier = tokenizer.nextToken();
quantity = Integer.parseInt(tokenizer.nextToken());
price = Float.parseFloat(tokenizer.nextToken());
Item itm = new Item(id,brandname,desc,category,supplier,quantity,price);
prdct.add(itm);
line = br.readLine();
}
br.close();
}
catch(FileNotFoundException e){
System.out.println("The file " + inFile + " was not found.");
}
catch(IOException e){
System.out.println("Reading error!");
}
finally
{
if (fr!=null){
try
{
fr.close();
}
catch(IOException e)
{
System.out.println("Error closing file!");
}
}
}
String INPUT_PROMPT = "\nPlease enter 3 to display all records, 4 to insert record, 5 to remove old records " + "or enter 'x' to quit.";
System.out.println(INPUT_PROMPT);
try
{
BufferedReader reader = new BufferedReader
(new InputStreamReader (System.in));
line = reader.readLine();
while(reader != null)
{
for(int i=0; i<prdct.size(); i++)
{
if(prdct.get(i).id.contains(line) || prdct.get(i).brandname.contains(line) || prdct.get(i).desc.contains(line)
|| prdct.get(i).category.contains(line) || prdct.get(i).supplier.contains(line))
{
System.out.println(prdct.get(i));
}
System.out.println(INPUT_PROMPT);
line = reader.readLine();
}
}
while("3".equals(line))
{
for(int i=0; i<prdct.size(); i++)
{
System.out.println(prdct.get(i));
}
System.out.println(INPUT_PROMPT);
line = reader.readLine();
}
while(!line.equals("x"))
{
System.out.println(INPUT_PROMPT);
line=reader.readLine();
}
}
catch(Exception e){
System.out.println("Input Error!");
}
}
}
The problem is with this loop:
while(reader != null)
{
for(int i=0; i<prdct.size(); i++)
{
if(prdct.get(i).id.contains(line) || prdct.get(i).brandname.contains(line) || prdct.get(i).desc.contains(line)
|| prdct.get(i).category.contains(line) || prdct.get(i).supplier.contains(line))
{
System.out.println(prdct.get(i));
}
System.out.println(INPUT_PROMPT);
line = reader.readLine();
}
}
It keeps on looping while reader is not null and it will never be. You might want to try checking something else that suits your problem better, maybe:
While(!line.equals("3"))
While(!line.equals("x"))
While(line != null)
Otherwise, even if there is an 'x', '3' or simply nothing, still (reader != null) and therefore the loop is infinite.
I suspect that the newline character is what causes the comparison to fail.
Instead of checking if:
"3".equals(line)
Try:
"3".equals(line.trim())
Same applies to the following comparison.
Try changing this..
line = reader.readLine();
while(reader != null)
{
to this..
line = reader.readLine();
while(line != null)
{
You are looping on the reader being not null, which it always will be.
you have to define these functions:
public void showAllRecords() {
// show all record here
}
public void insertRecord() {
// insert record here
}
public void removeRecord() {
// insert record here
}
public void exit() {
// insert record here
}
then
do{
System.out.println(INPUT_PROMPT);
switch(line)
{
case "3":
showAllRecords();
break;
case "4":
insertRecord();
break;
case "5":
removeRecord();
}
}while(!line.equals('x'));

Need my program to know where I left off

So I'm trying to make clip card application. In other words, I'm making an application that counts how many coffees a customer purchases, and for every 10:th purchase the customer gets awarded a free one. I'm pretty much done with the loop, but I'm having difficulties with figuring out how to make my program remember where I left off. For example, lets say I have bought my 7th coffee and am leaving so I want to close the application; is there a way for the program to remember where to continue next time it is being run?
Here's what I have so far:
import java.util.Scanner;
public class FelixNeww {
public static void main(String [] args) {
Scanner key;
String entry;
int count = 0;
String password = "knusan01";
while(true) {
System.out.println("Enter password: ");
key = new Scanner(System.in);
entry = key.nextLine();
if(entry.compareTo(password) == 0){
count++;
System.out.println("You're one step closer to a free coffe! You have so far bought "
+ count + " coffe(s)");
}
if(count == 10 && count != 0){
System.out.println("YOU'VE GOT A FREE COFFE!");
count = 0;
}
if(entry.compareTo(password) != 0){
System.out.println("Wrong password! Try again.\n");
}
}
}
}
Thanks
If you want to make sure the progress is saved, try looking into the RuntimeHook as said here: Intercepting java machine shutdown call?
And what you need to do is store the data in a file, the current count. This can be done fairly easily with the following code:
public void saveToFile(int count)
{
BufferedWriter bw = null;
try
{
bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(new File("countStorage"))));
bw.write(count);
}
catch(IOException e)
{
e.printStackTrace();
}
finally
{
if(bw != null)
{
try
{
bw.close();
}
catch(IOException e) {}
}
}
}
public int readFromFile()
{
BufferedReader br = null;
try
{
br = new BufferedReader(new InputStreamReader(new FileInputStream(new File("countStorage"))));
String line = br.readLine();
int count = Integer.parseInt(line);
return count;
}
catch(IOException e)
{
e.printStackTrace();
}
finally
{
if(br != null)
{
try
{
br.close();
}
catch(IOException e) {}
}
}
}

Categories