2017-01-13 3 views
2

Я реорганизую небольшой инструмент, который должен перебирать список файлов и изменять их на лету.Неправильно ли открыть файл для записи, прежде чем он будет закрыт для чтения?

В настоящий момент он выполняет операцию модификации одним способом, что означает, что он считывает файл в память, изменяет содержимое в памяти и записывает этот контент обратно в одно и то же местоположение файла.

Это делает все это в нескольких инструкциях try-with-resource. Однако это означает, что «открыто для записи» выполняется до того, как чтение будет закрыто.

Ниже приведено небольшое приближение (см. Метод «correctTxt»).

Чтобы проверить это, пожалуйста, создайте файл "FileQuestion.txt" с текстом, такие как

шустрая слон перепрыгивает через ленивую собаку

public class Demo 
{ 
    public static void main(String[] args) throws Exception 
    { 
     final File txtFile = new File("FileQuestion.txt"); 

     correctTxt(txtFile); 
    } 

    static void correctTxt(File txtFile) throws IOException 
    { 
     try (BufferedReader reader = new BufferedReader(new InputStreamReader (new BufferedInputStream(new FileInputStream(txtFile))))) { 
      String line = reader.readLine(); 
      if (line!=null) { 
       line = line.replace("elephant", "fox"); 
       try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(txtFile))) { 
        bos.write(line.getBytes()); 
        bos.flush(); 
       } 
      } 
     } 
    } 
} 

Он работает. Все это делается в одном процессе (один поток).

Вопрос заключается в том,

Это принципиально неправильно выполнить операцию записи до завершения чтения, в том, что делается в методе correctTxt?

Примечание: После первого чтения не предполагается, что дальнейшее чтение будет сделано.

+0

Я хотел бы отложить до основного принципа объектно-ориентированного программирования: Вместо того, чтобы идти с кодом, который появляется на работу, написать код, который гарантированно работать. Закрытие InputStream до открытия OutputStream гарантированно будет работать. – VGR

+0

Я предполагаю, что я спрашиваю, не вопрос стиля или попытка написать идеальный объектно-ориентированный код, но выяснить, есть ли на чисто техническом уровне (низкий уровень) причина полагать, что код может потерпеть неудачу. – svaens

+0

Я был удивлен, обнаружив, что код не терпит неудачу в Windows 7, который печально известен тем, что файл заблокирован до тех пор, пока открыт InputStream или OutputStream. Помимо Windows, я не ожидаю, что это создаст проблему. Я хотел сказать, что, если кто-то не сможет гарантировать, что это никогда не будет проблемой в Windows, я бы не рискнул. – VGR

ответ

1

Хороший вопрос. Я бы сказал, что это, вероятно, технически не проблема, но ... Я вижу, что объем try-with излишне большой, и если вы уменьшите масштаб до того, где он нужен, вы даже не будете в этой ситуации ,

Смотрите эту версию correctTxt с минимальным примерочным с областями

static void correctTxt(File txtFile) throws IOException { 
    String line; 
    try (BufferedReader reader = new BufferedReader(new InputStreamReader (new BufferedInputStream(new FileInputStream(txtFile))))) { 
     line = reader.readLine(); 
    } 
    if (line!=null) { 
     line = line.replace("elephant", "fox"); 
     try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(txtFile))) { 
      bos.write(line.getBytes()); 
      bos.flush(); 
     } 
    } 
} 
+0

Спасибо за ваш ответ!Да, я думаю, я могу сделать это так (фактический код немного сложнее и потребует немного больше рефакторинга, чем это, но в принципе я могу добиться того же, что и это). Но я предполагаю, что я больше спрашиваю о технической низкоуровневой основе, если есть основания полагать, что код может потерпеть неудачу. Я ищу дополнительную информацию о файлах, файловых дескрипторах, о том, как они управляются, на низком уровне. Файл заблокирован только для процесса, да? Может ли открытый входной поток вмешиваться в последующий открытый выходной поток .. и т. Д. – svaens

Смежные вопросы