почему буферы не были записаны в FileChannel

2

Я изучаю java NIO сейчас, я нашел пример, чтобы объяснить операцию сбора для FileChannel, как показано ниже:

public class ScattingAndGather {
    public static void main(String args[]) {
        gather();
    }

    public static void gather() {
        ByteBuffer header = ByteBuffer.allocate(10);
        ByteBuffer body = ByteBuffer.allocate(10);

        byte[] b1 = { '0', '1' };
        byte[] b2 = { '2', '3' };
        header.put(b1);
        body.put(b2);

        ByteBuffer[] buffs = { header, body };

        FileOutputStream os = null;
        FileChannel channel = null;
        try {
            os = new FileOutputStream("d:/scattingAndGather.txt");
            channel = os.getChannel();
            channel.write(buffs);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            if (channel != null) {
                try {
                    channel.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

в то время как результат показывает, что файл был создан, но он пуст, который должен быть 0123 в нем, что неправильно для примера?

Теги:
filechannel
nio

1 ответ

2
Лучший ответ

Проблемы возникают из-за того, что вы никогда не сбросили буферную позицию.

Когда вы создаете оба объекта ByteBuffer они начинаются с нуля. Всякий раз, когда вы добавляете в них контент, их позиция продвигается, а это означает, что когда вы пытаетесь записать их, они сообщают, что больше нет байтов для чтения. Таким образом, прежде чем выполнять какую-либо операцию, вам нужно как-то сбросить свое положение.

Buffer предлагает несколько методов, наиболее простым в использовании является flip(). Как вы можете видеть в документации здесь, это использование:

Отбрасывает этот буфер. Предел установлен в текущую позицию, а затем позиция установлена на ноль. Если знак определен, он отбрасывается.

После последовательности операций чтения или посылки канала вызывается этот метод для подготовки к последовательности операций записи канала или относительной операции get

Таким образом, прежде чем писать их, вам нужно перевернуть их. Кроме того, поскольку вы экспериментируете с java.nio я не понимаю, почему вы не должны использовать try with resources операторами try with resources для управления вашими различными ресурсами. Таким образом, вы избежите чрезмерного кода котловой плиты закрытия ресурсов, которые могут быть автоматически закрыты вручную.

Используя те, которые ваш код может значительно уменьшить и быть более читабельными:

public static void gather() {
    ByteBuffer header = ByteBuffer.allocate(10);
    ByteBuffer body = ByteBuffer.allocate(10);

    byte[] b1 = { '0', '1' };
    byte[] b2 = { '2', '3' };
    header.put(b1);
    body.put(b2);

    //flip buffers before writing them out.
    header.flip();
    body.flip();
    ByteBuffer[] buffs = { header, body };

    try(FileOutputStream os = new  FileOutputStream("d:/scattingAndGather.txt");
 FileChannel channel = os.getChannel()) {
    channel.write(buffs);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню