0

So I have a program that saves your password and usernames for you, it then saves them in a .txt file. I'm adding the option to delete one of the entries in case you misspelled or something. This is what my text file looks like.

Website
Username
Password

anotherWebsite
anotherUsername
anotherPassword

Now the passwords aren't encrypted as I was instructed not to encrypt them.

My main question is, are you able to delete certain lines in a text file with out reading the whole file then saving the ones you want to a new file and then using that one?

Filburt
  • 17,626
  • 12
  • 64
  • 115
Jonah
  • 1,013
  • 15
  • 25
  • possible duplicate of [Find a line in a file and remove it](http://stackoverflow.com/questions/1377279/find-a-line-in-a-file-and-remove-it) – karvoynistas Oct 09 '14 at 17:49
  • @karvoynistas, I looked at it but this isn't a duplicate, The answers given are creating a new text file then using that one, which if possible, I don't want to do. – Jonah Oct 09 '14 at 17:51
  • An alternative to rewriting the file for every operation is to load the file into a data structure and keep it active during the lifetime of the program. Then export the data to file when done. Saves you the process of file IO operations every time you make any change. – Grice Oct 09 '14 at 17:54
  • @JGrice, not a bad idea. I'll look into that. – Jonah Oct 09 '14 at 17:59

4 Answers4

2

The answer to your question is no. Essentially, the way to do this is to rewrite the file, omitting the line you want to delete

ControlAltDel
  • 33,923
  • 10
  • 53
  • 80
1

What you have to do is rewrite your entire file, and not writing the lines you wanna skip.

One implementation from Find a line in a file and remove it seems good enough for your case, you'll just need to check for 3 things (the tuple (Website, Username, Password) instead of only one parameter.

public void removeLineFromFile(String file, String lineToRemove) {

try {

  File inFile = new File(file);

  if (!inFile.isFile()) {
    System.out.println("Parameter is not an existing file");
    return;
  }

  //Construct the new file that will later be renamed to the original filename.
  File tempFile = new File(inFile.getAbsolutePath() + ".tmp");

  BufferedReader br = new BufferedReader(new FileReader(file));
  PrintWriter pw = new PrintWriter(new FileWriter(tempFile));

  String line = null;

  //Read from the original file and write to the new
  //unless content matches data to be removed.
  while ((line = br.readLine()) != null) {

    if (!line.trim().equals(lineToRemove)) {

      pw.println(line);
      pw.flush();
    }
  }
  pw.close();
  br.close();

  //Delete the original file
  if (!inFile.delete()) {
    System.out.println("Could not delete file");
    return;
  }

  //Rename the new file to the filename the original file had.
  if (!tempFile.renameTo(inFile))
    System.out.println("Could not rename file");

}
catch (FileNotFoundException ex) {
  ex.printStackTrace();
}
catch (IOException ex) {
  ex.printStackTrace();
}

}

Community
  • 1
  • 1
Mekap
  • 2,065
  • 14
  • 26
1

I don't know a way to do it without another temporary file to read and write. I think it is not possible since you will read it as byte array and work with some high level API.

If you are using Java 8 i recommend using this structure:

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;

    public static void main(String[] args) throws IOException {
        String content = new String(Files.readAllBytes(Paths.get("duke.java")));
    }

Then, with the string, you can read it, concat or delete information.

Link: http://www.adam-bien.com/roller/abien/entry/java_8_reading_a_file

If you are using another version, follow this link:

Find a line in a file and remove it

Community
  • 1
  • 1
Bruno Franco
  • 2,028
  • 11
  • 20
1

In a file, each bit of information has a position. Removing some of those bits does not move the position of the other elements.

 File

 1111111111111111
 222222222.....22
 3333.33333.3.333
 44.444.444.444.4
 5555555555555555

becomes

 1111111111111111
 222222222.....22
 44.444.444.444.4
 5555555555555555

by removing

 3333.33333.3.333

and moving

 44.444.444.444.4
 5555555555555555

into the location previous held by

 3333.33333.3.333
 44.444.444.444.4

So you can do it without a temporary file, buy using the following technique

  1. Open a random access file (we will be jumping around in it.
  2. Read the file until you detect the items to be deleted, keeping a "location" of the start of that area.
  3. Calculate the "size" of the deleted area.
  4. While there is area beyond the deleted area that hasn't been moved
    1. Copy that area over the deleted area.
    2. Reassign the deleted area to the area you just copied from.
  5. Write the end of the file.

Of course this is really, really dangerous; as any interruption in the procedure leaves you with a file that is not the original, nor the result. As files copies can easily be interrupted by power outages, killed programs, etc. you really don't want this approach as it is so hard to recover from a failure.

That's why the write a second file, wait till that's done and then move it over the original file is a far better solution.

Edwin Buck
  • 69,361
  • 7
  • 100
  • 138
  • Yeah, I could see how that would be risky. I guess that I will go with writing to a new file. Thanks for the detailed explanation! – Jonah Oct 09 '14 at 18:20
  • Seen as it looks like you know your stuff. Is there a way to delete all the contents in a text file without a second file? I can create a new question if needed. – Jonah Oct 09 '14 at 18:23
  • 1
    @Jonah Sure, you can delete the contents in a text file without writing a second file. Just open the file, and then write the end-of-file marker to it (typically done by the library, immediately closing it will do it if you have the file opened in the right context). – Edwin Buck Oct 15 '14 at 05:55