'Trouble with replacing a variable in a txt file with user input - using java in eclipse

I am trying to replace one word in a txt file with a new one from user input (Using Java in Eclipse IDE). For example:

My txt file is as follows:

Jacket 12 59.95
DesignerJeans 40 34.95
Shirt 20 24.95

After entering in "Shirt" to be replaced with "Dress", my expected output is as follows:

Jacket 12 59.95
DesignerJeans 40 34.95
Dress 20 24.95

But my actual output with my current code is:

Dress 20 24.95

I got it to replace the desired word, however it also deleted the rest of my txt file. I'm posting the part of my code this occurs in below. Any insight on where my problem lies would be greatly appreciated. I'm still fairly new with java and I've been working on this for a while now.

public static void changeDescriptionOfAnItem(RetailItem[] tempVal) throws IOException {
        
        System.out.print("Retail Item Description to change: ");
        Scanner keyboard = new Scanner(System.in);
        String userInput;
        String newDescription;
        userInput = keyboard.nextLine();
        System.out.println("Enter NEW Retail Item Description: ");
        newDescription = keyboard.nextLine();

        File file = new File("RetailItemDatabase.txt");
        BufferedReader reader = new BufferedReader(new FileReader(file));
        String oldtext = userInput;
        for (String line; (line = reader.readLine()) != null;) {
            line = line.replace(oldtext, newDescription);
            FileWriter writer = new FileWriter("RetailItemDatabase.txt");
            writer.write(line);
            writer.close();
        }
        reader.close();

      }


Solution 1:[1]

There are a number of ways to do this but to carry on with the way you are attempting it then it could be something like this this (read all the comments in code):

/****************************************************
 *            BEFORE RUNNING THIS CODE,             *
 *     MAKE A BACKUP OF YOUR ORIGINAL DATA FILE     *
 ****************************************************/
public static void changeDescriptionOfAnItem() throws java.io.IOException {
    String errMSG = "Invalid Entry! You must supply an item description" + LS 
                  + "of at least 3 characters in length or 'c' to cancel!" + LS;
    String cancelMSG = "Item Description Change - CANCELED!" + LS;
    String oldDescription = "";
    String newDescription = "";
    
    while (oldDescription.isEmpty()) {
        System.out.print("Retail Item Description to change (c to cancel): ");
        oldDescription = keyboard.nextLine().trim();
        if (oldDescription.equalsIgnoreCase("c")) {
            System.out.println(cancelMSG);
            return;
        }
        // Validation...
        if (oldDescription.isEmpty() || oldDescription.length() < 3) {
            System.out.println(errMSG);
            oldDescription = "";
        }
    }
    
    
    while (newDescription.isEmpty()) {
        System.out.print("Enter NEW Retail Item Description (c to cancel): ");
        newDescription = keyboard.nextLine().trim();
        if (newDescription.equalsIgnoreCase("c")) {
            System.out.println(cancelMSG);
            return;
        }
        // Validation...
        if (newDescription.isEmpty() || newDescription.length() < 3) {
            System.out.println(errMSG);
            newDescription = "";
        }
    }
    // ALL USER INPUT HAS BEEN RECEIVED
    
    // The original Data file
    File file = new File("RetailItemDatabase.txt"); 
    // A temp data file where the changes will be stored.
    File tmpFile = new File("RetailItemDatabase_tmp.txt");
    
    /* 'Try With Resouces' used here for both reader and writer
       so as to automatically close them and free resources.        */
    try (java.io.FileWriter writer = new java.io.FileWriter(tmpFile);
            java.io.BufferedReader reader = new java.io.BufferedReader(new java.io.FileReader(file))) {
        String oldtext = oldDescription;
        String line;
        while ((line = reader.readLine()) != null) {
            line = line.trim();
            /* To speed things up we make sure the line actually 
               contains the item we're looking for.           */
            if (line.toLowerCase().contains(oldtext.toLowerCase())) {
                /* Seemed to have found a line where our item is located
                   but there is no quarantee it's not just part of another
                   item like "DressJacket" instead of just "Dress", so we
                   break the line up into its individual data components as 
                   a String[] Array and then just compare the first one part 
                   of the string. We're ignoreing letter case so that the 
                   User doesn't have to be overly accurate.           */
                String[] lineParts = line.split("\\s+");
                if (lineParts[0].equalsIgnoreCase(oldtext)) {
                    // Yup...this seems to be the line alright. 
                    // Let's rebuild the new line...
                    line = newDescription;
                    for (int i = 1; i < lineParts.length; i++) {
                        line += " " + lineParts[i];
                    }
                    
                    /* Note: You can not break out of the loop at this point
                       just because you found the item and made the line change.
                       You have to let this process carry through the entire 
                       data file so that ALL original data is writen to the temp
                       data file.                     */
                }
            }
            // Write the line to the tmp file ("RetailItemDatabase_tmp.txt")
            writer.write(line + System.lineSeparator());
            writer.flush();  // Write immediately.
        }
    }
    // FILE READING/WRITING HAS COMPLETED!
    
    /* Delete Original File ("RetailItemDatabase.txt")    AND
       Rename the Temp file ("RetailItemDatabase_tmp.txt") to what 
       the Original file name was named ("RetailItemDatabase.txt").
       Because both the File#delete() and File#renameTo() methods 
       return boolean true if they are successful, we can use them 
       within the `if` statement as we do below.           */
    if (file.delete() && tmpFile.renameTo(file)) {
        System.out.println("Item changed from '" + oldDescription + "' to "
                         + "'" + newDescription + "' - SUCCESSFULLY!");
    }
    else {
        System.out.println("Item change from '" + oldDescription + "' to "
                         + "'" + newDescription + "' - FAILED!");
    }
}

I had gotten rid of the RetailItem[] tempVal parameter from your method's signature since there is no indication as to what it might be for. One of the major problems you had was you were closing the writer within the for loop. This would happen upon the very first iteration, so, yes, only one write. You only close the reader and writer after you have actually carried out all the necessary reading and writing.

You should make your Scanner object a static class member so that it can be easily accessed by all methods that may be in your class. No need to open one for every method you want to use it in:

public class MyClassName {

    /* The line separator (newLine) used for the 
       specific system running this application.  */  
    private final static String LS = System.lineSeparator();
    
    /* Declare as class member so that is can be used 
       anywhere in class.    */
    private final static Scanner keyboard = new Scanner(System.in);

    public static void main(String args[]) {

    // ----------- The rest of the class code ------------

}

I have also added validation to the User prompts within the changeDescriptionOfAnItem() method. This always helps to reduce possible errors or other nuisances. This also gives the User the opportunity to enter valid data. It simply provides a cleaner User experience...well in my opinion.

If you remove all the comments within the method, it really isn't all that much code. Keep in mind...this is only one way of doing things but it is effective.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 DevilsHnd