I have a text file named "message.txt" which is read using Buffer Reader. Each line of the text file contains both "word" and "meaning" as given in this example:
"PS:Primary school"
where PS - word, Primary school - meaning
When the file is being read, each line is tokenized to "word" and "meaning" from ":".
If the "meaning" is equal to the given input string called "f_msg3", "f_msg3" is displayed on the text view called "txtView". Otherwise, it displays "f_msg" on the text view.
But the "if condition" is not working properly in this code. For example if "f_msg3" is equal to "Primary school", the output on the text view must be "Primary school". But it gives the output as "f_msg" but not "f_msg3". ("f_msg3" does not contain any unnecessary strings.)
Can someone explain where I have gone wrong?
try {
BufferedReader file = new BufferedReader(new InputStreamReader(getAssets().open("message.txt")));
String line = "";
while ((line = file.readLine()) != null) {
try {
/*separate the line into two strings at the ":" */
StringTokenizer tokens = new StringTokenizer(line, ":");
String word = tokens.nextToken();
String meaning = tokens.nextToken();
/*compare the given input with the meaning of the read line */
if(meaning.equalsIgnoreCase(f_msg3)) {
txtView.setText(f_msg3);
} else {
txtView.setText(f_msg);
}
} catch (Exception e) {
txtView.setText("Cannot break");
}
}
} catch (IOException e) {
txtView.setText("File not found");
}
Try this
............
meaning = meaning.replaceAll("\\s+", " ");
/*compare the given input with the meaning of the read line */
if(meaning.equalsIgnoreCase(f_msg3)) {
txtView.setText(f_msg3);
} else {
txtView.setText(f_msg);
}
............
Otherwise comment the else part, then it will work.
I don't see any obvious error in your code, maybe it is just a matter
of cleaning the string (i.e. removing heading and trailing spaces, newlines and so on) before comparing it.
Try trimming meaning, e.g. like this :
...
String meaning = tokens.nextToken();
if(meaning != null) {
meaning = meaning.trim();
}
if(f_msg3.equalsIgnoreCase(meaning)) {
txtView.setText(f_msg3);
} else {
txtView.setText(f_msg);
}
...
A StringTokenizer takes care of numbers (the cause for your error) and other "tokens" - so might be considered to invoke too much complexity.
String[] pair = line.split("\\s*\\:\\s*", 2);
if (pair.length == 2) {
String word = pair[0];
String meaning = pair[1];
...
}
This splits the line into at most 2 parts (second optional parameter) using a regular expression. \s* stands for any whitespace: tabs and spaces.
You could also load all in a Properties. In a properties file the format key=value is convention, but also key:value is allowed. However then some escaping might be needed.
ArrayList vals = new ArrayList();
String jmeno = "Adam";
vals.add("Honza");
vals.add("Petr");
vals.add("Jan");
if(!(vals.contains(jmeno))){
vals.add(jmeno);
}else{
System.out.println("Adam je už v seznamu");
}
for (String jmena : vals){
System.out.println(jmena);
}
try (BufferedReader br = new BufferedReader(new FileReader("dokument.txt")))
{
String aktualni = br.readLine();
int pocetPruchodu = 0;
while (aktualni != null)
{
String[] znak = aktualni.split(";");
System.out.println(znak[pocetPruchodu] + " " +znak[pocetPruchodu + 1]);
aktualni = br.readLine();
}
br.close();
}
catch (IOException e)
{
System.out.println("Nezdařilo se");
}
try (BufferedWriter bw = new BufferedWriter(new FileWriter("dokument2.txt")))
{
int pocetpr = 0;
while (pocetpr < vals.size())
{
bw.write(vals.get(pocetpr));
bw.append(" ");
pocetpr++;
}
bw.close();
}
catch (IOException e)
{
System.out.println("Nezdařilo se");
}
Related
I created a list in a FlightBookingSystem Java Class, as you can see below:
public List<Flight> getFlights() {
List<Flight> out = new ArrayList<>(flights.values());
return Collections.unmodifiableList(out);
}
Which I imported from a text file show below:
1::LX2500::Birmingham::Munich::2020-11-25::
2::LX2500::Denmark::London::2021-07-01::
3::LY2380::London::France::2021-06-28::
It's a basic text file which holds the information for each flight
Here is the code I wish to adjust:
public Flight execute(FlightBookingSystem flightBookingSystem, int id)
throws FlightBookingSystemException {
List<Flight> flights = flightBookingSystem.getFlights();
for (Flight Flight : flights) {
if (Flight.getFlightNumber() == flightNumber) {
System.out.println(Flight.getFlightNumber() + " flight(s)");
return flights.get(id);
}
System.out.println(((Flight) flights).getFlightNumber() + " flight(s)");
}
return flights.get(id);
}
How do I change that code so that it allows the user to retrieve one single record from the text file?
Why not to retrieve all and get the one you want by key or id using HashMap ?
If you still want the other option, you can read the text file line by line, and check if it startsWith(...) and the to retrieve this line.
Code example:
try (BufferedReader br = new BufferedReader(new FileReader(file)))
{
String line;
while ((line = br.readLine()) != null)
{
// Add here 'if' condition and parse your line
}
}
Your question is a bit confusing. Your title states:
How do you allow a user to retrieve values from a list in Java?
and the very last line of your post states:
How do I change that code so that it allows the user to retrieve
one single record from the text file?
Which is it, from a List or from a text file?
If it's from a List because you already have the mechanism available then is could be something similar to this:
public String getFlightInfo(String flightNumber) {
List<Flight> flights = FlightBookingSystem.getFlights();
for (Flight flite : flights) {
if(flite.getFlightNumber().equalsIgnoreCase(flightNumber)){
return flite.toString();
}
}
JOptionPane.showMessageDialog(null, "<html>Flight number <font color=red><b>"
+ flightNumber + "</b></font> could not be found!</html>", "Flight Not "
+ "Found", JOptionPane.INFORMATION_MESSAGE);
return null;
}
The code above assumes you have an overriden toString() method applied to the Flight class. If you don't then create one.
If it's actually from file then it could be something like this:
public String getFlightInfo(String flightNumber) {
// 'Try With Resouces' to auto-close reader.
try (BufferedReader reader = new BufferedReader(new FileReader("Flights.txt"))) {
String fileLine = "";
while ((fileLine = reader.readLine()) != null) {
fileLine = fileLine.trim();
// If by chance the file line read in is blank then skip it.
if (fileLine.isEmpty()) {
continue;
}
// First, remove the double colons at the end of line (if any).
if (fileLine.endsWith("::")) {
fileLine = fileLine.substring(0, fileLine.lastIndexOf("::")).trim();
}
/* Split each read in file line based on a double colon delimiter.
The "\\s*" within the regex for the split method handles any
cases where the might be one or more whitespaces before or after
the double-colon delimiter. */
String[] lineParts = fileLine.split("\\s*\\:\\:\\s*");
if(lineParts[1].equalsIgnoreCase(flightNumber)){
// At this point you could just return the line, for example:
// return fileLine;
// or you can return a string with a little more structure:
return new StringBuilder("Flight ID: ").append(lineParts[0])
.append(", Flight #: ").append(lineParts[1]).append(", From: ")
.append(lineParts[2]).append(", To: ").append(lineParts[3])
.append(", Date: ").append(lineParts[4]).toString();
}
}
}
catch (FileNotFoundException ex) {
JOptionPane.showMessageDialog(null, ex.getMessage());
}
catch (IOException ex) {
JOptionPane.showMessageDialog(null, ex.getMessage());
}
JOptionPane.showMessageDialog(null, "<html>Flight number <font color=red><b>"
+ flightNumber + "</b></font> could not be found!</html>", "Flight Not "
+ "Found", JOptionPane.INFORMATION_MESSAGE);
return null;
}
I have a code which replace some characters (space, tabulator) of string introduced by the user, and then shows the text:
System.out.println("Text:");
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
try {
String text = bufferedReader.readLine();
text = text.replaceAll("\n", "");
text = text.replaceAll(" ", "");
text = text.replaceAll("\t", "");
System.out.println(text);
} catch (IOException e) {
}
But when I paste a text of varios lines:
First Substring Introduced
Second Substring Introduced
Third Substring Introduced
it shows just the substring before the first newline like:
firstSubtringIntroduced
I want to obtain the next result of whole pasted text:
FirstSubstringIntroducedSecondSubstringIntroducedThirdSubstringIntroduced
You are reading just one line, the first one:
String text = bufferedReader.readLine(); //just one line
That's why you got that output that only shows the first line processed. You should make a loop in order to read all of the lines you are entering:
while((text=bufferedReader.readLine())!=null)
{
text = text.replaceAll("\n", "");
text = text.replaceAll(" ", "");
text = text.replaceAll("\t", "");
System.out.print(text);
}
The first loop will print FirstSubtringIntroduced, the second SecondSubstringIntroduced, and so on, until all the lines are processed.
Try aggregating all lines together, after removing tab and space from each line:
StringBuilder sb = new StringBuilder();
String text = "";
try {
while ((text = br.readLine()) != null) {
text = text.replaceAll("[\t ]", "");
sb.append(text);
}
}
catch (IOException e) {
}
System.out.println(sb);
The issue here is that your BufferedReader is reading one line at a time.
As an alternative, and closer to your current solution, you could just using System.out.print, which does not automatically print a newline, instead of System.out.println:
try {
while ((text = br.readLine()) != null) {
text = text.replaceAll("[\t ]", "");
System.out.print(text);
}
}
catch (IOException e) {
}
Note that String#replaceAll expects a regular expression. String#replace replaces all occurrences of the first argument with the second argument (which is what you want).
System.out.println(text.replace("\n", "").replace("\r", ""));
The method names are a little bit confusing.
public static void main(String args[]) {
System.out.println("Text:");
StringBuilder stringBuilder = new StringBuilder();
try (InputStreamReader inputStreamReader = new InputStreamReader(System.in);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
Scanner scanner = new Scanner(bufferedReader);
) {
while (scanner.hasNext()) {
stringBuilder.append(scanner.next());
}
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(stringBuilder.toString());
}
I do think this is what you need.
I have a java program that can read multiple files and replace values accordingly. However, I am struggling to apply a condition to it and apply the changes only when a certain condition is met. For example, if the file contains this specific character ':20:' then apply the changes otherwise leave the text file as it is.
The problem here is, since I don't have fields to look for to apply the condition accordingly I don't know how these can be applied to such a text file which contains just data like : (12345555555) 233344 100 :20:aaa.
I also looked at using the contains() method to look into the file to find the value I want then apply the changes but couldn't make it work.
public class TextFm
{
public static void main(String[] args)
{
File folder = new File("C:\\tmp");
File[] listOfFiles = folder.listFiles();
for(File file : listOfFiles)
{
replaceText(file);
}
}
public static void replaceText(File file)
{
try
{
BufferedReader reader = new BufferedReader(new FileReader(file));
String line = "", oldtext = "";
while ((line = reader.readLine()) != null)
{
oldtext = oldtext + line + System.lineSeparator();
}
reader.close();
String replacedtext = oldtext.replaceAll("100", "200");
FileWriter writer = new FileWriter(file);
writer.write(replacedtext);
writer.close();
System.out.println("Done");
} catch (IOException ioe)
{
ioe.printStackTrace();
}
}
}
Using contains() method will work fine in this case. You can do that like this:
String line = "", oldtext = "";
while ((line = reader.readLine()) != null)
{
oldtext = oldtext + line + System.lineSeparator();
}
reader.close();
if(oldtext.contains(":20:")) {
String replacedtext = oldtext.replaceAll("100", "200");
FileWriter writer = new FileWriter(file);
writer.write(replacedtext);
writer.close();
System.out.println("Done");
}
public static void replaceText(File file)
{
try
{
Charset charset = Charsets.defaulCharset();
String oldText = new String(Files.readAllBytes(file.toPath()),
charset);
if (!oldText.contains(":20")) {
return;
}
if (!oldText.matches("(?s).*you (idiot|unspeakable).*")) {
return;
}
String replacedtext = oldtext.replace("100", "200");
replacedtext = replacedtext .replaceAll("\\d", "X"); // Digit X-ed out
if (!replacedText.equals(oldText)) {
Files.write(file.toPath(), replacedText.getBytes(charset));
}
System.out.println("Done");
} catch (IOException ioe)
{
ioe.printStackTrace();
}
}
For speed one should not collect the file contents with a String and +. Better use a StringBuilder, or the very nice Files class.
Finding text goes either by contains or by a regular expression match.
Replacement can be done by either too.
The replace, replaceFirst and replaceAll methods return the original string when nothing could be replaced.
Regex (?s) lets . (=any char) also match line breaks.
What I want to do is set a String called nameWithYear to be equal to be movies[0] + "(" + movies[1]+")" (So "Movie Title (Year)") from text being parsed off a CSV.
Whenever I try, I am experiencing an issue where I keep on getting an array out of bounds error. I tried setting the string equal to only movies[0], it works with success. When I try to set it to movies[1] by itself, it fails. I can do a System.out that includes element [1], and it outputs just fine with no issues. So in other words, for some reason, I can only include element[0] in the string and not element[1]. So I am assuming it has something to do with declaring the value for the string. Just not sure what.
The code is as follows:
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class CSVParsing {
public String parseCSV() {
String csvFile = "C:\\Users\\RAY\\Desktop\\movies.csv";
BufferedReader br = null;
String nameWithYear = new String();
String line = "";
String csvSplitBy = ",";
try {
br = new BufferedReader(new FileReader(csvFile));
while ((line = br.readLine()) != null) {
// use comma as separator
if (line.charAt(0) == '"')
{
csvSplitBy = "\",";
}
else
{
csvSplitBy = ",";
}
String[] movies = line.split(csvSplitBy);
nameWithYear = ""+ movies[0]+" ("+movies[1]+")";
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return nameWithYear;
}
public static void main (String[] args)
{
CSVParsing obj = new CSVParsing();
String testString = obj.parseCSV();
}
}
Note that it is not 100% complete, I am testing it in small chunks to make sure it is doing everything as I want it to do.
UPDATE: Found out that it was related to blank year entries as part of the CSV. How do I handle that? The program cuts off once it finds the year entry to be blank.
UPDATE 2: I solved it with my own but of research. I am taking the results after the split() and putting them into an ArrayList. That way, I could handle blank entries in the year column by replacing them with another value.
I guess problem is with your input file.Make sure your input is not of the form
"cauchy hep(21\10\1991) ","cauchy hep" .Notice the space between ) and " remove the space if any since:
if (line.charAt(0) == '"')
{
csvSplitBy = "\",";
}
else
{
csvSplitBy = ",";
}
csvSplitBy equals "\"," no space with the last character of string. If your file doesn't follow the pattern you specified whole line or whole file wil be treated as single string and will be stored in movies[0] .So there will no string at index 1 of movies that's why ArrayIndexOutOfBound.
Remove the space Or you can include the space the beginning " \"," again notice the space between " \"," .It will solve the problem.
split() method returns one element in the array this means that the separator does not exist in the line variable.
line.contains(csvSplitBy);// will be evaluated to false in case of one item is returned by split();
Make sure that the CSV file is comma separated .. or the data has more than one column (CSV formatted correctly )
I hope this could help!
I would like to implement a task of string matching from a large text file.
1. replace all the non-alphanumeric characters
2. count the number of a specific term in the text file. For example, matching term "tom". The matching is not case sensitive.so term "Tom" should me counted. However the term tomorrow should not be counted.
code template one:
try {
in = new BufferedReader(new InputStreamReader(new FileInputStream(inputFile));
} catch (FileNotFoundException e1) {
System.out.println("Not found the text file: "+inputFile);
}
Scanner scanner = null;
try {
while (( line = in.readLine())!=null){
String newline=line.replaceAll("[^a-zA-Z0-9\\s]", " ").toLowerCase();
scanner = new Scanner(newline);
while (scanner.hasNext()){
String term = scanner.next();
if (term.equalsIgnoreCase(args[1]))
countstr++;
}
}
} catch (IOException e) {
e.printStackTrace();
}
code template two:
try {
in = new BufferedReader(new InputStreamReader(new FileInputStream(inputFile));
} catch (FileNotFoundException e1) {
System.out.println("Not found the text file: "+inputFile);
}
Scanner scanner = null;
try {
while (( line = in.readLine())!=null){
String newline=line.replaceAll("[^a-zA-Z0-9\\s]", " ").toLowerCase();
String[] strArray=newline.split(" ");//split by blank space
for (int =0;i<strArray.length;i++)
if (strArray[i].equalsIgnoreCase(args[1]))
countstr++;
}
}
} catch (IOException e) {
e.printStackTrace();
}
By running the two codes, I get the different results, the Scanner looks like to get the right one.But for the large text file, the Scanner runs much more slower than the latter one. Anyone who can tell me the reason and give a much more efficient solution.
In your first approch. You dont need to use two scanner. Scanner with "" is not good choice for the large line.
your line is already Converted to lowercase. So you just need to do lowercase of key outside once . And do equals in loop
Or get the line
String key = String.valueOf(".*?\\b" + "Tom".toLowerCase() + "\\b.*?");
Pattern p = Pattern.compile(key);
word = word.toLowerCase().replaceAll("[^a-zA-Z0-9\\s]", "");
Matcher m = p.matcher(word);
if (m.find()) {
countstr++;
}
Personally i would choose BufferedReader approach for the large file.
String key = String.valueOf(".*?\\b" + args[0].toLowerCase() + "\\b.*?");
Pattern p = Pattern.compile(key);
try (final BufferedReader br = Files.newBufferedReader(inputFile,
StandardCharsets.UTF_8)) {
for (String line; (line = br.readLine()) != null;) {
// processing the line.
line = line.toLowerCase().replaceAll("[^a-zA-Z0-9\\s]", "");
Matcher m = p.matcher(line);
if (m.find()) {
countstr++;
}
}
}
Gave Sample in Java 7. Change if required!!