Почему исключение между начальной и конечной строками не будет работать должным образом в java?

У меня есть следующий файл, который представляет книги

Book: ISBN=3
title=english1
publishDate=1/12/2015
pageCount=200
authors=[12, 11, john]
-------------------------
Book: ISBN=5
title=english2
publishDate=1/12/2015
pageCount=200
authors=[12, 11, john2]
-------------------------
Book: ISBN=6
title=english3
publishDate=1/12/2015
pageCount=200
authors=[12, 11, john3]
-------------------------

Я попытался удалить вторую книгу из файла, используя эту функцию: Funtion:

public static void removeLineFromFile(String file, String start, String end) {
    try {

      File inFile = new File(file);

      //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;
      Boolean flag=true;
      //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(start)) {
         flag=false;  

        }
        if(line.trim().equals(end)){
         flag=true; 
        }

        if (flag && !(line.trim().equals(end))){
        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();
    }
}

вызов функции:

public static void main(String[] args) {
       removeLineFromFile("E:\\file.txt", "Book: ISBN=5","-------------------------")
}

книга была удалена, но другой раздел "-------------------------" также удален `

Book: ISBN=3
title=english1
publishDate=1/12/2015
pageCount=200
authors=[12, 11, john]
Book: ISBN=6
title=english3
publishDate=1/12/2015
pageCount=200
authors=[12, 11, john3]

Что мне делать, чтобы получить следующий результат:

Book: ISBN=3
title=english1
publishDate=1/12/2015
pageCount=200
authors=[12, 11, john]
-------------------------
Book: ISBN=6
title=english3
publishDate=1/12/2015
pageCount=200
authors=[12, 11, john3]
-------------------------

Ответы

Ответ 1

Это самое простое решение, которое я мог бы придумать:

public static void removeLineFromFile(String file, String start, String end) {
    try {

      File inFile = new File(file);

      //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;
      Boolean flag=true;
      //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(start)) {
         flag=false;  
        }

        if (flag){
        pw.println(line);
        pw.flush();
        }

        if(line.trim().equals(end)){
             flag=true; 
             continue; 
            }

      }
      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();
    }
}

Проблема заключалась в том, что вы устанавливали флаг слишком рано и, следовательно, не печатали строку.

Ответ 2

Ваша первая проблема связана с этой строкой:

if (flag && !(line.trim().equals(end)))

Так как вы уже проверили, соответствует ли текущая строка вашей конечной строке String и изменит флаг на true, весь этот оператор всегда будет истинным для каждого вхождения конца String. Вот почему каждая строка ------------------------- не находится на выходе.
Если вы удалите вторую часть в этом выражении if, это изменит ее на: if(flag){...}, вы достигнете того, что каждое появление конца строки будет в выводе.
Это приводит к второй проблеме с вашим кодом: заказ. Вы используете флаг в качестве клапана для ввода на выход. Вы сигнализируете своим флагом, чтобы отключить запись на выходе, когда нашли начальную строку. Затем проверьте, хотите ли вы сигнализировать о вводе вывода. И только тогда вы будете писать в зависимости от флага.
Вам нужно изменить порядок здесь, чтобы получить значимый поток данных.
Рассмотрим два состояния

Флаг TRUE означает, что ваш поток должен течь

  • Проверить начальную строку
  • Запись данных

Флаг FALSE означает, что ваш поток НЕ должен течь

  • Не записывать данные
  • Проверить конец строки

Вы можете добиться желаемого поведения с этим циклом while.

while ((line = br.readLine()) != null) {

    if (line.trim().equals(start)) {
        flag=false;  
    }

    if (flag){
        pw.println(line);
        pw.flush();
    }

    if(line.trim().equals(end)){
        flag=true; 
    }
}

Ответ 3

Вторая часть этого выражения - это то, почему ваш "-------------------------" удаляется (вы никогда не печатаете строки "end" ):

(flag && !(line.trim().equals(end)))

Ответ 4

Из-за этого.

if(line.trim().equals(end)){
    flag=true; 
}

if (flag && !(line.trim().equals(end))){
    pw.println(line);
    pw.flush();
}

В первом if флаг установлен true, но строка line.trim().equals(end) также верна для этого прогона в цикле, поэтому вторая, если никогда не будет посещаться, когда линия будет равна переменной end, В этом случае это -------------------.

Если ваш файл выглядит всегда одинаковым, вы можете изменить цикл на "когда вы найдете start, удалить следующие 5 строк", что на самом деле не эстетично, или вам нужно вложить новый цикл в первый if.

Вложенный цикл может выглядеть так:

while ((line = br.readLine()) != null) {
    if (line.trim().equals(start)) {
        while (!(line = br.readLine()).equals(end));
        line = br.readLine();
        // or you just write:
        // continue;
    }
    pw.println(line);
    pw.flush();
}

Второй, пока он просто спустится, пока не найдет конец, и это продолжается.

Ответ 5

Посмотрите на проблему с точки зрения режимов - вы либо находитесь в режиме копирования, либо нет. Если вы копируете, то, если вы не найдете шаблон начала, вы скопируете вход на выход. Если вы найдете шаблон начала, вы перейдете в режим без копирования.

В режиме без копирования вы просто смотрите на шаблон конца при переключении в режим копирования.

В кодовых терминах это становится

  Boolean copyMode=true;
  while ((line = br.readLine()) != null) {
    if(copyMode) {
        // Check for signal to stop copying
        if(line.trim().equals(start)) {
            copyMode = false;
            continue;
        }
        // Just copy to output file
        pw.println(line);
    } else {
        // Check for signal to restart copying
        if(line.trim().equals(end)) {
            copyMode = true;
        }
    }
}

Ответ 6

Ниже приведен обновленный код для этого

public static void removeLineFromFile(String file, String start, String end) {
    try {

      File inFile = new File(file);

      //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;
      Boolean flag=false;
      Boolean skip=false;

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

        if (flag || line.trim().equals(start)) {
         flag=true;
         skip =true;

        }

            if (!skip) {
                pw.println(line);
                pw.flush();
            }

        if(flag && line.trim().equals(end)){
            flag=false;
            skip=false;
        }

      }
      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();
    }
}

Обратите внимание на введение нового флага skip. Это поможет исключить содержимое из строки "Пуск" в конец строки.

Ответ 7

Это простое решение, при котором я подошел, он удалит все вещи, начиная с начала и конца строк, но только после того, как начнется строка начала.

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

        if (flag1&&line.trim().equals(start)) {
         flag1=false;  

        }
        if(!flag1&&line.trim().equals(end)){
                flag2 = false; 
                 flag1=true;  
        }

        if (flag1&&flag2){
                pw.println(line);
        pw.flush();

        }
        if(!flag2) flag2=true;

      }

Обратите внимание на введение нового flag1 и flag2 вместо flag.This поможет в исключении содержимого из строки Start в End string.