Это продолжение к anonymous file streams reusing descriptorsInvalidate поток без закрытия
Согласно моему предыдущему вопросу, я не могу зависеть от кода, как это (бывает работать в JDK8, на данный момент):
RandomAccessFile r = new RandomAccessFile(...);
FileInputStream f_1 = new FileInputStream(r.getFD());
// some io, not shown
f_1 = null;
f_2 = new FileInputStream(r.getFD());
// some io, not shown
f_2 = null;
f_3 = new FileInputStream(r.getFD());
// some io, not shown
f_3 = null;
Однако, чтобы предотвратить случайные ошибки и как форму самодокументации, я хотел бы аннулировать каждый поток файлов после того, как я закончил использовать его - без закрытия базового дескриптора файла.
Каждый FileInputStream должен быть независимым, с позиционированием, контролируемым RandomAccessFile. Я разделяю тот же FileDescriptor, чтобы предотвратить любые условия гонки, возникающие при открытии одного и того же пути несколько раз. Когда я закончил с одним FileInputStream, я хочу сделать его недействительным, чтобы не было возможности случайно прочитать его при использовании второго FileInputStream (что привело бы к тому, что второй FileInputStream пропустил данные).
Как это сделать?
нота:
- в библиотеках, которые я использую требует compatibiity с java.io. *
- если вы предлагаете библиотеку (я предпочитаю Java встроенную семантику, если это вообще возможно), его должен быть общедоступным (упакованным) для linux (основной мишень) и использоваться на окнах (экспериментальная цель)
- , но поддержка окон не является обязательной.
Edit: в ответ на замечание, вот мой рабочий процесс:
RandomAccessFile r = new RandomAccessFile(String path, "r");
int header_read;
int header_remaining = 4; // header length, initially
byte[] ba = new byte[header_remaining];
ByteBuffer bb = new ByteBuffer.allocate(header_remaining);
while ((header_read = r.read(ba, 0, header_remaining) > 0) {
header_remaining -= header_read;
bb.put(ba, 0, header_read);
}
byte[] header = bb.array();
// process header, not shown
// the RandomAccessFile above reads only a small amount, so buffering isn't required
r.seek(0);
FileInputStream f_1 = new FileInputStream(r.getFD());
Library1Result result1 = library1.Main.entry_point(f_1)
// process result1, not shown
// Library1 reads the InputStream in large chunks, so buffering isn't required
// invalidate f_1 (this question)
r.seek(0)
int read;
while ((read = r.read(byte[4096] buffer)) > 0 && library1.continue()) {
library2.process(buffer, read);
}
// the RandomAccessFile above is read in large chunks, so buffering isn't required
// in a previous edit the RandomAccessFile was used to create a FileInputStream. Obviously that's not required, so ignore
r.seek(0)
Reader r_1 = new BufferedReader(new InputStreamReader(new FileInputStream(r.getFD())));
Library3Result result3 = library3.Main.entry_point(r_2)
// process result3, not shown
// I'm not sure how Library3 uses the reader, so I'm providing buffering
// invalidate r_1 (this question) - bonus: frees the buffer
r.seek(0);
FileInputStream f_2 = new FileInputStream(r.getFD());
Library1Result result1 = library1.Main.entry_point(f_2)
// process result1 (reassigned), not shown
// Yes, I actually have to call 'library1.Main.entry_point' *again* - same comments apply as from before
// invalidate f_2 (this question)
//
// I've been told to be careful when opening multiple streams from the same
// descriptor if one is buffered. This is very vague. I assume because I only
// ever use any stream once and exclusively, this code is safe.
//
Это может помочь, если вы объясните причину, что нужно открывать отдельные потоки на одном FD. Я предполагаю, что вы хотите последовательно читать из файла несколько раз, но тогда почему вы просто не разделяете «RandomAccessFile» с соответствующим конфликтующим контролем? У этого есть запах кода об этом, или возможность быть [проблема XY] (http://xyproblem.info/). –