betacode

Руководство Java WritableByteChannel

  1. WritableByteChannel
  2. Methods
  3. write(ByteBuffer src)
  4. Example 1

1. WritableByteChannel

Если вы только начинаете работать с Java NIO, сначала прочитайте следующие статьи, чтобы узнать больше об основах:
  • Java Nio
WritableByteChannel - это интерфейс, который расширяется от interface Channel, который представляет каналы, которые могут записывать bytes на устройство IO.
public interface WritableByteChannel extends Channel
По сравнению с родительским интерфейсом, WritableByteChannel предоставляет еще только один метод записи bytes из ByteBuffer в этот Channel.
public int write(ByteBuffer src) throws IOException;
Одновременно на Channel может выполняться только одна операция записи. Это означает, что если один thread инициирует операцию записи на Channel, другие thread не могут выполнять запись на этом Channel, они блокируются (block) до завершения операции. Другие операции IO могут выполняться одновременно с операцией записи в зависимости от типа Channel.
Иерархия интерфейсов и классов, относящихся к WritableByteChannel:

2. Methods

WritableByteChannel предоставляет только на один метод больше, чем его родительский интерфейс.
public int write(ByteBuffer src) throws IOException;
Другие методы наследуются от интерфейса Channel:
public boolean isOpen();  
public void close() throws IOException;

3. write(ByteBuffer src)

public int write(ByteBuffer byteBuffer) throws IOException;
Метод write(ByteBuffer) записывает последовательность bytes между position и limit-1 на указанном ByteBuffer в этот Channel. Он запишет как можно больше и вернет количество записанных bytes.
  • Каждый byte, записанный в этот Channel, увеличит положение курсора в ByteBuffer на 1.
  • Перед вызовом этого метода вы должны вызвать метод ByteBuffer.clear(), чтобы установить position =0 и limit = capacity.
  • Максимальное количество bytes, которое может быть записано за один вызов этого метода, равно byteBuffer.limit()-byteBuffer.position().
Метод попытается записать все bytes от position до limit-1 в этот Channel . Однако в некоторые типы Channel, такие как SocketChannel, в зависимости от его состояния, может быть записано всего несколько bytes. Поэтому вам нужно написать code, как показано ниже, чтобы убедиться, что все bytes успешно записаны:
while(byteBuffer.hasRemaining())  {
    channel.write(byteBuffer);
}
Одновременно на Channel может выполняться только одна операция записи. Это означает, что если один thread инициирует операцию записи на Channel, другие thread не могут выполнять запись на этом Channel, они блокируются (block) до завершения операции. Другие операции IO могут выполняться одновременно с операцией записи в зависимости от типа Channel.

4. Example 1

Например: Используйте WritableByteChannel для записи данных в файл.
WritableByteChannel_ex1.java
package org.o7planning.writablebytechannel.ex;

import java.io.Closeable;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.WritableByteChannel;

public class WritableByteChannel_ex1 {
    // Windows: "C:/somepath/out-file.txt";
    private static final String outFilePath = "/Volumes/Data/test/out-file.txt";

    public static void main(String[] args) throws IOException {  
        OutputStream outputStream = null;
        WritableByteChannel channel = null;
        try {
            byte[] byteData = "JP日本-八洲".getBytes("UTF-8");
            
            File outFile = new File(outFilePath);
            outFile.getParentFile().mkdirs(); // Make sure parent folder is exists.
            outputStream = new FileOutputStream(outFile);
            
            // Create WritableByteChannel to write data to an OutputStream.
            channel = Channels.newChannel(outputStream);
            
            ByteBuffer buffer = ByteBuffer.allocate(byteData.length);
            buffer.put(byteData);
            // Set limit = current position and position = 0;
            buffer.flip();
            
            while(buffer.hasRemaining())  {
                channel.write(buffer);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            closeQuietly(outputStream);
            closeQuietly(channel);
        }
    }

    private static void closeQuietly(Closeable closeable) {
        try {
            closeable.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
Как OutputStream, так и Channel реализуют (implements) или расширяются из interface Closeable, поэтому он может автоматически закрываться, если вы используете синтаксис "Closeable-try-catch". И мы перепишем приведенный выше пример более кратко.
WritableByteChannel_ex1b.java
package org.o7planning.writablebytechannel.ex;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.WritableByteChannel;

public class WritableByteChannel_ex1b {
    // Windows: "C:/somepath/out-file.txt";
    private static final String outFilePath = "/Volumes/Data/test/out-file.txt";

    public static void main(String[] args) throws IOException {
        File outFile = new File(outFilePath);
        outFile.getParentFile().mkdirs(); // Make sure parent folder is exists.

        // Closeable-try-catch Syntax:
        try (OutputStream outputStream = new FileOutputStream(outFile);
                // Create WritableByteChannel to write data to an OutputStream.
                WritableByteChannel channel = Channels.newChannel(outputStream);) { // try

            byte[] byteData = "JP日本-八洲".getBytes("UTF-8");
            ByteBuffer buffer = ByteBuffer.allocate(byteData.length);
            buffer.put(byteData);
            // Set limit = current position and position = 0;
            buffer.flip();

            while (buffer.hasRemaining()) {
                channel.write(buffer);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
  • Руководство Java Closeable