0

I'm using an arraylist to append inputs and send the arraylist elements to file. However, everytime I exit the program and run it again, the contents in the written in the file becomes empty.

ArrayList<String> memory = new ArrayList<String>();

    public void fileHandling() {
        try {
            FileWriter fWriter = new FileWriter("notes.data");
            for (int x = 0; x <= memory.size() - 1; x++) {
                fWriter.write(memory.get(x) + '\n');
            }
            fWriter.close();

        } catch (IOException e) {
            System.out.println(e);
        }
    }

    public void createNote() {
        Scanner insertNote = new Scanner(System.in);
        LocalDate todayDate = LocalDate.now();
        LocalTime nowTime = LocalTime.now();
        String timeFormat = nowTime.format(DateTimeFormatter.ofLocalizedTime(FormatStyle.MEDIUM));
        String dateTime = todayDate.toString() + " at " + timeFormat;

        while (true) {
            System.out.println();
            System.out.println("Enter a note");
            System.out.print("> ");
            String note = insertNote.nextLine();

            if (note == null) {
                System.out.println("Invalid input! Try again");
                break;
            } else {
                memory.add(note + " /" + dateTime);
                
                fileHandling();
                System.out.println("Note is saved!\n");
                break;
            }
        }

I expect the program to save the contents of every input. Then if I exit and run the program again, the contents will go back to the array

dwextit
  • 11
  • 2
    Does this answer your question? [Java FileWriter with append mode](https://stackoverflow.com/questions/1225146/java-filewriter-with-append-mode) – maloomeister Nov 17 '22 at 08:22
  • 1
    In short: use the constructor with append mode [`new FileWriter(File file, boolean append)`](https://docs.oracle.com/javase/8/docs/api/java/io/FileWriter.html#FileWriter-java.io.File-boolean-). – maloomeister Nov 17 '22 at 08:24
  • 1
    The `while` loop in `createNote` is useless because both branches of the `if` contain a `break`. I can't see the code that reads the file. You'd be better off using the append mode as suggested by @maloomeister. – Maurice Perry Nov 17 '22 at 08:26
  • that doesn't work for me if u want to see, the full code is here: https://replit.com/join/fgjspcbfpq-dexterlanot – dwextit Nov 17 '22 at 08:32

2 Answers2

0

Your code currently does the following:

You enter something (X) for the first time:

  • It gets added to the ArrayList
  • The ArrayList gets written into the file
  • Your file now contains: X

You enter something second (Y):

  • It gets added to the ArrayList (Which now contains: X, Y)
  • The ArrayList gets written into the file
  • Your file now contains: X + newline + Y

Your Problem is, that everytime you create a new FileWrite it overwrites your file.

This can be avoided by using the constructor like this:

FileWriter writer = new FileWriter("notes.data", true);

This sets it into the append mode and therefore keeps previous data in the file

0

You don't need to create a separate Scanner, in method createNote(), in order to get a "note" from the user.

It is usually better to write your code using the interface rather than the specific implementation because then you usually need to change less code if you decide to change the implementation. Hence the type for member variable memory should probably be List rather than ArrayList.

Note that ArrayList may waste memory if the list of "note"s is large. I suggest using LinkedList instead. Alternatively, use an array (rather than a List) and handle expanding the array when adding a "note" as well as reducing the array when removing a "note".

Having an infinite loop, i.e. while (true), which contains a single if-else where both the if block and the else block contain break statements, means that the loop will perform exactly one iteration. May as well remove the while loop – which means also removing the break statements.

Rather than writing the code that generates a timestamp repeatedly, you should adopt the DRY principle and extract that code into a separate method.

The file name should be a constant so as to minimize the amount of code changes you will need to do if you decide to change the file name.

By convention, text files have a filename extension of .txt whereas binary files have the .data extension.

Although you don't need to, I personally prefer to initialize class member variables in the constructor.

The below code is a SSCCE, hence I added a main method. More notes appear after the code.

package Methods;

import java.util.*;
import java.time.format.*;
import java.time.*;
import java.io.*;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

public class FileSys {
    private static final String FILENAME = "notes.txt";
    private static final String CREATE = "C";
    private static final String DELETE = "D";
    private static final String FIND = "F";
    private static final String QUIT = "Q";
    private static final String SHOW = "S";
    private static final String UPDATE = "U";

    Scanner reader;
    List<String> memory;

    public FileSys() throws IOException {
        reader = new Scanner(System.in);
        memory = new LinkedList<String>();
        loadFile();
    }

    public void fileHandling() {
        Path path = Paths.get(FILENAME);
        try (BufferedWriter bw = Files.newBufferedWriter(path,
                                                         StandardOpenOption.CREATE,
                                                         StandardOpenOption.WRITE);
             PrintWriter pw = new PrintWriter(bw)) {
            for (String write : memory) {
                pw.println(write);
            }
        }
        catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void createNote() {
        String dateTime = getTimestamp();

            System.out.println();
            System.out.println("Enter a note");
            System.out.print("> ");
            String note = reader.nextLine();

            memory.add(note + " / " + dateTime);

            fileHandling();
            System.out.println("Note is saved!");
    }

    public void searchNote() {
        System.out.print("\nEnter note number: ");
        try {
            int search = reader.nextInt();
            reader.nextLine();
            System.out.println("\nSearch result:");
            int index = memory.indexOf(memory.get(search - 1));
            if (index != -1) {
                System.out.println("[" + (index + 1) + "]" + " " + memory.get(search - 1));
            }
            else {
                System.out.println("Note number-" + search + " is not found in the collection!");
            }
        }
        catch (IndexOutOfBoundsException e) {
            System.out.println("The note number you have entered is invalid!");
        }
    }

    public void updateNote() {
        String dateTime = getTimestamp(); // ZonedDateTime.now(ZoneId.systemDefault()).format(dateTimeObj);
        System.out.print("\nEnter note number to change: ");
        try {
            int search = reader.nextInt();
            int index = memory.indexOf(memory.get(search - 1));
            String updateLine;
            if (index != -1) {
                System.out.println("\nCurrent note: ");
                System.out.println("[" + (index + 1) + "]" + " " + memory.get(search - 1));
                System.out.println("\nThe updated note will be: ");
                System.out.print("> ");
                reader.nextLine();
                updateLine = reader.nextLine();
                memory.set(index, updateLine + " /" + dateTime);
                System.out.print("Note has been updated successfully!\n");
            }
            else {
                System.out.println(search + " is not found in the collection!");
            }
        }
        catch (IndexOutOfBoundsException e) {
            System.out.println("The note number you have entered is invalid!");
        }
        fileHandling();
    }

    public void deleteNote() {
        System.out.print("\nEnter note number to delete: ");
        try {
            int search = reader.nextInt();
            reader.nextLine();
            int index = memory.indexOf(memory.get(search - 1));
            System.out.println();
            if (index != -1) {
                System.out.println("[" + (index + 1) + "]" + " " + memory.get(search - 1));
                System.out.print("\nDo you want to delete this note? \n[y] or [n]: ");
                char delDecision = reader.nextLine().charAt(0);
                if (delDecision == 'y' || delDecision == 'Y') {
                    memory.remove(index);
                    System.out.println("Note has been deleted successfully!");
                    System.out.println();
                }
                else if (delDecision == 'n' || delDecision == 'N') {
                    System.out.println("Note was not deleted!");
                }
                else {
                    System.out.println("Invalid input!");
                }
            }
            else {
                System.out.println(search + " is not found in the collection!");
            }
        }
        catch (IndexOutOfBoundsException e) {
            System.out.println("The note number you have entered is invalid!");
        }
        fileHandling();
    }

    public void displayNote() {
        if (memory.size() > 0) {
            int counter = 0;
            for (String note : memory) {
                System.out.printf("%d. %s%n", ++counter, note);
            }
        }
        else {
            System.out.println("There are no notes.");
        }
    }

    private String getTimestamp() {
        LocalDate todayDate = LocalDate.now();
        LocalTime nowTime = LocalTime.now();
        String timeFormat = nowTime.format(DateTimeFormatter.ofLocalizedTime(FormatStyle.MEDIUM));
        String dateTime = todayDate.toString() + " at " + timeFormat;// ZonedDateTime.now(ZoneId.systemDefault()).format(dateTimeObj);
        return dateTime;
    }

    private void loadFile() throws IOException {
        Path path = Paths.get(FILENAME);
        if (Files.isRegularFile(path)) {
            memory.addAll(Files.readAllLines(path, Charset.defaultCharset()));
        }
    }

    private void showMenu() {
        String choice = "";
        while (!QUIT.equalsIgnoreCase(choice)) {
            System.out.println(CREATE + " - Create note");
            System.out.println(DELETE + " - Delete note");
            System.out.println(FIND + " - Search notes");
            System.out.println(SHOW + " - Show notes");
            System.out.println(UPDATE + " - Update note");
            System.out.println(QUIT + " - Quit");
            System.out.println();
            System.out.print("Your choice: ");
            choice = reader.nextLine();
            if (!choice.isEmpty()) {
                choice = choice.substring(0, 1);
                choice = choice.toUpperCase();
                switch (choice) {
                    case CREATE -> createNote();
                    case DELETE -> deleteNote();
                    case FIND -> searchNote();
                    case SHOW -> displayNote();
                    case UPDATE -> updateNote();
                    case QUIT -> System.out.println("Good bye.");
                    default -> System.out.println("Invalid: " + choice);
                }
            }
            else {
                System.out.println("No selection entered. Retry.");
            }
        }
    }

    public static void main(String[] args) {
        try {
            FileSys fs = new FileSys();
            fs.showMenu();
        }
        catch (IOException xIo) {
            xIo.printStackTrace();
        }
    }
}

Your code does not initially load memory with contents of file notes.txt so I added that in the constructor. Consequently you don't need to append to the file since you simply overwrite it with contents of memory.

The file handling is done using NIO.2 including try-with-resources – which was added in Java 7. There are more NIO.2 examples in the JDK documentation.

Whenever the code throws an unexpected exception, it is nearly always a good idea to print the stack trace.

Abra
  • 19,142
  • 7
  • 29
  • 41