자바

자바 NIO 버퍼 메소드 - 공통, 데이터를 읽고 저장하는, 버퍼 예외 종류

알통몬_ 2017. 4. 16. 19:06
반응형


안녕하세요 알통몬입니다.

공감 및 댓글은 포스팅 하는데 아주아주 큰 힘이 됩니다!!

포스팅 내용이 찾아주신 분들께 도움이 되길 바라며

더 깔끔하고 좋은 포스팅을 만들어 나가겠습니다^^

 


버퍼 메소드 Buffer :

버퍼 생성 후 사용할 때에는 Buffer 가 제공하는 메소드를 잘 활용해야 합니다.

버퍼마다 공통으로 사용되는 메소드가 있고 데이터 타입 별로 Buffer 가 개별적으로 가지는 메소드도 있습니다.


공통 메소드 :

각 타입 별로 버퍼 클래스는 Buffer 추상 클래스를 상속합니다.

BUffer 추상 클래스에는 모든 버퍼가 공통적으로 가져야 할 메소드들이 정의되어 있습니다.


데이터를 읽거나 저장하는 메소드

 : 버퍼에 데이터를 저장하는 메소드는 put() 이고 읽는 메소드는 get() 입니다

이 메소드들은 Buffer 추상 클래스에는 없고, 각 타입 별 하위 Buffer 클래스를 가집니다.

get() 과 put() 은 상대적과 절대적으로 구분합니다.


상대적 : 버퍼 내의 현재 위치 속성인 position 에서 데이터를 읽고 저장할 경우

get() 과 put()을 호출하면 position 값이 증가합니다.


절대적 : position 과 상관 없이 주어진 인덱스에서 데이터를 읽고 저장할 경우

get()과 put()을 호출하면 position 값이 증가하지 않습니다.


만약 position 값이 limit 값까지 증가했는데도 상대적 get()을 사용하면 BufferUnderflowException이 발생하고

put()을 사용하면 BufferOverflowException이 발생합니다.


ByteBuffer 와 CharBuffer 이 제공하는 get() , put()

index 매개 변수가 없으면 상대적이고

index 매개 변수가 있으면 절대적입니다.


버퍼 예외 종류

 : 버퍼가 다 찼을 때 데이터를 저장하려는 경우와 버퍼에서 더 이상 읽어올 데이터가 없을 때

데이터를 읽으려는 경우 예외가 발생합니다.


예제)

 import java.nio.Buffer;

import java.nio.ByteBuffer;


public class Example {

 public static void main(String[] args) {

  System.out.println("[[7바이트 크기로 버퍼 생성]]");

  ByteBuffer buffer = ByteBuffer.allocateDirect(7);

  printState(buffer);

  

  buffer.put((byte)10);

  buffer.put((byte)11);

  System.out.println("[[2바이트 저장후]]");

  printState(buffer);

  

  buffer.put((byte)12);

  buffer.put((byte)13);

  buffer.put((byte)14);

  System.out.println("[[3바이트 저장후]]");

  printState(buffer);

  

  buffer.flip();

  System.out.println("[flip() 실행후]");

  printState(buffer);

  

  buffer.get(new byte[3]);

  System.out.println("[[3바이트 읽은후]]");

  printState(buffer);

  

  buffer.mark();

  System.out.println("--------[[현재 위치를 마크 해놓음]]");

  

  buffer.get(new byte[2]);

  System.out.println("[[2바이트 읽은후]]");

  printState(buffer);

  

  buffer.reset();

  System.out.println("--------[[position을 마크 위치로 옮김]]");

  printState(buffer);

  

  buffer.rewind();

  System.out.println("[[rewind() 실행후]]");

  printState(buffer);

  

  buffer.clear();

  System.out.println("[[clear() 실행후]]");

  printState(buffer);

 }

 

 public static void printState(Buffer buffer) {

  System.out.print("\tposition:" + buffer.position() + ", ");

  System.out.print("\tlimit:" + buffer.limit() + ", ");

  System.out.println("\tcapacity:" + buffer.capacity());

 }

}


예제2) compact()를 호출한 후 변경된 버퍼 내용과 position, limit 위치

 import java.nio.ByteBuffer;


public class Example {

 public static void main(String[] args) {

  System.out.println("[[7바이트 크기로 버퍼 생성]]");

  ByteBuffer buffer = ByteBuffer.allocateDirect(7);

  buffer.put((byte)10);

  buffer.put((byte)11);

  buffer.put((byte)12);

  buffer.put((byte)13);

  buffer.put((byte)14);

  buffer.flip();

  printState(buffer);

  

  buffer.get(new byte[3]);

  System.out.println("[[3바이트 읽음]]");

  

  buffer.compact();

  System.out.println("[[compact() 실행후]]");

  printState(buffer);

 }

 

 public static void printState(ByteBuffer buffer) {

  System.out.print(buffer.get(0) + ", ");

  System.out.print(buffer.get(1) + ", ");

  System.out.print(buffer.get(2) + ", ");

  System.out.print(buffer.get(3) + ", ");

  System.out.println(buffer.get(4));

  System.out.print("position:" + buffer.position() + ", ");

  System.out.print("limit:" + buffer.limit() + ", ");

  System.out.println("capacity:" + buffer.capacity());

 }

}



버퍼 변환

 : 채널이 데이터를 읽고 쓰는 버퍼는 모두 ByteBuffer 입니다.

채널을 통해 읽은 데이터를 복원하려면 ByteBufer를 문자열이나 다른 타입의 버퍼로 

변환해야 합니다. 반대로 문자열 또는 다른 타입 버퍼의 내용을 채널을 통해 쓰려면 ByteBuffer로 변환해야 합니다.


ByteBuffer <-> String

 : 채널을 통해 문자열을 파일이나 네트워크로 전송하려면 특정 문자셋(UTF-8, EUC-KR)으로

인코딩 해 ByteBuffer로 변환해야 합니다.

문자셋을 표현하는 java.nio.charset.Charset 객체가 필요합니다.

Charset charset = Charset.forName("UTF-8");

Charset charset = Charset.defaultCharset(); // 운영체제가 사용하는 디폴트 문자셋


Charset을 이용하여 문자열을 ByteBuffer로 변환하려면

 => String data = "";

     ByteBuffer byteBuffer = charset.encode(data);

반대로 하려면

ByteBuffer byteBuffer = ...;

String data = charset.decode(byteBuffer).toString();


예제)

import java.nio.ByteBuffer;

import java.nio.charset.Charset;


public class Example {

 public static void main(String[] args) {

  Charset charset = Charset.forName("UTF-8");

  

  //문자열 -> 인코딩 -> ByteBuffer

  String data = "티스토리 블로그는 알통몬";

  ByteBuffer byteBuffer = charset.encode(data);

  

  //ByteBuffer -> 디코딩 -> CharBuffer -> 문자열

  data = charset.decode(byteBuffer).toString();

  System.out.println("문자열 복원: " + data);

 }

 

}


ByteBuffer < - > IntBuffer

 : int[] 배열을 생성하고 파일이나 네트워크로 출력을 하려면 int[] 배열이나 IntBuffer로부터

ByteBuffer 를 생성해야 합니다.

int 타입은 4Byte 크기를 가지기 때문에 int[] 배열 크기나 IntBuffer 의 capacity 보다 4배 큰 capacity를

가진 ByteBuffer 를 생성한 후 ByteBuffer의 putInt() 롤 정수 값을 하나씩 저장해주면 됩니다.


예 및 예제)

ex)

int[] data = new int[] {10, 20};

IntBuffer intBuffer = IntBuffer.wrap(data);

ByteBuffer byteBuffer = ByteBuffer.allocate(intBuffer.capacity() * 4);

for(int i =0; i< intBuffer.capacity(); i++){

   byteBuffer.putInt(intBuffer.get(i));

}

byteBuffer.flip();


반대로 하려면

ByteBuffer byteBuffer = ...;

IntBuffer intBuffer = IntBuffer.asIntBuffer();

int[] data = new int[intBuffer.capacity()];

intBuffer.get(data);

* ByteBuffer에서 asIntBuffer() 로 얻은 IntBuffer 에서는 array() 를 사용하여 int[]배열을 얻을 수 없음.

array()는 래핑한 배열만 리턴하므로 int[]배열을 wrap()으로 래핑한 IntBuffer에서만 사용 가능


예제)

import java.nio.ByteBuffer;

import java.nio.IntBuffer;

import java.util.Arrays;


public class Example {

 public static void main(String[] args) throws Exception {

  //int[] -> IntBuffer -> ByteBuffer

  int[] writeData = { 2017, 04, 16 };

  IntBuffer writeIntBuffer = IntBuffer.wrap(writeData);

  ByteBuffer writeByteBuffer= ByteBuffer.allocate(writeIntBuffer.capacity()*4);

  for(int i=0; i<writeIntBuffer.capacity(); i++) {

   writeByteBuffer.putInt(writeIntBuffer.get(i));

  }

  writeByteBuffer.flip();

  

  //ByteBuffer -> IntBuffer -> int[]

  ByteBuffer readByteBuffer = writeByteBuffer; 

  IntBuffer readIntBuffer = readByteBuffer.asIntBuffer();

  int[] readData = new int[readIntBuffer.capacity()];

  readIntBuffer.get(readData);

  System.out.println("[[배열 복원]]: " + Arrays.toString(readData));

 }

 


이상입니다.

반응형