I can not delete the "necessary" lines from a text file. There is a class of the Person model, whose fields are parsed on the command line and, using the add command, are added to the text file. Then, the contents of the file can be viewed by entering the view command. And for deletion, use the remove command. For this team wrote the following logic:

try(BufferedReader reader = new BufferedReader(new FileReader(fileName)); BufferedWriter writer = new BufferedWriter(new FileWriter(fileName))){ while ((reader.readLine()) != null){ people.add(person); } List<Person> filteredList = people.stream().filter(p -> person.getSurname().equals(searchString)).collect(Collectors.toList()); people.removeAll(filteredList); writer.write(person.getName()+ "\r" + person.getSurname() + "\r" + person.getAge() + "\r" + person.getEmail() + "\r\n\r\n"); } catch (IOException e){ throw new RuntimeException(e); } 

But, instead of deleting what you need, everything else is deleted, and what was going to be deleted is overwritten to a file. Help me understand what I'm doing wrong?

I’ll add some information: Model class:

 public class Person implements Serializable { private static final long serialVersionUID = -3763710615439958865L; private static AtomicInteger nextID = new AtomicInteger(0); private int id; private String name; private String surname; private int age; private String email; private Person(int id, String name, String surname, int age, String email) { this.id = id; this.name = name; this.surname = surname; this.age = age; this.email = email; } public Person(String name, String surname, int age, String email) { this(nextID.getAndIncrement(), name, surname, age, email); } private int getId() { return id; } public String getName() { return name; } public String getSurname() { return surname; } public int getAge() { return age; } public String getEmail() { return email; } public static PersonBuilder newBuilder() { return new PersonBuilder(); } @Override public String toString() { return "\n\nID: " + getId() + "\nName: " + getName() + "\nSurname: " + getSurname() + "\nAge: " + getAge() + "\nE_mail: " + getEmail(); }} 

One of the classes in the Controller package, where the logic for the "remove" command is implemented:

 public class DeleteCommand implements Command { private String fileName; private String searchString; private List<Person> people = new ArrayList<>(); private Person person; public DeleteCommand(String fileName, String searchString, Person person) { this.fileName = fileName; this.searchString = searchString; this.person = person; } @Override public void execute(String[] args) { try(BufferedReader reader = new BufferedReader(new FileReader(fileName)); BufferedWriter writer = new BufferedWriter(new FileWriter(fileName))){ while ((reader.readLine()) != null){ people.add(person); } List<Person> filteredList = people.stream().filter(p -> p.getSurname().equals(searchString)).collect(Collectors.toList()); people.removeAll(filteredList); writer.write(person.getName()+ "\r" + pperson.getSurname() + "\r" + person.getAge() + "\r" + person.getEmail() + "\r\n\r\n"); } catch (IOException e){ throw new RuntimeException(e); }}} 
  • one
    if it is a real code, then it is strange. You add links to a person to the people list by the number of lines in the input file, then perform some manipulations with this list, then write data from the person to the output file and finish this (the list does not participate in the record at all). - zRrr
  • Well, people, in this case, this is not a list, but a collection of List <Person> people. Those. just reassigning the original link to the filtered collection (i.e. people = filteredList). In any case, as I understand it. But, if I understand something wrong, tell me how it is right. I can place more code to make it clearer if needed. - Alex
  • in the output file, only the object that you want to delete ( person ) writer.write(person.getName()... , because the line writer.write(person.getName()... writes it there and this is the only line that writes to the file. Reading is also bad, t. because you simply ignore the lines read from the file. The filtering could be replaced with removeIf , but it is working. - zRrr
  • ok, I will try with removeif ... - Alex
  • one
    you do not save your list to a file - zRrr

1 answer 1

If you focus on the symptoms described by you, then obviously, the predicate condition should be reversed.

 .filter(p -> !p.getSurname().equals(searchString)). 

But judging by the code, the described cannot happen at all. It doesn’t matter what and how you filter if you don’t use the result of the filter. Instead of writing to the people list file, you write the person .

This is how you can accomplish your task:

 class Person { private final String name; private final String surname; private int age; private String email; public Person(String name, String surname) { this.name = name; this.surname = surname; } public static Person valueOf(String[] fields) { Person person = new Person(fields[0], fields[1]); person.setAge(Integer.parseInt(fields[2])); person.setEmail(fields[3]); return person; } public String getName() { return name; } public String getSurname() { return surname; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String toString() { return String.format("%s\t%s\t%d\t%s", name, surname, age, email); } } class DeleteCommand implements Command { private final String fileName; private final Predicate<Person> condition; public DeleteCommand(String fileName, Predicate<Person> condition) { this.fileName = fileName; this.condition = condition; } @Override public void execute(String[] args) { try { Path path = Paths.get(fileName); Path tmp = Files.createTempFile(fileName, ".tmp"); try (Stream<String> stream = Files.lines(path, StandardCharsets.UTF_8); PrintWriter pw = new PrintWriter(tmp.toString(), StandardCharsets.UTF_8.toString())) { stream.map(s -> s.split("\t")) .map(Person::valueOf) .filter(condition) .forEachOrdered(pw::println); } Files.copy(tmp, path, StandardCopyOption.REPLACE_EXISTING); } catch (IOException exc) { exc.printStackTrace(); } } } public class Example { public static void main(String[] args) { String searchString = "Doe"; Predicate<Person> predicate = p -> p.getSurname().equals(searchString); Command command = new DeleteCommand("people.csv", predicate.negate()); command.execute(null); } } 
  • I also thought so, but, unfortunately, even after the change - the result is the same. And this makes it even more incomprehensible what is wrong ... - Alex
  • the code did not become clearer .. people.add(person); Why is always the same person added and how is it related to what is in the file? - keekkenen