#java #nio #bufferedwriter #filechannel #java.nio.file
#java #nio #bufferedwriter #filechannel #java.nio.file
Вопрос:
Ниже приведен мой код. Я могу успешно прочитать файл. Но не может выполнить повторную запись в него с замененным содержимым с помощью BufferedWriter. Но можно сделать это с помощью ByteBuffer. Любые предложения, пожалуйста, где я ошибаюсь.
myFile.txt содержание:
Key1-Value1
Key2-Value2
Key3-Value3
Код Java ниже:
String fileAbsolutePath = "C:\myPath\myFile.txt";
try {
RandomAccessFile file = new RandomAccessFile(fileAbsolutePath, "rw");
FileChannel fileChannel = file.getChannel();
FileLock lock = fileChannel.lock();
// read from the channel
BufferedReader bufferedReader = new BufferedReader(Channels.newReader(fileChannel, "UTF-8"));
List<String> filteredList = bufferedReader.lines().filter(line -> !line.contains("KEY1-VALUE1")).onClose(() -> {
try {
bufferedReader.close();
} catch (IOException ex) {
throw new UncheckedIOException(ex);
}
}).collect(Collectors.toList());
fileChannel.truncate(0);
BufferedWriter bufferedWriter = new BufferedWriter(Channels.newWriter(fileChannel, "UTF-8"));
for (String string : list) {
bufferedWriter.write(string);//does n't work
bufferedWriter.newLine();
}
lock.release();
file.close();
fileChannel.close();
} catch (Exception e) {
e.printStackTrace();
}
Часть ByteBuffer, которая работает:
ByteBuffer buff = null;
for (int i = 0; i < filteredList.size(); i ) {
buff = ByteBuffer.wrap(filteredList.get(i).concat("n").getBytes(StandardCharsets.UTF_8));
fileChannel.write(buff);
}
Задача заключается в достижении того же с помощью BufferedWriter
Обновленный код после попытки try-with-resources
try (RandomAccessFile file = new RandomAccessFile(fileAbsolutePath, "rw");
FileChannel fileChannel = file.getChannel();
FileLock lock = fileChannel.lock();
BufferedReader bufferedReader = new BufferedReader(Channels.newReader(fileChannel, "UTF-8"));
BufferedWriter bufferedWriter = new BufferedWriter(Channels.newWriter(fileChannel, "UTF-8"))) {
// read from the channel
List<String> list = bufferedReader.lines().filter(line -> !line.contains("Key1-Value1"))
.collect(Collectors.toList());
fileChannel.truncate(0);
list.forEach(item -> {
try {
bufferedWriter.write(item.concat("n"));
} catch (IOException e) {
e.printStackTrace();
}
});
bufferedWriter.flush();
}
Комментарии:
1. быстрый вопрос, но почему вы просто не используете NIO ?
Files.write(path, list)
.2. Обратите внимание, что в вашем коде есть утечки ресурсов, потому что вы не используете try-with-resources .
3.
// TODO handle exception
Первый.e.printStacktrace();
4. @JoopEggen Готово. Но исключения как такового нет. Похоже, что часть кода BufferedWriter не может получить доступ к открытому файловому каналу
5. @Zabuzard Мне нужно заблокировать файл, поскольку есть вероятность, что другие процессы одновременно обращаются к файлу. Files.write(путь, список); выдает исключение java.io.IOException: процесс не может получить доступ к файлу, поскольку другой процесс заблокировал часть файла
Ответ №1:
Вы не очищаете BufferedWriter в конце, что означает, что он содержит некоторые или все строки, которые вы хотите записать обратно. Добавьте flush() перед закрытием каналов, чтобы убедиться, что буфер записан:
bufferedWriter.flush();
lock.release();
В идеале вы должны использовать try()
with resources, чтобы все ваши файлы были аккуратно закрыты в соответствующее время.
Комментарии:
1. Реализованы ваши предложения. Смотрите Код описания вопроса под заголовком «Обновленный код после попытки try-with-resources», получая поток «main» java.nio.channels. Исключение ClosedChannelException при использовании try-with-resources. Что я мог снова делать неправильно?
2. Интересно — вы можете переместить RandomAccessFile / FileChannel / FileLock в a
try()
и удалить release / close / close в конце, но, похоже, вам придется оставить BufferedReader и BufferedWriter и flush() такими, какими они были, потому что, если они автоматически закрываются, это портит канал.3. flush() работает как и раньше. Давайте попробуем вывести BufferedReader / Writer из try
4. Огромное спасибо! BufferedReader / Writer, перемещенный из try (), работает нормально!