I have just gotten into java, and i was working on an elementary project.
I tried to create a program which would locate the desired string within a txt which stored some activities, and the id associated with them (e.g:
1 Sleep
2 Exercise
3 Socializing
4 Studying
5 Transportation
6 Eating)
The code is as follows
import java.io.*;
import java.util.*;
import javax.swing.JOptionPane;
public class ReadNSearchFile {
private static Scanner x;
public static void main(String[] args) {
String filepath = "C:\\Users\\John\\Desktop\\Java crap\\Activities.txt";
String searchTerm = "Sleep";
readRecord(searchTerm, filepath);
}
public static void readRecord(String searchTerm, String filepath) { //it will search for the ID
boolean found = false;
String ID = ""; String activity = "";
try {
x = new Scanner(new File(filepath));
x.useDelimiter("[\n\s]"); //used to separate fields in a file eg words
while(x.hasNext() && !found) {
ID = x.next();
activity = x.next();
if(activity.equals(searchTerm)) {
found = true;
}
}
if(found) {
JOptionPane.showMessageDialog(null, "ID:" + ID + "Activity: " + activity);
}else if(!found) {
JOptionPane.showMessageDialog(null, "Record not found");
}
}
catch(Exception e){
JOptionPane.showMessageDialog(null, "error");
}
}
}
The desired activity is contained within the text, however is not located through the code.
Why is this?
Related
Clarification: I have a text file with multiple lines and I want to separate specific lines into fields for an object.
I have been banging my head against a wall for about 3 days now, and I feel as if I'm overthinking this.
import java.io.*;
import java.util.*;
public class ReadFile {
public static void main(String[] args) throws FileNotFoundException {
String fileName = null;
Scanner input = new Scanner(System.in);
System.out.print("Enter file path: ");
fileName = input.nextLine();
input.close();
String fileText = readFile(fileName);
System.out.println(fileText);
}
public static String readFile(String fileName) throws FileNotFoundException {
String fileText = "";
String lineText = "";
File newFile = new File(fileName);
if (newFile.canRead()) {
try (Scanner scanFile = new Scanner(newFile)) {
while (scanFile.hasNext()) {
lineText = scanFile.nextLine();
if (lineText.startsWith("+")) {
}
else {
fileText = fileText + lineText + "\n";
}
}
} catch (Exception e) {
System.out.println(e);
}
} else {
System.out.println("No file found. Please try again.");
}
return fileText;
}
}
My goal is to take a file that looks similar to this (this is the whole file, imagine a .txt with exactly this in it):
Name of Person
----
Clothing:
Graphic TeeShirt
This shirt has a fun logo of
depicting stackoverflow and a horizon.
****
Brown Slacks
These slacks reach to the floor and
barely cover the ankles.
****
Worn Sandals
The straps on the sandals are frayed,
and the soles are obviously worn.
----
Then I need to extract the top line (e.g.: "Graphic TeeShirt") as a type of clothing the object is wearing, then "This shirt has a fun [...]" as the description of that object.
I have another .java with setters/getters/constructors, but I can't figure out how to iterate through the text file.
Edit: I know I loop through each line, but I need to create an object that has the person's name as a field, the item name (Graphic TeeShirt) as a field, then the description under the item as the next field. Then the next object will be a new object with person's name as a field, the next item (Brown Slacks) as a field, then the description as a field.
I don't know how to separate the lines in to the fields I need.
As I mentioned, the data file format is lousy, which is the real source of the problem, but your delimiters can be used to help out a little. You might approach the problem this way. Obviously don't dump your code like I've done into main but this might start you off. You still need to separate the clothing names from their descriptions but you should get the idea from the below. You can then start making a pojo out of the data.
Pass the path to your data file to this app and look out for the metadata debug outputs of 'Name' and 'Item'.
import java.util.Scanner;
import java.nio.file.Paths;
public class PersonParser {
public static void main(String[] args) {
try {
try (Scanner scPeople = new Scanner(Paths.get(args[0]))) {
scPeople.useDelimiter("----+");
int tokenCount = 0;
while (scPeople.hasNext()) {
String token = scPeople.next();
if (tokenCount % 2 == 0) {
System.out.printf("Name: %s", token);
} else {
// Parse clothing
Scanner scClothing = new Scanner(token);
scClothing.useDelimiter("\\*\\*\\*+");
while (scClothing.hasNext()) {
String item = scClothing.next();
System.out.printf("Item: %s", item);
}
}
tokenCount++;
}
}
} catch (Throwable t) {
t.printStackTrace();
}
}
}
The following code is according to the details in your question, namely:
The sample file in your question is the entire file.
You want to create instances of objects that have the following three attributes:
Person's name.
Name of an item of clothing.
Description of that item.
Note that rather than ask the user for the name of the file, I simply use a hard-coded file name. Also note that method toString, in the below code, is simply for testing purposes. The code also uses try-with-resources and method references.
public class ReadFile {
private static final String DELIM = "****";
private static final String LAST = "----";
private String name;
private String item;
private String description;
public void setName(String name) {
this.name = name;
}
public String getItem() {
return item;
}
public void setItem(String item) {
this.item = item;
}
public void setDescription(String description) {
this.description = description;
}
public String toString() {
return String.format("%s | %s | %s", name, item, description);
}
public static void main(String[] strings) {
try (FileReader fr = new FileReader("clothing.txt");
BufferedReader br = new BufferedReader(fr)) {
String line = br.readLine();
String name = line;
br.readLine();
br.readLine();
line = br.readLine();
String item = line;
List<ReadFile> list = new ArrayList<>();
ReadFile instance = new ReadFile();
instance.setName(name);
instance.setItem(item);
line = br.readLine();
StringBuilder description = new StringBuilder();
while (line != null && !LAST.equals(line)) {
if (DELIM.equals(line)) {
instance.setDescription(description.toString());
list.add(instance);
instance = new ReadFile();
instance.setName(name);
description.delete(0, description.length());
}
else {
if (instance.getItem() == null) {
instance.setItem(line);
}
else {
description.append(line);
}
}
line = br.readLine();
}
if (description.length() > 0) {
instance.setDescription(description.toString());
list.add(instance);
}
list.forEach(System.out::println);
}
catch (IOException xIo) {
xIo.printStackTrace();
}
}
}
Running the above code produces the following output:
Name of Person | Graphic TeeShirt | This shirt has a fun logo ofdepicting stackoverflow and a horizon.
Name of Person | Brown Slacks | These slacks reach to the floor andbarely cover the ankles.
Name of Person | Worn Sandals | The straps on the sandals are frayed,and the soles are obviously worn.
It's not clear what you want to achieve and what is your issue exactly. You said that you can't figure out how to iterate through a text file, so let's dive into this fairly straightforward task.
In general, you have a valid, but the overcomplicated method for reading a file. Modern versions of Java provide a lot simpler methods and it's better to use them (only if you're not implementing some test task to understand how everything is working under the hood).
Please see my example below for reading a file line by line using Java NIO and Streams APIs:
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Scanner;
import java.util.stream.Stream;
public class Test {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("Enter file path: ");
String fileName = input.nextLine();
input.close();
Path path = Paths.get(fileName);
try (Stream<String> lines = Files.lines(path)) {
lines.filter(line -> {
// filter your lines on some predicate
return line.startsWith("+");
});
// do the mapping to your object
} catch (IOException e) {
throw new IllegalArgumentException("Incorrect file path");
}
}
}
This should allow you to filter the lines from your files based on some predicate and later to the mapping to your POJO if you intend to do so.
If you have any other issues besides reading the file and filtering its content, please add clarification to your questions. Preferably, with examples and test data.
I am trying to get the GETTER of "FileHandler.java" to return the value(final_match) to "main.java" and out put. Problem is that final_match outputs as 0. In "FileHandler.java" Outside of my getter final_match has the correct value, but when called/returned from the GETTER value is plain 0
main.java
package textreader;
import java.io.File;
import java.util.ArrayList;
import java.util.Scanner;
public class main {
public String data = "";
public static void main(String[] args) {
Scanner user_input = new Scanner(System.in);
final File directory = new File("E:\\test\\filename.txt");
// final File directory2 = new File("E:\\test\\filename2.txt");
ArrayList<File> f = new ArrayList<>();
f.add(directory);
// f.add(directory2);
final String words;
System.out.println("The word you would like to search for. ");
System.out.println("----------------------------------------");
words = user_input.next();
main aMain = new main(f, words);
}
main(ArrayList<File> f, String words) { //constructor
ArrayList<FileHandler> threadArray = new ArrayList<>();//arraylist of type filehandler
for (File file : f) {
FileHandler fh = new FileHandler(this, words, file);// instance of filehandler = fh
threadArray.add(fh);
fh.start();
for (FileHandler x : threadArray) {
if (x.isFinished()) {
x.setFinished(true);
synchronized (x) {
x.notify();// notify next thread to continue
}
}
int answer = x.getfinal_match(); // CALLING THE GETTER FOR VALUE
System.out.println("----------------------------------------");
System.out.println("this word has appeared: " + answer + " times.");
System.out.println("----------------------------------------");
}
}
}
}
FileHander.java
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
public class FileHandler extends Thread {
BufferedReader br = null;
FileReader fr = null;
String words;
File file;
int counter;
int match;
int final_match;
boolean done = true;
boolean finished;
private final main main;
public FileHandler(main instance, String words, File file) { //constructor
this.words = words;
this.file = file;
this.main = instance;
}
#Override
public synchronized void run() {
try {
fr = new FileReader(this.file);//file path
br = new BufferedReader(fr);// reads the words in the file
String theLine;
while ((theLine = br.readLine()) != null) {
String List[] = theLine.split(" ");
for (String List1 : List) {
if (List1.equals(List[counter])) {// of words are the same as "word" increment match
match++; //Amount of occurrences
}
counter++;//loop through each word
}
synchronized (this) {
//System.out.println("test2 " + match);
this.finished = true;
}
}
} catch (IOException e) {
} finally {
try {
if (br != null) {
br.close();
}
if (fr != null) {
fr.close();
}
} catch (IOException ex) {
}
}
final_match = match;
System.out.println("testing " + final_match); // THIS TEST WORKS AS VALUE WAS OUTPUTTED AS 5
}
public void setfinal_match(int test) {
final_match = test;
}
public Integer getfinal_match() {
System.out.println("testing 123456 " + final_match); // THIS VALUE DOES NOT WORK AS IT OUTPUTS A BIG FAT 0
return final_match;
}
public boolean isFinished() {
return this.finished;
}
public void setFinished(boolean finished) {
this.finished = finished;
}
}
//OUTPUT
//run:
//the word you would like to search for.
//----------------------------------------
//dog
//testing GETTER 123456 0
//----------------------------------------
//this word has appeared: 0 times.
//----------------------------------------
//testing 5
//BUILD SUCCESSFUL (total time: 2 seconds)
//EXPECTED OUTPUT
//run:
//The word you would like to search for.
//----------------------------------------
//dog
//testing GETTER 123456 5
//----------------------------------------
//this word has appeared: 5 times. (THIS IS THE MAIN VALUE THAT HAS TO CHANGE)
//----------------------------------------
//testing 5
//BUILD SUCCESSFUL (total time: 2 seconds)
Your final_match is 0 at the time of the output, since the thread starts and is not finished yet, when you output the value of final_match.
I have created a simple program that takes a title and a note which you enter then you have a choice to export the notes to txt file using BufferedWriter however because each note is a object which is stored in a ArrayList when storing them I iterate through a for enhanced loop it keeps duplicating each note as I iterate through all the object.
Note Class
import java.util.*;
public class Notes
{
private String notes;
private String titleOfNotes;
Scanner input = new Scanner(System.in);
public Notes()
{
titleOfNote(input);
takeNotes(input);
}
public void takeNotes(Scanner x)
{
System.out.println("Please Enter Your Note");
notes = x.nextLine();
}
public void titleOfNote(Scanner y)
{
System.out.println("Please Enter Title");
titleOfNotes = y.nextLine();
}
public String toString()
{
return "Title: " + titleOfNotes + "\t" + notes;
}
}
App Class //Does mostof the Work
import java.util.*;
import java.io.*;
public class App
{
private int exit = 0;
private int createANote;
private int displayTheNotes;
private int inputFromUser;
public boolean haveFileBeenWritten = true;
File file = new File("Notes.txt");
Scanner input = new Scanner(System.in);
ArrayList<Notes> arrayOfNotes = new ArrayList<Notes>();
public void makeNoteObject()
{
arrayOfNotes.add(new Notes());
}
public void displayAllTheNote(ArrayList<Notes> n)
{
for(Notes singleObjectOfNote : n)
{
System.out.println(singleObjectOfNote);
}
}
public void programUI(){
while(exit != 1)
{
System.out.println("1. Create A Note");
System.out.println("2. Display The Notes");
System.out.println("3. Exit");
System.out.println("4. Export to text file");
System.out.println("Enter Your Operation");
inputFromUser = input.nextInt();
if(inputFromUser == 1)
{
makeNoteObject();
}
else if(inputFromUser == 2)
{
displayAllTheNote(arrayOfNotes);
}
else if(inputFromUser == 3)
{
System.out.println("Exited");
exit = 1;
}
else if(inputFromUser == 4)
{
makeATxtFileFromNotes(arrayOfNotes);
System.out.println("Textfile created filename: " + file.toString());
}
else
{
System.out.println("You Select A Invalid Command");
}
}
}
public void makeATxtFileFromNotes(ArrayList<Notes> x)
{
try (BufferedWriter bw = new BufferedWriter(new FileWriter(file,haveFileBeenWritten)))
{
//Problem here!
for(Notes singleObjectOfNotes : x)
{
bw.write(singleObjectOfNotes.toString());
bw.newLine();
}
}catch(IOException e)
{
System.out.println("Cant Write File: " + file.toString());
haveFileBeenWritten = false;
}
}
public App()
{
programUI();
}
public static void main(String[]args)
{
App objectOfApp = new App();
}
}
I am new to Java so my code my not be the best!
If your problem is that you only need to see current list's Notes excluding the previous', it's because of this line:
try (BufferedWriter bw = new BufferedWriter(new FileWriter(file,haveFileBeenWritten)))
By default, haveFileBeenWritten is true so based on the FileWriter API it will APPEND on the existing file Notes.txt so if you don't want that, change it to false.
Parameters:
file - a File object to write to
append - if true, then bytes will be
written to the end of the file rather than the beginning
EDIT: To access List<> elements, use get().
Example:
int size = myList.size();
for (int i = 0 ; i < size ; i++) {
//...
Notes note = myList.get(i);
//...
}
So I'm making a program that will store the meetings I've had with some kids I'm tutoring. It'll keep tabs on the meeting times, discussions, and how many hours I've done. I know how to write all the methods to do that, but my issue is that the program will only hold that information for the session that the program is open... how would I go about storing this information and accessing it after the program is closed and opened again?
This is some excerpts from a test score keeper program I did in java class that has this same issue...
public class Student {
private String name;
private int test1;
private int test2;
private int test3;
public Student() {
name = "";
test1 = 0;
test2 = 0;
test3 = 0;
}
public Student(String nm, int t1, int t2, int t3){
name = nm;
test1 = t1;
test2 = t2;
test3 = t3;
}
public Student(Student s){
name = s.name;
test1 = s.test1;
test2 = s.test2;
test3 = s.test3;
}
public void setName(String nm){
name = nm;
}
public String getName (){
return name;
}
public void setScore (int i, int score){
if (i == 1) test1 = score;
else if (i == 2) test2 = score;
else test3 = score;
}
public int getScore (int i){
if (i == 1) return test1;
else if (i == 2) return test2;
else return test3;
}
public int getAverage(){
int average;
average = (int) Math.round((test1 + test2 + test3) / 3.0);
return average;
}
public int getHighScore(){
int highScore;
highScore = test1;
if (test2 > highScore) highScore = test2;
if (test3 > highScore) highScore = test3;
return highScore;
}
public String toString(){
String str;
str = "Name: " + name + "\n" + //\n makes a newline
"Test 1: " + test1 + "\n" +
"Test 2: " + test2 + "\n" +
"Test 3: " + test3 + "\n" +
"Average: " + getAverage();
return str;
}
}
If your data is not too big or complicated - something that you could save in a Rolodex in days gone by - you can save it to a file. Add methods to your class that will format the data properly and write it to a given OutputStream or Writer or whatever. And a method that will read it back.
To write to the file, add an option "save" in your program menu, and when it's chosen, open a file, iterate through your data, and call the saving method for each of your object.
To read from the file, add an option "load" in your program menu, and when it's chosen, open a file, and use your method of reading for each object.
The method for reading can be a static method in the class, that will first see if there are any data in the file and if it can read them properly, and only if it did, will create an object and return it (otherwise return null). There are other options, but this is the one that most encapsulates the needs of the object.
There is also an option to serialize and deserialize each object and put it in an object stream.
If the data is complicated, and there are many objects with various relations between them, you should use a database. This will require learning some database design and SQL.
To demonstrate the file reading/writing idea, add to your Student class:
public void save(PrintWriter outfile) {
outfile.format("%s|%d|%d|%d%n", name, test1, test2, test3);
}
This will write a line with the fields separated by "|" (vertical bar). Of course, you'll have to make sure none of the student names has a vertical bar in it. So you'll need to modify your 4-parameter constructor and your setter:
public Student(String nm, int t1, int t2, int t3) {
name = nm.replaceAll("\\|", "");
test1 = t1;
test2 = t2;
test3 = t3;
}
public void setName(String nm) {
name = nm.replaceAll("\\|", "");
}
Now, to read the file, we add a static method:
public static Student load(BufferedReader infile) throws IOException {
String line;
line = infile.readLine();
// Check if we reached end of file
if (line == null) {
return null;
}
// Split the fields by the "|", and check that we have no less than 4
// fields.
String[] fields = line.split("\\|");
if (fields.length < 4) {
return null;
}
// Parse the test scores
int[] tests = new int[3];
for (int i = 0; i < 3; i++) {
try {
tests[i] = Integer.parseInt(fields[i + 1]);
} catch (NumberFormatException e) {
// The field is not a number. Return null as we cannot parse
// this line.
return null;
}
}
// All checks done, data ready, create a new student record and return
// it
return new Student(fields[0], tests[0], tests[1], tests[2]);
}
You can see that this is more complicated, because you need to check that everything is OK at every step. In any case when things are not OK, we return null but of course, you can decide to just display a warning and read the next line. You'll have to return null when there are no more lines, though.
So, assuming we have a List<Student> students, here is how we write it to a file. I just chose "students.txt" but you can specify a full path leading where you want it. Note how I'm making a backup of the old file before I open the new file. If something goes wrong, at least you have the previous version of the file.
File f = new File("students.txt");
if (f.exists()) {
File backup = new File("students.bak");
if ( ! f.renameTo(backup) ) {
System.err.println( "Could not create backup.");
return;
}
f = new File("students.txt");
}
try ( PrintWriter outFile = new PrintWriter(f);) {
for (Student student : students) {
student.save(outFile);
}
} catch (FileNotFoundException e) {
System.err.println("Could not open file for writing.");
return;
}
After you do this, if you look for the file "students.txt", you will see the records you wrote in it.
How about reading it? Assume we have an empty students list (not null!):
try ( BufferedReader inFile = new BufferedReader(new FileReader(f))) {
Student student;
while ( ( student = Student.load(inFile)) != null) {
students.add(student);
}
} catch (FileNotFoundException e) {
System.err.println( "Could not open file for reading.");
return;
} catch (IOException e) {
System.err.println( "An error occured while reading from the file.");
}
Having done this, you can check your students list, and unless there were errors in the file, all your records will be there.
This is a demonstration, of course. You may want to read into some other collection or instead of printing an error and returning do something else. But it should give you the idea.
You could use db4o for persisting your data. Its an object-database with a spimple api to use. You can store java object read or delete them..
Download it here DB4O
And use the snippets of this tutorial (GER):Tutorial in German
Here is an example:
and Code:
package db4o.example;
public class Student {
String name;
public Student(String name) {
this.name = name;
}
#Override
public String toString() {
return "Student Name: " + name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package db4o.example;
import java.util.List;
import com.db4o.Db4oEmbedded;
import com.db4o.ObjectContainer;
public class Main {
public static void main(String[] args) {
ObjectContainer db = Db4oEmbedded.openFile("F:\\studentDB");
saveExample(db);
readAllExample(db);
readExample(db);
deleteAllExample(db);
db.close();
}
private static void deleteAllExample(ObjectContainer db) {
System.out.println("DeleteAllExample Example:");
List<Student> allStudents =readAllExample(db);
for (Student student : allStudents) {
db.delete(student);
}
db.commit();
}
private static List<Student> readAllExample(ObjectContainer db) {
System.out.println("ReadAllExample Example:");
List<Student> allStudents = db.query(Student.class);
System.out.println("Count: " + allStudents.size());
for (Student student : allStudents) {
System.out.println(student);
}
return allStudents;
}
private static void readExample(ObjectContainer db) {
System.out.println("ReadExample Example:");
Student queryStudent = new Student("Max Mustermann");
// Gets all Students named Max Mustermann
List<Student> students = db.queryByExample(queryStudent);
System.out.println("Count: " + students.size());
for (Student student : students) {
System.out.println(student);
}
}
private static void saveExample(ObjectContainer db) {
System.out.println("Save Example:");
Student myStudent = new Student("Max Mustermann");
db.store(myStudent);
db.commit();
}
}
I am having a hard time tryin to add an if statement to check if the folder exists before deletion and if it does not, it won't try to run. I am using the class in another class, so at the moment, it makes the main class stop what it is doing when this fails because the folder does not exist. Bonus points if you can make it do multiple extensions.
public class cleardiroftxt {
static String userprofile = System.getenv("USERPROFILE");
private static final String FILE_DIR = userprofile+"\\Downloads\\Software_Tokens";
private static final String FILE_TEXT_EXT = ".txt";
public static void run(String args[]) {
new cleardiroftxt().deleteFile(FILE_DIR,FILE_TEXT_EXT);
}
public void deleteFile(String folder, String ext){
GenericExtFilter filter = new GenericExtFilter(ext);
File dir = new File(folder);
//list out all the file name with .txt extension
String[] list = dir.list(filter);
if (list.length == 0) return;
File fileDelete;
for (String file : list){
String temp = new StringBuffer(FILE_DIR)
.append(File.separator)
.append(file).toString();
fileDelete = new File(temp);
boolean isdeleted = fileDelete.delete();
System.out.println("file : " + temp + " is deleted : " + isdeleted);
}
}
//inner class, generic extension filter
public class GenericExtFilter implements FilenameFilter {
private String ext;
public GenericExtFilter(String ext) {
this.ext = ext;
}
public boolean accept(File dir, String name) {
return (name.endsWith(ext));
}
}
}
If you need it, I am calling it here
public void actionPerformed(ActionEvent e){
JButton clickedButton = (JButton) e.getSource();
// JOptionPane.showMessageDialog(null, clickedButton.getText() + " clicked");
cleardir.run(null);
cleardiroftxt.run(null);
Unzip.run(null);
//when we click the ok button... then
if(clickedButton == btnOk){
JOptionPane.showMessageDialog(null, clickedButton.getText() + " clicked");
String cboString = (String) cboSequence.getSelectedItem();
/* we have to check if user have entered any value, is the chosen digit is NOT NONE.
* the ComboBox selection is NOT "None"
*/
if(cboString.equals("None") == false){
String temp = txtSequence.getText();
// then it has to be have some value for the textfield
if(temp.equals("") || temp == null){
JOptionPane.showMessageDialog(null, "Oops... Please fill up the sequence number field");
txtSequence.grabFocus();
//something to highlight the field in future?
return;
}
}
JOptionPane.showMessageDialog(null, "rename invoked");
renameFile();
}
File dir = new File(folder);
if (dir.exists()) {
//list out all the file name with .txt extension
String[] list = dir.list(filter);
...
}