Я изучаю 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 в нем, что неправильно для примера?
Проблемы возникают из-за того, что вы никогда не сбросили буферную позицию.
Когда вы создаете оба объекта 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();
}
}