Java Tutorial/File/ByteBuffer

Материал из Java эксперт
Перейти к: навигация, поиск

A ByteBuffer is a fixed-capacity buffer that holds byte values.

import java.nio.ByteBuffer;
public class Main {
  public static void main(String[] argv) throws Exception {
    
    byte[] bytes = new byte[10];
    ByteBuffer buf = ByteBuffer.wrap(bytes);
  }
}





Allocation automatically zeroes the ByteBuffer

import java.nio.ByteBuffer;
public class MainClass {
  private static final int BSIZE = 1024;
  public static void main(String[] args) {
    ByteBuffer bb = ByteBuffer.allocate(BSIZE);
     int i = 0;
    while (i++ < bb.limit())
      if (bb.get() != 0)
        System.out.println("nonzero");
    System.out.println("i = " + i);
  }
}





ByteBuffer.hasRemaining()

import java.nio.ByteBuffer;
public class MainClass {
  public static void main(String[] args) {
    ByteBuffer bb = ByteBuffer.wrap(new byte[] { 0, 0, 0, 0, 0, 0, 0, "a" });
    bb.rewind();
    System.out.println("Byte Buffer");
    while (bb.hasRemaining())
      System.out.println(bb.position() + " -> " + bb.get());
  }
}
/**/



Byte Buffer
0 -> 0
1 -> 0
2 -> 0
3 -> 0
4 -> 0
5 -> 0
6 -> 0
7 -> 97


Converting Between a ByteBuffer an a Byte Array

import java.nio.ByteBuffer;
public class Main {
  public static void main(String[] argv) throws Exception {
    // Create a ByteBuffer from a byte array
    byte[] bytes = new byte[10];
    ByteBuffer buf = ByteBuffer.wrap(bytes);
  }
}





Converting text to and from ByteBuffers

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
public class MainClass {
  private static final int BSIZE = 1024;
  public static void main(String[] args) throws Exception {
    FileChannel fc = new FileOutputStream("data2.txt").getChannel();
    fc.write(ByteBuffer.wrap("Some text".getBytes()));
    fc.close();
    fc = new FileInputStream("data2.txt").getChannel();
    ByteBuffer buff = ByteBuffer.allocate(BSIZE);
    fc.read(buff);
    buff.flip();
    System.out.println(buff.asCharBuffer());
    // Decode using this system"s default Charset:
    buff.rewind();
    String encoding = System.getProperty("file.encoding");
    System.out.println("Decoded using " + encoding + ": " + Charset.forName(encoding).decode(buff));
    // Or, we could encode with something that will print:
    fc = new FileOutputStream("data2.txt").getChannel();
    fc.write(ByteBuffer.wrap("Some text".getBytes("UTF-16BE")));
    fc.close();
  }
}
/**/



????
Decoded using Cp1252: Some text


Converting text to and from ByteBuffers with UTF-16BE

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
public class MainClass {
  private static final int BSIZE = 1024;
  public static void main(String[] args) throws Exception {
    FileChannel fc = new FileOutputStream("data2.txt").getChannel();
    fc.write(ByteBuffer.wrap(
      "Some text".getBytes("UTF-16BE")));
    fc.close();
    ByteBuffer buff = ByteBuffer.allocate(BSIZE);
    // Now try reading again:
    fc = new FileInputStream("data2.txt").getChannel();
    buff.clear();
    fc.read(buff);
    buff.flip();
    System.out.println(buff.asCharBuffer());
    
  }
}
/**/



Some text


Create a ByteBuffer using a byte array

import java.nio.ByteBuffer;
public class Main {
  public static void main(String[] argv) throws Exception {
    
    byte[] bytes = new byte[10];
    ByteBuffer buf = ByteBuffer.wrap(bytes);
  }
}





Create a direct (memory-mapped) ByteBuffer with a 10 byte capacity.

import java.nio.ByteBuffer;
public class Main {
  public static void main(String[] argv) throws Exception {
    ByteBuffer buf = ByteBuffer.allocateDirect(10);
  }
}





Create a non-direct ByteBuffer with a 10 byte capacity

import java.nio.ByteBuffer;
public class Main {
  public static void main(String[] argv) throws Exception {
    ByteBuffer buf = ByteBuffer.allocate(10);
  }
}





Endian differences and data storage

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
public class MainClass {
  public static void main(String[] args) {
    ByteBuffer bb = ByteBuffer.wrap(new byte[12]);
    bb.asCharBuffer().put("abcdef");
    System.out.println(toString(bb.array()));
    bb.rewind();
    bb.order(ByteOrder.BIG_ENDIAN);
    bb.asCharBuffer().put("abcdef");
    System.out.println(toString(bb.array()));
    bb.rewind();
    bb.order(ByteOrder.LITTLE_ENDIAN);
    bb.asCharBuffer().put("abcdef");
    System.out.println(toString(bb.array()));
  }
  public static String toString(byte[] a) {
    StringBuffer result = new StringBuffer("[");
    for (int i = 0; i < a.length; i++) {
      result.append(a[i]);
      if (i < a.length - 1)
        result.append(", ");
    }
    result.append("]");
    return result.toString();
  }
}
/*
 * [0, 97, 0, 98, 0, 99, 0, 100, 0, 101, 0, 102] [0, 97, 0, 98, 0, 99, 0, 100,
 * 0, 101, 0, 102] [97, 0, 98, 0, 99, 0, 100, 0, 101, 0, 102, 0]
 */





Get remaining byte count in a ByteBuffer

import java.nio.ByteBuffer;
public class Main {
  public static void main(String[] argv) throws Exception {
    ByteBuffer buf = ByteBuffer.allocateDirect(10);
    int rem = buf.remaining();
  }
}





Get the ByteBuffer"s capacity

import java.nio.ByteBuffer;
public class Main {
  public static void main(String[] argv) throws Exception {
    ByteBuffer buf = ByteBuffer.allocateDirect(10);
    int capacity = buf.capacity(); // 10
  }
}





Putting Bytes into a ByteBuffer

import java.nio.ByteBuffer;
public class Main {
  public static void main(String[] argv) throws Exception {
    ByteBuffer bbuf = ByteBuffer.allocate(10);
    int capacity = bbuf.capacity(); // 10
    System.out.println(capacity);
    bbuf.put((byte) 0xFF); 
    bbuf.position(5);
    bbuf.put((byte) 0xFF);
    int pos = bbuf.position(); 
    int rem = bbuf.remaining();
    bbuf.limit(7); 
    bbuf.rewind(); 
  }
}





Read from a channel with a ByteBuffer

import java.io.FileInputStream;
import java.nio.ByteBuffer;
import java.nio.channels.ReadableByteChannel;
public class Main {
  public static void main(String[] argv) throws Exception {
    ReadableByteChannel channel = new FileInputStream("infile").getChannel();
    ByteBuffer buf = ByteBuffer.allocateDirect(10);
    int numRead = 0;
    while (numRead >= 0) {
      buf.rewind();
      numRead = channel.read(buf);
      buf.rewind();
      for (int i = 0; i < numRead; i++) {
        byte b = buf.get();
      }
    }
  }
}





Retrieve all bytes in the buffer

import java.nio.ByteBuffer;
public class Main {
  public static void main(String[] argv) throws Exception {
    byte[] bytes = new byte[10];
    ByteBuffer buf = ByteBuffer.wrap(bytes);
    buf.clear();
    bytes = new byte[buf.capacity()];
    buf.get(bytes, 0, bytes.length);
  }
}





Retrieve bytes between the position and limit

import java.nio.ByteBuffer;
public class Main {
  public static void main(String[] argv) throws Exception {
    byte[] bytes = new byte[10];
    ByteBuffer buf = ByteBuffer.wrap(bytes);
    bytes = new byte[buf.remaining()];
    buf.get(bytes, 0, bytes.length);
  }
}





Rewind a ByteBuffer

import java.nio.ByteBuffer;
public class MainClass {
  private static final int BSIZE = 1024;
  public static void main(String[] args) {
    ByteBuffer bb = ByteBuffer.allocate(BSIZE);
    bb.asCharBuffer().put("Howdy!");
    char c;
    while ((c = bb.getChar()) != 0)
      System.out.print(c + " ");
    System.out.println();
    bb.rewind();
    // Store and read a short:
    bb.asShortBuffer().put((short) 471142);
    System.out.println(bb.getShort());
  }
}
/**/



H o w d y ! 
12390


Set the limit for ByteBuffer

import java.nio.ByteBuffer;
public class Main {
  public static void main(String[] argv) throws Exception {
    ByteBuffer buf = ByteBuffer.allocateDirect(10);
    buf.limit(7); // remaining=1
  }
}





Set the position

import java.nio.ByteBuffer;
public class Main {
  public static void main(String[] argv) throws Exception {
    ByteBuffer buf = ByteBuffer.allocateDirect(10);
    buf.position(5);
  }
}





Store and read a char array

import java.nio.ByteBuffer;
public class MainClass {
  private static final int BSIZE = 1024;
  public static void main(String[] args) {
    ByteBuffer bb = ByteBuffer.allocate(BSIZE);
    bb.asCharBuffer().put("Howdy!");
    char c;
    while ((c = bb.getChar()) != 0)
      System.out.print(c + " ");
    System.out.println();
  }
}//



H o w d y !


Store and read a double

import java.nio.ByteBuffer;
public class MainClass {
  private static final int BSIZE = 1024;
  public static void main(String[] args) {
    ByteBuffer bb = ByteBuffer.allocate(BSIZE);
    bb.asDoubleBuffer().put(99471142);
    System.out.println(bb.getDouble());
  }
}
/*
*/



9.9471142E7


Store and read a float

import java.nio.ByteBuffer;
public class MainClass {
  private static final int BSIZE = 1024;
  public static void main(String[] args) {
    ByteBuffer bb = ByteBuffer.allocate(BSIZE);
    bb.asFloatBuffer().put(99471142);
    System.out.println(bb.getFloat());
  }
}
/**/



9.9471144E7


Store and read a long

import java.nio.ByteBuffer;
public class MainClass {
  private static final int BSIZE = 1024;
  public static void main(String[] args) {
    ByteBuffer bb = ByteBuffer.allocate(BSIZE);
    bb.asLongBuffer().put(99472342341142L);
    System.out.println(bb.getLong());
  }
}
/**/



99472342341142


Store and read an int

import java.nio.ByteBuffer;
public class MainClass {
  private static final int BSIZE = 1024;
  public static void main(String[] args) {
    ByteBuffer bb = ByteBuffer.allocate(BSIZE);
    bb.asIntBuffer().put(99471142);
    System.out.println(bb.getInt());
  }
}
/**/



99471142


Store and read a short

import java.nio.ByteBuffer;
public class MainClass {
  private static final int BSIZE = 1024;
  public static void main(String[] args) {
    ByteBuffer bb = ByteBuffer.allocate(BSIZE);
    bb.asCharBuffer().put("Howdy!");
    char c;
    while ((c = bb.getChar()) != 0)
      System.out.print(c + " ");
    System.out.println();
    bb.rewind();
    // Store and read a short:
    bb.asShortBuffer().put((short) 471142);
    System.out.println(bb.getShort());
  }
}
/**/



H o w d y ! 
12390


Test views of long elements in a ByteBuffer

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
/**
 * Test views of long elements in a ByteBuffer.
 * 
 */
public class MainClass {
  public static void main(String[] argv) throws Exception {
    ByteBuffer bb = ByteBuffer.allocate(20);
    bb.put((byte) 0x07);
    bb.put((byte) 0x08);
    bb.put((byte) 0x09);
    bb.put((byte) 0x10);
    bb.put((byte) 0x11);
    bb.put((byte) 0x12);
    bb.put((byte) 0x13);
    bb.put((byte) 0x14);
    bb.position(1).limit(5);
    bb.mark();
    System.out.println("Expect an exception here");
    System.out.println("" + bb.order().toString() + ": " + bb.getLong());
  }
}
/**/



Expect an exception here
Exception in thread "main" java.nio.BufferUnderflowException
  at java.nio.Buffer.nextGetIndex(Buffer.java:404)
  at java.nio.HeapByteBuffer.getLong(HeapByteBuffer.java:387)
  at MainClass.main(MainClass.java:25)


This convenience method sets the position to 0

import java.nio.ByteBuffer;
public class Main {
  public static void main(String[] argv) throws Exception {
    ByteBuffer buf = ByteBuffer.allocateDirect(10);
    buf.rewind(); // remaining=7
  }
}





Use FileChannel and ByteBuffer to Copy File

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
public class Main {
  public static void main(String[] args) throws Exception {
    String source = "s.txt";
    String destination = "d.txt";
    FileInputStream fis = new FileInputStream(source);
    FileOutputStream fos = new FileOutputStream(destination);
    FileChannel fci = fis.getChannel();
    FileChannel fco = fos.getChannel();
    ByteBuffer buffer = ByteBuffer.allocate(1024);
    while (true) {
      int read = fci.read(buffer);
      if (read == -1)
        break;
      buffer.flip();
      fco.write(buffer);
      buffer.clear();
    }
  }
}





Use the absolute get().

import java.nio.ByteBuffer;
public class Main {
  public static void main(String[] argv) throws Exception {
    ByteBuffer buf = ByteBuffer.allocateDirect(10);
    byte b = buf.get(5); // position=0
  }
}





Use the relative get()

import java.nio.ByteBuffer;
public class Main {
  public static void main(String[] argv) throws Exception {
    ByteBuffer buf = ByteBuffer.allocateDirect(10);
    byte b = buf.get();
  }
}





Use while loop to read a ByteBuffer

import java.nio.ByteBuffer;
public class MainClass {
  public static void main(String[] args) {
    ByteBuffer bb = ByteBuffer.wrap(new byte[] { 0, 0, 0, 0, 0, 0, 0, "a" });
    bb.rewind();
    System.out.println("Byte Buffer");
    while (bb.hasRemaining())
      System.out.println(bb.position() + " -> " + bb.get());
  }
}
/**/



Byte Buffer
0 -> 0
1 -> 0
2 -> 0
3 -> 0
4 -> 0
5 -> 0
6 -> 0
7 -> 97