How to read and append text file based on certain conditions - java

What the program does: A user loads a file and it saves the file name, creation date and a file number to a text file. I want the program to check the file to see if the filename is already stored. If it is, to then check the creation date to see if it matches the one the user is currently trying to save. If it differs, to save over the currently saved creation date with the new one.
An example of Info.txt:
CreationDate: 140319, FileName: example1.txt, FileNumber: 1
CreationDate: 110219, FileName: example2.txt, FileNumber: 6
CreationDate: 100319, FileName: example3.txt, FileNumber: 14
How I create and write to the file:
public void fileCreation() throws IOException {
String fileinformation = File.creationdate + ", " + File.name + ", " + "Number: " + File.Number;
FileWriter wr = new FileWriter("Info.txt", true);
PrintWriter output = new PrintWriter(wr);
output.println(fileinformation);
output.close();
}
How I'm currently checking the file, at the moment it only prints the file contents, so if a User goes to save example2.txt with a different creation date, then the new one should overwrite the current one
public void scanFile() throws IOException {
BufferedReader br = new BufferedReader(new FileReader("Info.txt"));
String readfile;
while ((readfile = br.readLine()) != null) {
System.out.println(readfile);
}
System.out.println("file not found");
}
Creation date is a long number and File.creationdate is a string such as "CreationDate: 140319", it would also be good to put a check to see if the FileNumber matches, but this is not necessary.

You should use split on your line with ',' as a separator.
Then you can go through every line and for each line check if first the name is the same as the file name, if it is, go and check the date and then finally check the FileNumber.
But why do you need to check it one by one ? Better to write it in with &&, like this
public boolean scanFile() throws IOException {
BufferedReader br = new BufferedReader(new FileReader("Info.txt"));
String readfile;
Boolean isAlreadyIn = false;
while ((readfile = br.readLine()) != null) {
String[] parts = readFile.split(',');
if(parts[1].replace("FileName: ","").equals(File.name) &&parts[0].replace("CreationDate: ","").equals(File.creationdate) &&parts[2].replace("FileNumber: ","").equals(File.number){
isAlreadyIn = true; // you can also write directly in this fonction
}
return isAlreadyIn;
}
}
if you really need to check it one by one, just make a if(if( if()) with the condition in it

Related

How to delete a whole line from a text file from the input entered

i'm trying to delete a whole line after entering the Association Name but isnt working. it keeps showing the error, could not delete original input file can you please help me with this?
String inputFileName = "Association Record.txt";
String outputFileName = "Association Report.txt";
String lineToRemove = JOptionPane.showInputDialog("Enter Association Name to Delete the Record");
try{
File inputFile = new File(inputFileName);
File outputFile = new File(outputFileName);
try{
BufferedReader r1= new BufferedReader(new FileReader(inputFile));
BufferedWriter w1 = new BufferedWriter(new FileWriter(outputFile));
String line = null;
while ((line = r1.readLine()) != null) {
if (!line.equals(lineToRemove)) {
w1.write(line);
w1.newLine();
}
}//end while
}
catch (IOException ex) {ex.printStackTrace();}
if (inputFile.delete()) {
if (!outputFile.renameTo(inputFile))
throw new IOException("Could not rename " + outputFileName + " to " + inputFileName);
}
else {throw new IOException("Could not delete original input file " + inputFileName);}
}
catch (Exception e){System.out.println(e.getMessage());}
}
example of one of the line in the file:
COMPUTER,pc,08/07/2018,brandon
*COMPUTER is the association name
If the word COMPUTER is the association word and the line you want to delete starts with the word COMPUTER then the String#equals() method is not the one to use in your IF statement. You would want to use the String#startsWith() method, for example:
boolean ignoreLetterCase = true; // ignore Letter Case by default
String lineToRemove = "computer";
String criteria = ignoreLetterCase ? lineToRemove.toLowerCase() : lineToRemove;
while ((line = r1.readLine()) != null) {
String procString = ignoreLetterCase ? line.toLowerCase : line;
if (!procString.startsWith(criteria)) {
w1.write(line);
w1.newLine();
}
}
The file data line COMPUTER,pc,08/07/2018,brandon will not be written to the destination file.
If however you want to ignore a file line that contains the associative word COMPUTER anywhere within a retrieved data line then you will want to utilize the String#contains() method, for example:
boolean ignoreLetterCase = true; // ignore Letter Case by default
String lineToRemove = "computer";
String criteria = ignoreLetterCase ? lineToRemove.toLowerCase() : lineToRemove;
while ((line = r1.readLine()) != null) {
String procString = ignoreLetterCase ? line.toLowerCase : line;
if (!procString.contains(criteria)) {
w1.write(line);
w1.newLine();
}
}
The file data line COMPUTER,pc,08/07/2018,brandon will not be written to the destination file. However a file data line which contains PRINTER,pc-computer,09/27/2018,joseph will also not be written to the destination file since the word computer is contained within the original file line.
I highly doubt this will ever be the case with your data file but if a retrieved file data line only contains the associative word (COMPUTER) then by all means you would want to use the String#equals() or String#equalsIgnoreCase() method.
If you want to ignore original file lines where the associative word is only pertinent within a specific data column of any retrieved file data line then you would want to parse (split) each line into a columnar data array and do your comparisons on the desired column (array elemental index). For example:
// Delete all file lines where the NAME column equals
// the name 'brandon' or 'Brandon' or 'BRANDON'.
boolean ignoreLetterCase = true; // ignore Letter Case by default
int deleteIfInColumn = 3;
String nameToDelete = "Brandon";
String criteria = ignoreLetterCase ? nameToDelete .toLowerCase() : nameToDelete;
while ((line = r1.readLine()) != null) {
String procString = ignoreLetterCase ? line.toLowerCase : line;
String[] columnData = procString.split(",");
if (columnData[deleteIfInColumn].equals(criteria)) {
continue; // Skip to next file line
}
w1.write(line);
w1.newLine();
}

How to delete a line from a textfile using java?

I wanted to delete a line from a textfile after asking the user what he/she wants to delete but I don't know what to do next in my code.
The textfile looks like this:
1::name::mobileNum::homeNum::fax::birthday::email::website::address // line the user wants to delete
2::name::mobileNum::homeNum::fax::birthday::email::website::address
3::name::mobileNum::homeNum::fax::birthday::email::website::address
Here's my code:
public static void readFromFile(String ans, String file) throws Exception {
BufferedReader fileIn = new BufferedReader(new FileReader(file));
GetUserInput console = new GetUserInput();
String checkLine = fileIn.readLine();
while(checkLine!=null) {
String [] splitDetails = checkLine.split("::");
Contact details = new Contact(splitDetails[0], splitDetails[1], splitDetails[2], splitDetails[3], splitDetails[4], splitDetails[5], splitDetails[6], splitDetails[7], splitDetails[8]);
checkLine = fileIn.readLine();
if(ans.equals(splitDetails[0])) {
// not sure what the code will look like here.
// in this part, it should delete the line the user wants to delete in the textfile
}
}
}
So the output of the textfile should be like this:
2::name::mobileNum::homeNum::fax::birthday::email::website::address
3::name::mobileNum::homeNum::fax::birthday::email::website::address
Also, I want the line number 2 and 3 to be adjusted to 1 and 2:
1::name::mobileNum::homeNum::fax::birthday::email::website::address
2::name::mobileNum::homeNum::fax::birthday::email::website::address
How would I do this?
Here's a working code, assuming you are using Java >= 7:
public static void removeLine(String ans, String file) throws IOException {
boolean foundLine = false;
try (BufferedReader br = Files.newBufferedReader(Paths.get(file));
BufferedWriter bw = Files.newBufferedWriter(Paths.get(file + ".tmp"))) {
String line;
while ((line = br.readLine()) != null) {
String[] tokens = line.split("::", 2);
if (tokens[0].equals(ans)) {
foundLine = true;
} else {
if (foundLine) {
bw.write((Integer.parseInt(tokens[0]) - 1) + "::" + tokens[1]);
} else {
bw.write(line);
}
bw.newLine();
}
}
}
Files.move(Paths.get(file + ".tmp"), Paths.get(file), StandardCopyOption.REPLACE_EXISTING);
}
It is not possible to delete a line from a file. What you need to do is read the existing file, write the contents you want to keep to a temporary file and then rename the temporary file to overwrite the input file.
Here, the temporary file is created in the same directory as the input file, with the extension .tmp added (note that you can also use Files.createTempFile for this).
For each line that is read, we check if this is the line the user wants to delete.
If it is, we update a boolean variable telling us that we just hit the line to be deleted and we do not copy this line to the temporary file.
If it is not, we have a choice:
Either we did not yet hit the line to be deleted. Then we simply copy what we read to the temporary file
Or we did and we need to decrement the first number and copy the rest of the line to the temporary file.
The current line is splitted with the help of String.split(regex, limit) (it splits the line only two times, thereby creating an array of 2 Strings: first part is the number, second part is the rest of the line).
Finally, the temporary file overwrites the input file with Files.move (we need to use the REPLACE_EXISTING option).

Updating a single line on a text file with a Java method

I know previous questions LIKE this one have been asked, but this question has to do with the specifics of the code that I have written. I am trying to update a single line of code on a file that will be permanently updated even when the program terminates so that the data can be brought up again. The method that I am writing currently looks like this (no compile errors found with eclipse)
public static void editLine(String fileName, String name, int element,
String content) throws IOException {
try {
// Open the file specified in the fileName parameter.
FileInputStream fStream = new FileInputStream(fileName);
BufferedReader br = new BufferedReader(new InputStreamReader(
fStream));
String strLine;
StringBuilder fileContent = new StringBuilder();
// Read line by line.
while ((strLine = br.readLine()) != null) {
String tokens[] = strLine.split(" ");
if (tokens.length > 0) {
if (tokens[0].equals(name)) {
tokens[element] = content;
String newLine = tokens[0] + " " + tokens[1] + " "
+ tokens[2];
fileContent.append(newLine);
fileContent.append("\n");
} else {
fileContent.append(strLine);
fileContent.append("\n");
}
}
/*
* File Content now has updated content to be used to override
* content of the text file
*/
FileWriter fStreamWrite = new FileWriter(fileName);
BufferedWriter out = new BufferedWriter(fStreamWrite);
out.write(fileContent.toString());
out.close();
// Close InputStream.
br.close();
}
} catch (IOException e) {
System.out.println("COULD NOT UPDATE FILE!");
System.exit(0);
}
}
If you could look at the code and let me know what you would suggest, that would be wonderful, because currently I am only getting my catch message.
Okay. First off the bat, StringBuilder fileContent = new StringBuilder(); is bad practice as this file could well be larger than the user's available memory. You should not keep much of the file in memory at all. Do this by reading into a buffer, processing the buffer (adjusting it if necessary), and writing the buffer to a new file. When done, delete the old file and rename the secondary to the old one's name. Hope this helps.

reading a txt file form External Storage Directory by one by eclipse Android

I have a .txt file in ExternalStorageDirectory() in Android. This file contains 10 sentence line by line. I want to read each sentence one by one. And then show it on EditText when every button click. I found only all file reading codes. I don't want this. How can I do that? Here is my little code:
enter cod private String Load() {
String result = null;;
String FILE_NAME = "counter.txt";
//if (isExternalStorageAvailable() && isExternalStorageReadOnly()) {
String baseDir = Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + "Records";
File file = new File(baseDir, FILE_NAME);
String line = "";
StringBuilder text = new StringBuilder();
try {
FileReader fReader = new FileReader(file);
BufferedReader bReader = new BufferedReader(fReader);
while( (line = bReader.readLine()) != null ){
text.append(line+"\n");
}
result = String.valueOf(text);
} catch (IOException e) {
e.printStackTrace();
}
//}
return result;
}
All Load() does is reads the file and returns it as a String. From here, you have a few options.
1).
Convert the result to an array of Strings using String.split('\n'), and grab the next value when you click the button. Here's a quick example:
int counter = 0;
String file = Load();
String[] lines = file.split("\n");
button.onClicked() {
editText.setText(lines[counter++]);
}
2).
Declare the buffered reader as a class member, so you can call readLine() inside the button's onClicked() method. This way, it will only read one line of the file when someone clicks the button, instead of reading the whole file in Load().

Cannot read first line of a file

I want to read the content of /etc/passwd file and get some data:
public void getLinuxUsers()
{
try
{
// !!! firstl line of the file is not read
BufferedReader in = new BufferedReader(new FileReader("/etc/passwd"));
String str;
str = in.readLine();
while ((str = in.readLine()) != null)
{
String[] ar = str.split(":");
String username = ar[0];
String userID = ar[2];
String groupID = ar[3];
String userComment = ar[4];
String homedir = ar[5];
System.out.println("Usrname " + username +
" user ID " + userID);
}
in.close();
}
catch (IOException e)
{
System.out.println("File Read Error");
}
}
I noticed two problems:
first line of the file is not read with root account information. I starts this way:
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
And how I can modify the code to use Java 8 NIO? I want to check first the existing of the file and then to proceed with reading the content.
The problem is that the first readLine() is outside the loop where the string is being processed, you should delete this:
str = in.readLine();
… Because in the next line (the one with the while) you're reassigning the str variable, that's why the first line is lost: the loop's body starts processing from the second line. Finally, to use Java nio, do something like this:
if (new File("/etc/passwd").exists()) {
Path path = Paths.get("/etc/passwd");
List<String> lines = Files.readAllLines(path, Charset.defaultCharset());
for (String line : lines) {
// loop body, same as yours
}
}
with nio:
Path filePath = Paths.get("/etc/passwd");
List<String> fileLines = Files.readAllLines(filePath);
Note that Files.readAllLines without 2nd parameter treats the file encoding as UTF-8, instead of system encoding (property "file.encoding")

Categories