I've done a small address book program that allows the user to:
add contact
search contact
delete contact
display all contacts
It ends after you enter one option, I want it to keep running until the user says eg 5- exit
another problem I want the data to written and read to data.dat file
I'm completly new, can some tell me how to split up this into separate classes and inherit each other.
my code:
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
public class AddressBookOperations
{
public static void main(String[] args) throws IOException
{
String s = null;
String s2 = null;
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
// Console in = System.console();
System.out.println(" Please select the required operations.\n"
+ " 1- Add contact\t 2- search contact\t 3- delete contact\t 4- display all contacts\n");
s2 = in.readLine();
if (s2 != null && !(s2.equals("1") || s2.equals("2") || s2.equals("3") || s2.equals("4")))
{
System.out.println("Invalid Operation Selected\n");
System.exit(0);
}
else
{
s = s2;
}
if (s != null)
{
String dataLine;
String data;
if (s.equals("1")) {
System.out.println("Name: ");
dataLine = in.readLine();
data = dataLine;
in = new BufferedReader(new InputStreamReader(System.in));
System.out.println("PhoneNumber: ");
dataLine = in.readLine();
data = data + ":" + dataLine;
writeToFile("C:/AddressBook.bat", data, true, true);
} else if (s.equals("2")) {
System.out.println("Enter Name 0r PhoneNumber: ");
dataLine = in.readLine();
String result = readFromFile("C:/AddressBook.bat", dataLine);
System.out.println("Search Results\n" + result);
} else if (s.equals("3")) {
System.out.println("Enter Name: ");
dataLine = in.readLine();
data = dataLine;
System.out.println("PhoneNumber: ");
dataLine = in.readLine();
data = data + ":" + dataLine;
deleteFromFile("C:/AddressBook.bat", data);
} else if (s.equals("4")) {
String result = readFromFile("C:/AddressBook.bat", null);
System.out.println("Search Results\n" + result);
}
}
}
private static void deleteFromFile(String string, String dataLine) {
String data = readFromFile(string, null);
data = data.replaceAll(dataLine, "");
writeToFile(string, data, false, false);
}
public static boolean writeToFile(String fileName, String dataLine,
boolean isAppendMode, boolean isNewLine) {
if (isNewLine) {
dataLine = "\n" + dataLine;
}
try {
File outFile = new File(fileName);
DataOutputStream dos;
if (isAppendMode) {
dos = new DataOutputStream(new FileOutputStream(fileName, true));
} else {
dos = new DataOutputStream(new FileOutputStream(outFile));
}
dos.writeBytes(dataLine);
dos.close();
} catch (FileNotFoundException ex) {
return (false);
} catch (IOException ex) {
return (false);
}
return (true);
}
/*
* Reads data from a given file
*/
public static String readFromFile(String fileName, String dataLine2) {
String DataLine = "";
String fileData = "";
try {
File inFile = new File(fileName);
BufferedReader br = new BufferedReader(new InputStreamReader(
new FileInputStream(inFile)));
if (dataLine2 != null)
{
while ((DataLine = br.readLine()) != null)
{
if (DataLine.contains(dataLine2)) {
fileData = DataLine;
}
}
}
else
{
while ((DataLine = br.readLine()) != null)
{
fileData = fileData + "\n" + DataLine;
//System.out.println(DataLine);
}
}
br.close();
}
catch (FileNotFoundException ex)
{
return (null);
} catch (IOException ex)
{
return (null);
}
return (fileData);
}
public static boolean isFileExists(String fileName) {
File file = new File(fileName);
return file.exists();
}
}
You can wrap your logic in a while loop which terminates when a given boolean is true, therefore you will keep going back to the start after each operation is performed. For example:
boolean isRunning = true;
while (isRunning) {
//your code here
if (s2.equals("5")) {
isRunning = false;
}
}
You should also move all of your logic out of main() and into its own seperate function that is called from main(). I'm also not sure why you are writing to a .bat file? Change the extension to .dat if you want to write to a .dat file.
I guess you just want a general code review. Here are my thoughts:
1. Scanner is much easier to use for console input because you can specify input types, such as nextInt(). To initialize it, just use
Scanner sc = new Scanner(System.in);
You can use the same Scanner for every user input in the course of the program. Also, remember to call Scanner.close() before your program exits.
2. Initialize your BufferedReader as follows:
// file is a String variable
BufferedReader in = new BufferedReader(new FileReader(file));
Analogously, read files as follows:
BufferedWriter br = new BufferedWriter(new BufferedReader(file));
3. To keep the program running, practice implementing a do-while block:
boolean quit = false;
do {
// loop program; when user is finished, set quit = true
} while (!quit)
4. For the conditionals based on "Please select the required operations", practice implementing a switch block.
5. Separate the logic for parsing the user input and the logic for operating on the address book by making the console interface a separate class, say, AddressBookUI. When it is runs, it should immediately create an instance of the AddressBookOperations class, and call appropriate methods from there based on user input - AddressBookOperations should have a separate method for each operation (this will also make your switch quite short). It should also have the following private (but not static) variables to store the filename and BufferedRead/Writer. The class should have a constructor with an String filename argument which initializes these variables.
6. Deleting specific lines in files is rather tricky in Java. Try this:
Create a BufferedReader for the file.
Create a new temporary file, and create a BufferedWriter for it.
Read the file line by line. For each line, if it is not the line you want to delete, write it to the temporary file.
Close the reader and the writer
Delete the old file
Rename the temp file to the filename.
Related
I am trying to replace a string from a js file which have content like this
........
minimumSupportedVersion: '1.1.0',
........
now 'm trying to replace the 1.1.0 with 1.1.1. My code is searching the text but not replacing. Can anyone help me with this. Thanks in advance.
public class replacestring {
public static void main(String[] args)throws Exception
{
try{
FileReader fr = new FileReader("G:/backup/default0/default.js");
BufferedReader br = new BufferedReader(fr);
String line;
while((line=br.readLine()) != null) {
if(line.contains("1.1.0"))
{
System.out.println("searched");
line.replace("1.1.0","1.1.1");
System.out.println("String replaced");
}
}
}
catch(Exception e){
e.printStackTrace();
}
}
}
First, make sure you are assigning the result of the replace to something, otherwise it's lost, remember, String is immutable, it can't be changed...
line = line.replace("1.1.0","1.1.1");
Second, you will need to write the changes back to some file. I'd recommend that you create a temporary file, to which you can write each `line and when finished, delete the original file and rename the temporary file back into its place
Something like...
File original = new File("G:/backup/default0/default.js");
File tmp = new File("G:/backup/default0/tmpdefault.js");
boolean replace = false;
try (FileReader fr = new FileReader(original);
BufferedReader br = new BufferedReader(fr);
FileWriter fw = new FileWriter(tmp);
BufferedWriter bw = new BufferedWriter(fw)) {
String line = null;
while ((line = br.readLine()) != null) {
if (line.contains("1.1.0")) {
System.out.println("searched");
line = line.replace("1.1.0", "1.1.1");
bw.write(line);
bw.newLine();
System.out.println("String replaced");
}
}
replace = true;
} catch (Exception e) {
e.printStackTrace();
}
// Doing this here because I want the files to be closed!
if (replace) {
if (original.delete()) {
if (tmp.renameTo(original)) {
System.out.println("File was updated successfully");
} else {
System.err.println("Failed to rename " + tmp + " to " + original);
}
} else {
System.err.println("Failed to delete " + original);
}
}
for example.
You may also like to take a look at The try-with-resources Statement and make sure you are managing your resources properly
If you're working with Java 7 or above, use the new File I/O API (aka NIO) as
// Get the file path
Path jsFile = Paths.get("C:\\Users\\UserName\\Desktop\\file.js");
// Read all the contents
byte[] content = Files.readAllBytes(jsFile);
// Create a buffer
StringBuilder buffer = new StringBuilder(
new String(content, StandardCharsets.UTF_8)
);
// Search for version code
int pos = buffer.indexOf("1.1.0");
if (pos != -1) {
// Replace if found
buffer.replace(pos, pos + 5, "1.1.1");
// Overwrite with new contents
Files.write(jsFile,
buffer.toString().getBytes(StandardCharsets.UTF_8),
StandardOpenOption.TRUNCATE_EXISTING);
}
I'm assuming your script file size doesn't cross into MBs; use buffered I/O classes otherwise.
Forgive me if this is a basic (or not very well explained) question, I am fairly new to Java and have been reading extensive material as well as trying to understand the relevant Javadoc but to no avail.
To give a brief background as to what I am trying to create, I have created a reader class which reads data in from a csv file (4 lines long) including fields such as Item ID, price, description etc. I have created a separate demo class that displays the details of this csv file (through creating an instance of my reader class) and am now trying to create a method that asks the user to input an Item ID that then displays the corresponding Item, based on the ID input by the user. The part I am stuck on is accessing specific rows/columns in a csv file and then comparing these with a given string (entered by the user which corresponds to a specific field in the csv file)
This is what I have come up with thus far:
input = new Scanner(System.in);
System.out.println("Enter a product code");
String prodC = input.next();
//Here I want to know if there is a way of accessing a field in a csv file
Any ideas would be greatly appreciated.
UPDATE
Thank you for quick responses, am currently reading through and seeing how I can try to implement the various techniques. In response to the comment asking about the file reader, this is how I have set that out:
public CatalogueReader(String filename) throws FileNotFoundException {
this.filename = filename;
this.catalogue = new Catalogue();
Scanner csvFile;
try {
csvFile = new Scanner(new File(filename));
} catch (FileNotFoundException fnf) {
throw new FileNotFoundException("File has not been found!");
}
csvFile.useDelimiter("\n");
boolean first = true;
String productCode;
double price;
String description;
double weight;
int rating;
String category;
boolean ageRestriction;
String csvRows;
while (csvFile.hasNextLine()) {
csvRows = csvFile.nextLine();
if (first) {
first = false;
continue;
}
System.out.println(csvRows);
String[] fields = csvRows.split(",");
productCode = (fields[0].trim());
price = Double.parseDouble(fields[1].trim());
description = fields[2].trim();
weight = Double.parseDouble(fields[3].trim());
rating = Integer.parseInt(fields[4].trim());
category = fields[5].trim();
ageRestriction = Boolean.parseBoolean(fields[6].trim());
catalogue.addAProduct(new Item(productCode, price, description, weight, rating, category, ageRestriction));
}
csvFile.close();
}
}
ok so for a CSV file like this:
"1.0.0.0","1.0.0.255","16777216","16777471","AU","Australia"
"1.0.1.0","1.0.3.255","16777472","16778239","CN","China"
"1.0.4.0","1.0.7.255","16778240","16779263","AU","Australia"
"1.0.8.0","1.0.15.255","16779264","16781311","CN","China"
"1.0.16.0","1.0.31.255","16781312","16785407","JP","Japan"
"1.0.32.0","1.0.63.255","16785408","16793599","CN","China"
"1.0.64.0","1.0.127.255","16793600","16809983","JP","Japan"
"1.0.128.0","1.0.255.255","16809984","16842751","TH","Thailand"
here is a sample of how to read using Java Native Libraries
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class CSVReader {
public static void main(String[] args) {
CSVReader obj = new CSVReader();
obj.run();
}
public void run() {
String csvFile = YOURFILEPATHHERE ;
BufferedReader br = null;
String line = "";
String cvsSplitBy = ",";
try {
br = new BufferedReader(new FileReader(csvFile));
while ((line = br.readLine()) != null) {
// use comma as separator
String[] country = line.split(cvsSplitBy);
System.out.println("Country [code= " + country[4]
+ " , name=" + country[5] + "]");
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
System.out.println("Done");
}
}
does this help?
If you are just doing a single look-up and then exiting then just remember the String you are looking for. As you parse the lines compare to see if you have a match and if you do then return that line.
For repeated searches that would be very inefficient though. Assuming your data set is not too large for memory you would be better off parsing the file and putting it into a Map:
Map<String, Data> dataMap = new HashMap<>();
Parse the file, putting all the lines into the map
Then the lookup just becomes:
Data d = dataMap.get(lineKey);
If d is null then there is no matching line. If it not null then you have found your line.
You can create an array list of object. An object for each line in the CSV. Then search the array object with your search criteria.
User CSVReader framework to read the csv file. Sample code (not exactly what you want)
FileInputStream fis = new FileInputStream(file);
CSVReader reader = new CSVReader(new BufferedReader( new InputStreamReader(fis, "UTF-8" )));
ArrayList<String> row = new ArrayList<String>();
ArrayList<Entry> entries = new ArrayList<Entry>();
// a line = ID, Name, Price, Description
while (!reader.isEOF()) {
reader.readFields(row);
if( row.size() >= 4)
entries.add(new Entry(row.get(0), row.get(1), row.get(2), row.get(3)));
}
System.out.println("Size : "+entries);
This code is reading a bunch of .java files and finding "public [classname]" or "private [classname]" and adding "System.out.println([classname])" to that line.
The problem is When I write that line back in I end up with a blank file
Can anyone see what I am doing wrong?
private static void work(ArrayList<File> fileList) {
for (int i = 0; i < fileList.size(); i++) {
replaceLines(fileList.get(i));
}
}
public static void replaceLines(File file) {
String path = file.getPath();
String fileNameLong = file.getName();
String fileName = null;
if (fileNameLong.contains(".java")) {
fileName = fileNameLong.substring(0, file.getName().indexOf("."));
}
if (fileName != null && fileName != "") {
System.out.println(fileName);
try {
//prepare reading
FileInputStream in = new FileInputStream(path);
BufferedReader br = new BufferedReader(
new InputStreamReader(in));
//prepare writing
FileWriter fw = new FileWriter(file);
PrintWriter out = new PrintWriter(fw);
String strLine;
while ((strLine = br.readLine()) != null) {
// Does it contain a public or private constructor?
boolean containsPrivateCon = strLine.contains("private "
+ fileName);
boolean containsPublicCon = strLine.contains("public "
+ fileName);
if (containsPrivateCon || containsPublicCon) {
int lastIndexOfBrack = strLine.lastIndexOf("{");
while (lastIndexOfBrack == -1) {
strLine = br.readLine();
lastIndexOfBrack = strLine.lastIndexOf("{");
}
if (lastIndexOfBrack != -1) {
String myAddition = "\n System.out.println(\""
+ fileName + ".java\"); \n";
String strLineModified = strLine.substring(0,
lastIndexOfBrack + 1)
+ myAddition
+ strLine.substring(lastIndexOfBrack + 1);
strLine = strLineModified;
}
}
out.write(strLine);
}
} catch (Exception e) {
System.out.println(e);
}
}
}
If you want to write to the same file you're reading from, you should either write to a copy of the file (different filename) and then rename the output file, or use RandomAccessFile interface to edit a file in-place.
Usually, the first solution will be much easier to implement than the second one; unless the files are huge (which is probably not the case with .java files), there is no real reason to use the second.
You forgot to flush and close the file. PrintWriter keeps a buffer and unless you explicitly flush() it, the data will (un)happily sit in the buffer and it will never be written to the output.
So you need to add this before the line catch (Exception e) {
out.flush();
out.close();
Note that this is only necessary for PrintWriter and PrintStream. All other output classes flush when you close them.
This question already has answers here:
BufferedWriter not writing everything to its output file
(8 answers)
Closed 8 years ago.
This is a code snippet but basically what I want to do is read from a file named 'listings.txt' and write to a file named 'overview.txt'. I want to take the information out of 'listings.txt' and put them into 'overview.txt' as is (I will figure out the rest later).
The file 'overview.txt' is created and appears to loop through the file 'listings.txt' and write to 'overview.txt'. However, once I open the file 'overview.txt' it is empty. Could someone go through a quick glance at my code and spot something erroneous?
package yesOverview;
import java.io.BufferedReader;
import java.io.*;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.util.Scanner;
import java.util.logging.Level;
import java.util.logging.Logger;
public class yesOverview {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
String strInput = "foo.bar";
System.out.print("Please enter the listings file (the full path to the file): ");
strInput = input.next();
//This makes sure that the inputed file is listings.txt as required for KET1 task 2
while (strInput.contains("listings.txt") == false) {
System.out.print("Incorrect file. Please enter listings file(the full path to the file): ");
strInput = input.next();
}
infos(strInput);
input.close();
}
public static void infos(String strInput) {
Scanner input2 = new Scanner(System.in);
System.out.print("Please enter the overview.txt file (the full path to the file): ");
String strInput2 = "foo.bar";
strInput2 = input2.next();
//This also makes sure that the overview.txt file is provided.
while (strInput2.contains("overview.txt") == false) {
System.out.print("Incorrect file. Please enter overview file(the full path to the file): ");
strInput2 = input2.next();
}
//Creates the file f then places it in the specified directory.
File f = new File(strInput2);
try {
//Creates a printerwriter out that writes to the output file.
PrintWriter out = new PrintWriter(strInput2);
} catch (FileNotFoundException ex) {
Logger.getLogger(KETTask2Overview.class.getName()).log(Level.SEVERE, null, ex);
}
//String that holds the value of the next line.
String inputLine = "";
//Creates the Buffered file reader / writer.
try {
BufferedReader in = new BufferedReader(new FileReader(strInput));
FileWriter fstream = new FileWriter(strInput2);
BufferedWriter out = new BufferedWriter(fstream);
while (in.readLine() != null) {
out.write(in.read());
}
in.close();
} catch (IOException e) {
System.err.println("Error: " + e.getMessage());
}
}
}
Try this
Close the BufferedWriter stream (ie out.close() )
try and use nextLine() instead of next(), as next() only takes in a single word, but for a complete line use nextLine(), though this doesnt seem to be the problem here.
What i do when i have to read and write to files, i normally follow these steps
For Reading from a file
File f = new File("my.txt");
FileReader fr = new FileReader(f);
BufferedReader br = new BufferedReader(fr);
String s = null;
while ((br.readLine())!=null) {
// Do whatever u want to do with the content of the file,eg print it on console using SysOut...etc
}
br.close();
For Writing to a file:
Boolean isDone = true;
Scanner scan = new Scanner(System.in);
File f = new File("my.txt");
FileWriter fr = new FileWriter(f);
BufferedWriter br = new BufferedWriter(fr);
while (isDone) {
if (!isDone) {
br.write(new Scanner(System.in).nextLine());
}
}
public static long copy (Reader input, Writer output) throws IOException {
char[] buffer = new char[8192];
long count = 0;
int n;
while ((n = input.read( buffer )) != -1) {
output.write( buffer, 0, n );
count += n;
}
return count;
}
Usage Example:
copy( reader, new FileWriter( file ) );
You're not closing out.
The finally block for the writeList method cleans up and then closes the BufferedWriter.
finally {
if (out != null) {
System.out.println("Closing BufferedWriter");
out.close();
} else {
System.out.println("BufferedWriter not open");
}
}
I am writing a Java program that inputs a test file, performs some modifications to the data, then writes it to a new file output.
The input text file looks like this...
url = http://184.154.145.114:8013/wlraac name = wlr samplerate = 44100 channels =2 format = S16le~
url = http://newstalk.fmstreams.com:8080 name = newstalk samplerate = 22050 channels = 1 format = S16le
The program needs to be able to change the samplerate to 44100, and the channels to 1, if they don't already have these values. I would also remove the url and name pieces completely. After these changes, the new line needs to be written out to a different output text file.
So far, all my program can do is select a file and display the contents of the file to the user. Could someone please point me in the right direction for how my program should work
to achieve my required outcome.
As somebody asked here is what I have so far
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
public class reader2 {
public reader2() {
}
public static void main(String[] args) {
reader(args);
}
public static void reader(String[] args) {
JFileChooser chooser = new JFileChooser();
chooser.setCurrentDirectory(new File("."));
chooser.setFileFilter(new javax.swing.filechooser.FileFilter() {
public boolean accept(File f) {
return f.getName().toLowerCase().endsWith(".txt")
|| f.isDirectory();
}
public String getDescription() {
return "Text Documents (.txt)";
}
});
int r = chooser.showOpenDialog(new JFrame());
if (r == JFileChooser.APPROVE_OPTION) {
String name = chooser.getSelectedFile().getName();
String pathToFIle = chooser.getSelectedFile().getPath();
System.out.println(name);
try{
BufferedReader reader = new BufferedReader( new FileReader( pathToFIle ) ); //Setup the reader
while (reader.ready()) { //While there are content left to read
String line = reader.readLine(); //Read the next line from the file
String[] tokens = line.split( "url = " ); //Split the string at every # character. Place the results in an array.
for (String token : tokens){ //Iterate through all of the found results
//System.out.println(token);
System.out.println(token);
}
}
reader.close(); //Stop using the resource
}catch (Exception e){//Catch exception if any
System.err.println("Error: " + e.getMessage());
}
}
}
}
You will need to do something like this ...
Read the contents of the file, one line at a time
Split the line up into the individual components, such as splitting it on the 'space' character
Change the sample rate and channel values according to your question
Write the line out to a file, and start again from step 1.
If you give this a try, post some code on StackExchange with any problems and we'll try to assist.
can you try
File file = new File( fileName );
File tempFile = File.createTempFile("buffer", ".tmp");
FileWriter fw = new FileWriter(tempFile);
Reader fr = new FileReader(file);
BufferedReader br = new BufferedReader(fr);
while(br.ready()) {
String line = br.readLine();
String newLine = line.replaceAll( "samplerate =\\s*\\d+", "samplerate = 44100");
newLine = newLine.replaceAll( "channels =\\s*\\d+", "channels = 1");
fw.write(newLine + "\n");
}
fw.close();
br.close();
fr.close();
// Finally replace the original file.
tempFile.renameTo(file);
Ref: Files java replacing characters