openplanning

Hướng dẫn và ví dụ Java GatheringByteChannel

  1. GatheringByteChannel
  2. Methods
  3. write(ByteBuffer[])
  4. write(ByteBuffer[], int, int)
  5. Example 1

1. GatheringByteChannel

Nếu bạn mới bắt đầu với Java NIO, hãy đọc trước các bài viết dưới đây để hiểu thêm về các khái niệm cơ bản:
  • Hướng dẫn và ví dụ Java Nio (Java New IO)
Như đã biết, WritableByteChannel là một interface cung cấp phương thức để ghi các bytes từ một ByteBuffer. GatheringByteChannel là một mở rộng từ WritableByteChannel, cung cấp các phương thức cho việc ghi tụ họp (gathering write). Trong một lần gọi, các bytes từ nhiều ByteBuffer(s) sẽ được ghi vào GatheringByteChannel.
public interface GatheringByteChannel extends WritableByteChannel
GatheringByteChannel channel =...; // (GatheringByteChannel)Channels.newChannel(fileOS);
ByteBuffer[] buffers = new ByteBuffer[]{buf1, buf2, buf3};
channel.write(buffers);
Hệ thống phân cấp các interface và các lớp có liên quan tới GatheringByteChannel:

2. Methods

Các phương thức được định nghĩa trong interface GatheringByteChannel:
public long write(ByteBuffer[] srcs, int offset, int length) throws IOException;

public long write(ByteBuffer[] srcs) throws IOException;
Các phương thức thừa kế từ interface WritableByteChannel:
public int write(ByteBuffer src) throws IOException;
Các phương thức thừa kế từ interface Channel:
public boolean isOpen();  
public void close() throws IOException;

3. write(ByteBuffer[])

public long write(ByteBuffer[] srcs) throws IOException;
Ghi một dẫy các bytes vào GatheringByteChannel này từ nhiều ByteBuffer đã cho. Phương thức trả về số bytes đã được ghi hoặc trả về -1 nếu đã tiến tới cuối kênh.
Việc gọi phương thức này tương đương với:
gatheringByteChannel.write(srcs, 0, srcs.length);
Tại một thời điểm chỉ một hoạt động ghi trên Channel được diễn ra. Điều này có nghĩa là nếu một thread đang bắt đầu thao tác ghi trên một Channel thì các thread khác không thể ghi trên Channel này, chúng bị chặn (block) cho tới khi hoạt động này hoàn thành. Các hoạt động IO khác có thể tiến hành đồng thời với hoạt động ghi hay không phụ thuộc vào loại Channel.

4. write(ByteBuffer[], int, int)

public long write(ByteBuffer[] srcs, int offset, int length) throws IOException;
Ghi một dẫy các bytes vào GatheringByteChannel này từ một mảng các ByteBuffer, từ chỉ số offset đến offset+length-1. Phương thức trả về số bytes đã được ghi hoặc trả về -1 nếu đã tiến tới cuối kênh.
Việc gọi phương thức này tương đương với:
ByteBuffer[] srcs2 = new ByteBuffer[] {srcs[offset], srcs[offset+1], .., srcs[offset+length-1]};

gatheringByteChannel.write(srcs2);
Tại một thời điểm chỉ một hoạt động ghi trên Channel được diễn ra. Điều này có nghĩa là nếu một thread đang bắt đầu thao tác ghi trên một Channel thì các thread khác không thể ghi trên Channel này, chúng bị chặn (block) cho tới khi hoạt động này hoàn thành. Các hoạt động IO khác có thể tiến hành đồng thời với hoạt động ghi hay không phụ thuộc vào loại Channel.

5. Example 1

Ví dụ: Viết một chương trình copy file, sử dụng ScatteringByteChannel để đọc file đầu vào và sử dụng GatheringByteChannel để ghi file.
GatheringByteChannel_ex1.java
package org.o7planning.gatheringbytechannel.ex;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.GatheringByteChannel;
import java.nio.channels.ScatteringByteChannel;

public class GatheringByteChannel_ex1 {

    // Windows: C:/somepath/test-file.txt
    private static final String inputFilePath = "/Volumes/Data/test/in-file.txt";

    private static final String outputFilePath = "/Volumes/Data/test/out-file.txt";

    public static void main(String[] args) throws IOException {
        try (// Input:
                FileInputStream fis = new FileInputStream(inputFilePath);
                ScatteringByteChannel inChannel = (ScatteringByteChannel) Channels.newChannel(fis);
                // Output:
                FileOutputStream fos = new FileOutputStream(outputFilePath);
                GatheringByteChannel outChannel = (GatheringByteChannel) Channels.newChannel(fos);) { // try

            ByteBuffer buf1 = ByteBuffer.allocate(10);
            ByteBuffer buf2 = ByteBuffer.allocate(15);
            ByteBuffer buf3 = ByteBuffer.allocate(10);

            ByteBuffer[] buffers = new ByteBuffer[] { buf1, buf2, buf3 };

            long bytesRead = -1;
            while ((bytesRead = inChannel.read(buffers)) != -1) {
                for (int i = 0; i < buffers.length; i++) {
                    System.out.println(" --- buffer[" + i + "] ---");
                    ByteBuffer buffer = buffers[i];
                    // Set limit = current position; position = 0;
                    buffer.flip();
                    outChannel.write(buffer);
                    buffer.clear();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}