Я запутался с Java NIO - PullRequest
       7

Я запутался с Java NIO

1 голос
/ 06 марта 2019

Я запутался с буферами java nio и Files.write, если я могу писать с буферами и каналами в файле, зачем мне нужен класс Files.

В чем разница между обоими этими примерами рабочего кода.

String newData = "New String to write to file..." + System.currentTimeMillis();

Path path = Paths.get("C://data/nio-data2.txt");
try {
    Files.write(path,newData.getBytes());
} catch (IOException e) {
    e.printStackTrace();
}

и

try {
    RandomAccessFile aFile = new RandomAccessFile("C://data/nio-data.txt", "rw");
    FileChannel channel = aFile.getChannel();
    ByteBuffer buf = ByteBuffer.allocate(48);
    buf.clear();
    buf.put(newData.getBytes());

    buf.flip();

    while(buf.hasRemaining()) {
        channel.write(buf);
    }
} catch (FileNotFoundException e) {
    e.printStackTrace();
} catch (IOException e) {
    e.printStackTrace();
}

EDIT

Я хочу задать еще один вопрос, является ли Channels.newOutputStream прерывать поток при записи в файл или работает как неблокирующая

Ответы [ 2 ]

2 голосов
/ 06 марта 2019

Версия с Files короче и проще для понимания.

Другая версия более гибкая. Это не очень полезно, когда у вас есть только один файл для записи, но если у вас много файлов в разных хранилищах, это может сэкономить вам некоторые ресурсы.

EDIT

Вот Files.write исходный код:

public static Path write(Path path, byte[] bytes, OpenOption... options)
    throws IOException
{
    // ensure bytes is not null before opening file
    Objects.requireNonNull(bytes);

    try (OutputStream out = Files.newOutputStream(path, options)) {
        int len = bytes.length;
        int rem = len;
        while (rem > 0) {
            int n = Math.min(rem, BUFFER_SIZE);
            out.write(bytes, (len-rem), n);
            rem -= n;
        }
    }
    return path;
}

Как вы видите, он не использует NIO внутри, только старый добрый OutputStream.

РЕДАКТИРОВАТЬ 2

На самом деле Files.newOutputStream не верните FileOutputStream, как я ожидал. Он возвращает OutputStream, определенный в Channels.newOutputStream, который использует NIO внутри.

1 голос
/ 06 марта 2019
  1. Files.write(...) используйте OutputStream вместо RandomAccessFile.getChannel(). это какие-то разные механизмы, так что лучше гуглить, чтобы понять

  2. Files.write(...) гораздо более короткая и инкапсулированная логика записи в файл

  3. Когда вы используете такой «низкий» код, вам нужно заботиться о многих вещах. Например, в вашем примере вы не закрыли свой канал.

Итак, в заключение, если вам нужно просто написать - лучше использовать Files или другой высокоуровневый API. Если вам нужны некоторые «дополнительные» функции во время чтения / записи, вам нужно использовать RandomAccessFile или InputStream/OutputStream

...