java - read user input and print line if it is a duplicate - java

So I'm learning about reading text files in java and I'm trying to write a program that reads user input one line at a time and outputs the current line if and only if it is a duplicate of some previous line. This is the part of code I'm struggling with and was wondering if I could get a push in the right direction. Right now it currently asks for user input, and when I write a line and press enter, the program ends without printing anything.
public static void doIt(BufferedReader r, PrintWriter w) throws IOException {
Set<String> s = new HashSet<String>();
while(true) {
String line = r.readLine();
if(s.contains(line)) {
s.add(line);
}else {
break;
}
}
for (String text : s) {
w.println(text);
}
}

You can keep two mutable states, one for all the lines and one for duplicate lines.
Example below. (You can exit program on :q).
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashSet;
import java.util.Set;
public class CheckDupes {
public static void main(String[] args) throws IOException {
Set<String> lines = new HashSet<String>();
Set<String> duplicateLines = new HashSet<String>();
BufferedReader stdReader =
new BufferedReader(new InputStreamReader(System.in));
String line = null;
while (!(line = stdReader.readLine()).equals(":q")) {
if (lines.contains(line)) {
duplicateLines.add(line);
} else {
lines.add(line);
}
}
duplicateLines.forEach(l -> System.out.println(l));
}
}
Input/ Output
love is great
weather is good
software is version 4
weather is good
love is great
:q
weather is good
love is great

Related

StreamTokenizer infinite input problem from console

I am beginner in Java, so during my learning another topic as StreamTokenizer, I faced some kind of intresting problem. And I didn't found any close solutions or hints in the Internet.
So, basically, almost every educational source give us an example like this:
import java.io.*;
public class pr_23 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StreamTokenizer st = new StreamTokenizer(br);
while (st.nextToken() != st.TT_EOF)
if (st.ttype == st.TT_NUMBER)
System.out.print(st.nval + " "); // not infinite cycle
br.close();
}
}
And it works well. But if I include in the cycle some other operators with st.nval, like double b = st.nval and exclude this System.out.print() code, compiler cant determine the end of the Stream in this case anymore, so it starts infinite reading. I wanted StreamTokenizer gave numbers to my ArrayList, but magically it cant see the end of Stream in this case with similar cycle. What's intresting it does work correctly if I use FileInputStream instead of InputStreamReader. But I need to get input from the console, not from a file. Also, using FIS in Tokenizer is deprecated. So here's similar code, but it doesnt work properly:
import java.io.*;
import java.util.ArrayList;
public class pr_23 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StreamTokenizer st = new StreamTokenizer(br);
ArrayList<Integer> a = new ArrayList<>();
while (st.nextToken() != st.TT_EOF) {
a.add((int)st.nval); // infinite cycle
}
System.out.print(a);
br.close();
}
}
P.S. input is meant to be only int numbers for simplicity
Please understand that your loop is repeating until the input reaches to the EOF. And, your latter code does not output anything before your loop would exit. So, if you want to see your output with the latter code, you must close your standard input stream first. To close standard input, you should send EOF code from keyboard. On Linux and macos, you can close standard input with Ctrl-D, and on Windows, it is Ctrl-Z.
The source of your problem is using System.in.
Try reading from a file:
import java.io.*;
import java.util.ArrayList;
public class pr_23 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new FileReader("myfile.txt"));
StreamTokenizer st = new StreamTokenizer(br);
ArrayList<Integer> a = new ArrayList<>();
while (st.nextToken() != st.TT_EOF) {
a.add((int)st.nval); // infinite cycle
}
System.out.print(a);
br.close();
}
}
The problem is that you won't get an EOF in a System.in if you run it interactively. Though you would get it if you run it like this:
java pr_23 < myfile.txt
By the way a better way to write this without the dangling close() would be:
import java.io.*;
import java.util.ArrayList;
public class pr_23 {
public static void main(String[] args) throws IOException {
// using try this way will close br automagically
try (BufferedReader br = new BufferedReader(new FileReader("myfile.txt"))) {
StreamTokenizer st = new StreamTokenizer(br);
ArrayList<Integer> a = new ArrayList<>();
while (st.nextToken() != st.TT_EOF) {
a.add((int)st.nval); // infinite cycle
}
System.out.print(a);
}
}
}

Use Scanner on csv, iterate every time method is called

I am trying to parse a text document that has release notes and grab specific ones. To do that I have a csv with the desired release note keys. I want to scan the csv and use each key to find the matching section of the release note, and print the description that follows.
I would like to use the Scanner class for this to practice with it.
The csv looks like:
foobar-123,foobar-127,foobar-129
The release note text doc looks like:
foobar-123: ewkjhlq kghlhrekgh
foobar-124: lkjhfgrelgkj nberg
foobar-127: ljdfgl kjwneglkjn fdg
foobar-129: lguwlrkguj gwrlekgj werlktj
The issue I am running into is iterating through the csv. I seem to keep grabbing the first string in the csv. I am trying to figure out how to save my place in the csv, so every time the method is called, it goes to the next string.
I'm thinking I could create a variable that saves the last found string, and then use scanner to find that and then grab the next string. But that would require scanning through the csv each time I want to progress and which does not seem efficient. What would be the best way to iterate through the csv using the Scanner class?
Here is the code I have so far:
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.Scanner;
public class ReleaseNotesScan {
public static void main(String[] args) {
//Open csv file with issue keys
Scanner getIssueKeys = null;
try {
getIssueKeys = new Scanner(new FileReader("resources/Issues.txt"));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
//Open release notes
Scanner releaseNotes = null;
try {
releaseNotes = new Scanner(new FileReader("resources/Release notes text.txt"));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
//Get issue key from csv
String issueKey = Finders.issueKey(getIssueKeys);
//The below three lines are just for testing if I am iterating through the csv
System.out.println(issueKey);
Finders.issueKey(getIssueKeys);
System.out.println(issueKey);
//Get issue key and description
String description = Finders.sectionContent(releaseNotes, issueKey);
System.out.println(issueKey + ": " + description);
//Close csv
getIssueKeys.close();
//Close release notes
releaseNotes.close();
}
}
My Finders class:
import java.util.Scanner;
public class Finders {
//parse csv
public static String issueKey(Scanner findIssues) {
findIssues.useDelimiter(",");
String issue = findIssues.next();
return issue;
}
public static String sectionContent(Scanner releaseNotes, String heading) {
while (releaseNotes.hasNextLine()){
String found = releaseNotes.findInLine(heading);
if (found != null){
releaseNotes.findInLine(": ");
String grabIt = releaseNotes.nextLine();
return grabIt;
}
releaseNotes.nextLine();
}
releaseNotes.close();
return "Not found";
}
}
Here is some example code to demonstrate how the application can be structured. I made some assumptions that the input file "issues" as a string (instead of a file, for brevity). The issues are stored in an array and release notes in HashMap collection. The release notes are read from the file, tokenized (split with ":" as delimiter) as the issue and its release-note text. The issue is the key and the release-note is the value in the map.
Finally, iterate each issue and get the corresponding release-note from the map.
Example Code:
import java.util.*;
import java.io.*;
public class MatchIssues {
private static String [] issues;
private static Map<String,String> releseNotes = new HashMap<>();
public static void main(String [] args)
throws IOException {
getIssues();
getReleaseNotes();
for(String issue : issues) {
// Match release notes for the issue
System.out.println(releseNotes.get(issue));
}
}
private static void getIssues() {
String s = "foobar-123,foobar-127,foobar-129"; // use string for demo
issues = s.split(",");
System.out.println(Arrays.toString(issues));
}
private static void getReleaseNotes()
throws IOException {
BufferedReader reader =
new BufferedReader(new FileReader("release_notes.txt"));
String line = null;
while ((line = reader.readLine()) != null) {
String [] tokens = line.split(":");
releseNotes.put(tokens[0].trim(), tokens[1].trim());
}
System.out.println(releseNotes);
}
}
release_notes.txt:
foobar-123: aa ewk jhlq kghlhrekgh aa
foobar-124: bb lkjh fgrelgkj nberg bb
foobar-127: yy ljdfgl kjw neglkjn fdg yy
foobar-129: zz lgu wlrkguj gw rlekgj werlktj zz

Read a line and push into a line-stack until the end of file

I have to do a program and unfortunately I have no idea where to start. It's like we were doing very basic coding and then my teacher went on maternity leave and our substitute thinks we are further along then we actually are. I know how to ready from a file, but I do not know how to put the line into a stack from there.
These are the instructions
1) Read a line and push into a line-stack until the end of file 2) While line_stack is not empty a. Pop one element out and process the following i. Split elements in this line (i.e. numbers) using StringTokenzier ii. Push all numbers into number-stack iii. While number_stack is not empty 1. Pop a number 2. Print a character using that ascii number
If I understand the problem correctly you need to:
Represent a line as a java.lang.String.
Then using java.util.Stack create a Stack< String> and put all the lines there.
Use java.util.StringTokenizer to split each line into multiple parts. Each part will be a String itself.
Turn each part of the line into a number using Integer.valueOf(String)
Put all the numbers into a Stack< Integer>.
Print the right character for each number by casting integer value to char.
I think this may be the solution for your problem:
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.IOException;
import java.util.Stack;
import java.util.StringTokenizer;
public class LinesProcessor {
private static Stack<String> readLinesFromFile(String fileName) throws IOException {
Stack<String> lines = new Stack<>();
try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(fileName)))) {
String line = null;
while ((line = br.readLine()) != null) {
lines.push(line);
}
}
return lines;
}
private static void processNumbers(Stack<Integer> stackOfNumbers) {
while (!stackOfNumbers.empty()) {
Integer number = stackOfNumbers.pop();
System.out.print((char) number.intValue());
}
}
private static void processLine(String line) {
StringTokenizer tokenizer = new StringTokenizer(line, " ");
Stack<Integer> stackOfNumbers = new Stack<>();
while (tokenizer.hasMoreTokens()) {
Integer number = Integer.valueOf(tokenizer.nextToken());
stackOfNumbers.push(number);
}
processNumbers(stackOfNumbers);
}
private static void processLines(Stack<String> stackOfLines) {
while (!stackOfLines.empty()) {
String currentLine = stackOfLines.pop();
processLine(currentLine);
}
}
public static void main(String[] args) throws IOException {
if (args.length < 1) {
System.out.println("Name of file missing");
System.exit(1);
}
String fileName = args[0];
Stack<String> stackOfLines = readLinesFromFile(fileName);
processLines(stackOfLines);
}
}

How can I parse through a file for a string matching a generated string?

My bad for the title, I am usually not good at making those.
I have a programme that will generate all permutations of an inputted word and that is supposed to check to see if those are words (checks dictionary), and output the ones that are. Really I just need the last the part and I can not figure out how to parse through a file.
I took out what was there (now displaying the "String words =") because it really made thing worse (was an if statement). Right now, all it will do is output all permutations.
Edit: I should add that the try/catch was added in when I tried turning the file in a list (as opposed to the string format which it is currently in). So right now it does nothing.
One more thing: is it possible (well how, really) to get the permutations to display permutations with lesser characters than entered ? Sorry for the bad wording, like if I enter five characters, show all five character permutations, and four, and three, and two, and one.
import java.util.List;
import java.util.Scanner;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.io.IOException;
import org.apache.commons.io.FileUtils;
import static java.lang.System.out;
public class Permutations
{
public static void main(String[] args) throws Exception
{
out.println("Enter anything to get permutations: ");
Scanner scan = new Scanner(System.in);
String io = scan.nextLine();
String str = io;
StringBuffer strBuf = new StringBuffer(str);
mutate(strBuf,str.length());
}
private static void mutate(StringBuffer str, int index)
{
try
{
String words = FileUtils.readFileToString(new File("wordsEn.txt"));
if(index <= 0)
{
out.println(str);
}
else
{
mutate(str, index - 1);
int currLoc = str.length()-index;
for (int i = currLoc + 1; i < str.length(); i++)
{
change(str, currLoc, i);
mutate(str, index - 1);
change(str, i, currLoc);
}
}
}
catch(IOException e)
{
out.println("Your search found no results");
}
}
private static void change(StringBuffer str, int loc1, int loc2)
{
char t1 = str.charAt(loc1);
str.setCharAt(loc1, str.charAt(loc2));
str.setCharAt(loc2, t1);
}
}
If each word in your file is actually on a different line, maybe you can try this:
BufferedReader br = new BufferedReader(new FileReader(file));
String line = null;
while ((line = br.readLine()) != null)
{
... // check and print here
}
Or if you want to try something else, the Apache Commons IO library has something called LineIterator.
An Iterator over the lines in a Reader.
LineIterator holds a reference to an open Reader. When you have finished with the iterator you should close the reader to free internal resources. This can be done by closing the reader directly, or by calling the close() or closeQuietly(LineIterator) method on the iterator.
The recommended usage pattern is:
LineIterator it = FileUtils.lineIterator(file, "UTF-8");
try {
while (it.hasNext()) {
String line = it.nextLine();
// do something with line
}
} finally {
it.close();
}

Incorrect Output from CSV File

import java.util.Scanner;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Arrays;
import java.util.ArrayList;
/**
* Write a description of class ReadInCsv here.
*
* #author (Kevin Knapp)
* #version (10-10-2013)
*/
public class ReadInCsv
{
public static void main(String[] args)
{
String csvName = "Countries.csv";
File csvFile = new File(csvName);
ArrayList<String> nameList = new ArrayList<>();
ArrayList<String> popList = new ArrayList<>();
ArrayList<String> areaList = new ArrayList<>();
ArrayList<String> gdpList = new ArrayList<>();
ArrayList<String> litRateList = new ArrayList<>();
try
{
Scanner in = new Scanner(csvFile).useDelimiter(",");
while (in.hasNext())
{
String name = in.next();
nameList.add(name);
String pop = in.next();
popList.add(pop);
String area = in.next();
areaList.add(area);
String gdp = in.next();
gdpList.add(gdp);
String litRate = in.next();
litRateList.add(litRate);
}
in.close();
System.out.println(nameList);
System.out.println(popList);
System.out.println(areaList);
System.out.println(gdpList);
System.out.println(litRateList);
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
}
}
So im trying to read from a csv file and as it goes through it should add each scanned instance into a array list (im going to reference each element from these lists at a later point), but my outputs show that as soon as it reads something and adds it, it skips to the next line before reading the next string, i need it to read straight across, not diagonally
im sure im just missing something very simple, I just began learning java about a week ago, thanks for the help
A big problem with this method is that unless each line in the file ends in a comma, newlines will not be delimited. A better way is to read each line in, split on commas, and add the values to the ArrayLists one line at a time:
Scanner in = new Scanner(csvFile);
while (in.hasNextLine()) {
String[] fields = in.nextLine().split(",");
if (fields.length == 5) {
nameList.add(fields[0]);
popList.add(fields[1]);
areaList.add(fields[2]);
gdpList.add(fields[3]);
litRateList.add(fields[4]);
} else {
// Bad line...do what you want to show error here
}
}
An even better way is to use a Java library dedicated to reading CSV files. A quick Google search should turn up some good ones.

Categories