[Close()]

=> Java 코드가 메모리에 생성한 것이 아닌 것과 

작성을 할 때는 사용이 끝나면 사용이 종료 되었다는 것을알려주어야합니다. 


=> 이때 사용되는 메소드 이름은 대부분 close, disconnect, release(자원에 대한 해제, 이거 다썼다 ) 


어떤 문제가 생기는가 ? 


이 이유로 인해서 대부분의 코드가 아래처럼 작성됩니다. 


자원을 사용하는 클래스에 변수를 만들고 null을 대입합니다. 

try를 만들어서 안에서 자원을 사용 

try안에서 클로즈를 할 수 없는 이유는 

클로즈를 하기전에 문제가 발생하면 클로즈를 못함 

그렇기에  finally를 만들어서 finally에서 자원을 해제 합니다. 



클래스 s =  null;


try{


}catch(Exception e ) {


System.out.println("예외" + e.getMessage());


}finally {


try {

if (ois != null) {

// 종료

s.close();

}

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

  }

}






**AutoCloseable 인터페이스 

- java 1.7 에서부터 사용됨 

=> 일정시간동안 사용하지 않으면, 자동으로 Close 해주는 메소드를 소유한 인터페이스

이 인터페이스가 implements 클래스는 close()하지 않아도 자동으로 연결해제 됩니다. 



[사용방법]


**try ~ with ~ Resourece

//괄호 안에서 생성한 객체는 예외가 발생하지 않으면 try 끝에서 close()를 호출하고 

//예외가 발생하면, 즉시 close()를 부릅니다. 

try(객체생성 ){

}

catch(    ) {  } 





버퍼가 출력되지 못한 상태에서 프로그램이 종료되버리면, 끝까지 데이터가 출력되지 못할 수 도 있다. 

그러므로 Close() 호출해주어서 버퍼에 남아있던 모든 내용이 출력되도록해주어야한다.

Stream에 대한 정의 



 **Stream ( 데이터를 주고 받기 위한 통로 )


외부 HW나 파일 또는 네트워크와 데이터를 주고받을 수 있는 통로 


[일반적으로 스트림을 쓰는 경우 ]


스트림

  Program              <======================>  File, Network (Soket), H/W ( keyboard, Monitor) 

  

  


  

  keyboard와 연결된 스트림은 System.int

  Monitor와 연결된 스트림은 System.out

  

  


  

[ 방향에 따른 분류 ]

  

1) Input Stream 

  

2) Output Stream  

  


[ 데이터에 따른 분류 ]

  

1) Byte Stream     : 일반적인 스트림 

  

2) Character Stream : 문자 단위로 해석 

  

  문자에는 Encoding이 있다 





  AComputer <-----------------> BComputer

   A컴퓨터와 B컴퓨터가 통신을 하고 싶다 . 

  

  OS  == OS      운영체제마다 Default가 있다. // 운영체제가 다르면 안된다 

      언어 ==언어     프로그래밍 언어어도 같아야한다 . 

운영체제와 언어가 다르면 Character를 안쓰고 ByteStream을써야한다.


[처리과정]


             //try안에 작성을 한다.

try{  

     1) 스트림 생성 

     2) 읽고 쓰기 

}

   //반드시 닫아하기 때문에 finally에 저장 

finally { 

      3) 스트림 닫기  ( 항상 닫아야합니다 ) 

}

프로그램이 종료되지 않는다면, 상관이 없는데 

종료가 안되면 문제가 생긴다. 

java.io의 close()를 해주지 않으면 어떤 문제가 생길까요 ? 



Data에 수정을 하기 위해 접근을 하면,  Lock에는  eXclusive와  Shared가 있습니다.

Lock에는 Write는 1개, Read는  n개가 있습니다.

수정을 할 때는 eXclusive가 있는지 확인해보고 eXclusive가 있으면 수정의 권한을 가지게됩니다. 

그러나 Close()를 해주지 않으면 eXclusive는 이미 다른 프로그램에 사용중이라서 

다른 프로그램은 Data에 수정으로 접근을 할수 없습니다. 

단, 읽기는 n개가 있기 때문에 수에 제약을 받지 않습니다. 




Stream을 이용한 파일복사 









파일이나 전송되어온 데이터가 많은 경우에는 부분적으로 읽어서 기록하는 것이 효율적입니다.


아래 방법은 데이터를 나누어 배열에 넣어 나누어서 출력하는 코드입니다. 



Stream의 BufferdOutputStream, BufferdInputStream






 [Stream Class ]

  

Stream 클래스는 크게 4가지로 나눈다 

이중 본 내용에서는 BufferdOutputStream, BufferdInputStream에 대해서 알아보도록 하자 

하지만 BufferdOutputStream은 printOutputStream을 것을 더 추천한다.


BufferdOutputStream은 read만 사용할 수 있지만 

printOutputStream은 read 뿐만 아니라, print 까지 사용할 수 있다. 




[ 알고 갑시다 ]

 ** OutPutStream - ByteStream들 중에서 출력에 관련되 메소드 이름을 소유한 추상클래스

  

  void close () : 스트림 닫기 

  void flush() : 현재 버퍼에 남아있는 내용 모두 출력 

  void write(int r)  : r을 기록 

  void write(byte[] b ) : b의 모든 내용을 기록 

  void write(byte [] b , int offset, int length) : b 배열에서 offset 부터 length만큼 기록 



** InPutStream - ByteStream들의 입력에 관련된 메소드 이름을 소유한 추상 클래스 


int available()  : 스트림에서 읽을 수 있는 크기를 바이트 단위로 리턴 

int read() : 하나의 바이트를 읽어서 정수로 리턴 못 읽으면 음수를 리턴 

int read(byte[] b ) : b배열의 크기만큼을 읽어서 b에 저장하고 읽은 바이트 수를 리턴 데이터를 못 읽으면 0보다 작거나 같은 수를 리턴 

int read(byte [] b , int offset, int length) : b배열에 offset 부터 length만큼을 읽어서 저장하고 읽은 개수를 리턴 데이터를 못 읽으면 0보다 작거나 같은 수를 리턴 







**BufferdOutputStream - > PrintStream 

2개의 스트림을 모아서 처리를 합니다. 

출력을 할 때 마다 운영체제의 native method를 호출하지 않고 모아서 호출하기 때문에 호출 횟수를 줄여서 출력을 효율적으로 할 수 있습니다.




**BufferdOutputStream - 한바이트씩 출력하지 않고 바이트배열(버퍼)를 이용해서 한번에 출력


[생성자]


BufferdOutputStream(OutputStream out) :OutputStream을 출력소스로하고, 크기를 지정하지 않음으로 8192byte크기의 버퍼를 갖게된다.


BufferdOutputStream(OutPutStream out, int size) : OutStream 인스턴스를 출력소르로하며 지정된 크기의 버퍼를 갖는BufferdOutputStream 인스턴스를 생성한다 . 


마지막 출력부분이 쓰이지 못하고 BufferedOutputStream의 버퍼에 남아 있는 채로 프로그램이 종료될수 있습니다.

그래서 flsush()나 Close()를 호출해서 마지막에 버퍼에 있는 모든 내용이 출력소스에 출력되도록해야합니다




**PrintStream


[생성자] 


PrintStream(String fileName) : 파일 경로를 가지고 생성

PrintStream(OutPutStream out ) : OutPutStream 객체를 가지고 생성 



[메소드]

print(), printf(), println() 메소드를 제공 등....





[코드]


void flush() : 현재 버퍼에 남아있는 내용 모두 출력 





[결과]







**BufferdInputStream - 한바이트씩 입력하지 않고 바이트배열(버퍼)를 이용해 한번에 입력



[생성자]


BufferedInputStream(InputStream in, int size) : InPutStream 인스턴스를 입력소스로하며 버퍼의 크기를 설정해서 객체를 생성

 

BufferedInputStream(InputStream in)  : InputStream 인스턴스를 입력소스로 하며 버퍼의 크기를 지정해주지 않으면 8192로 합니다.

단, InputStream은 추상 클래스여서 직접 넣을수가 없으므로 다른 InPutStream을 대입받아서 생성해야합니다.





[결과]












ByteStream에 대한 정의 및 메소드, 생성자 



 **Stream ( 데이터를 주고 받기 위한 통로 )


외부 HW나 파일 또는 네트워크와 데이터를 주고받을 수 있는 통로 


[일반적으로 스트림을 쓰는 경우 ]


스트림

  Program              <======================>  File, Network (Soket), H/W ( keyboard, Monitor) 

  

  


  

  keyboard와 연결된 스트림은 System.int

  Monitor와 연결된 스트림은 System.out

  

  


  

[ 방향에 따른 분류 ]

  

1) Input Stream 

  

2) Output Stream  

  


[ 데이터에 따른 분류 ]

  

1) Byte Stream     : 일반적인 스트림 

  

2) Character Stream : 문자 단위로 해석 

  

  문자에는 Encoding이 있다 






/** 공부한 내용 정리 가 필요함 **/

  AComputer <-----------------> BComputer

   통신을 하고 싶다 . 

  

  OS  == OS      운영체제마다 Default가 있다. // 운영체제가 다르면 안된다 

      언어 ==언어     프로그래밍 언어어도 같아야한다 . 

운영체제와 언어가 다르면 Character를 안쓰고 ByteStream을써야한다.


[처리과정]


             //try안에 작성을 한다.

try{  

     1) 스트림 생성

     2) 읽고 쓰기 

}

   //반드시 닫아하기 때문에 finally에 저장 

finally { 

      3) 스트림 닫기  ( 항상 닫아야합니다 ) 

}

프로그램이 종료되지 않는다면, 상관이 없는데 

종료가 안되면 문제가 생긴다. 

java.io의 close()를 해주지 않으면 어떤 문제가 생길까요 ? 







/** 공부한 내용 정리 가 필요함 **/



[문자열과 Byte전환]


1)문자열 - > byte[] 


getBytes() : 기본인코딩  기본인코딩 

getBytes("인코딩방식") : 인코딩방식으로


2)byte [] -> 문자열

new String(byte 배열);

new String(Byte 배열, "인코딩방식")




 [Stream Class ]

  

  Stream 클래스는 크게 4가지로 나눈다 







** OutPutStream - ByteStream들 중에서 출력에 관련되 메소드 이름을 소유한 추상클래스

  

  void close () : 스트림 닫기 

  void flush() : 현재 버퍼에 남아있는 내용 모두 출력 

  void write(int r)  : r을 기록 

  void write(byte[] b ) : b의 모든 내용을 기록 

  void write(byte [] b , int offset, int length) : b 배열에서 offset 부터 length만큼 기록 






생성자에 true를 넣어주면, 덮어쓰기가 아닌 이어서 쓴다.

 fos = new FileOutputStream("sample.txt",true);

반대로 생성자에 true를 쓰지 않으면 덮어쓰기 형식으로 작성됩니다.

fos = new FileOutputStream("sample.txt");




** InPutStream - ByteStream들의 입력에 관련된 메소드 이름을 소유한 추상 클래스 


int available()  : 스트림에서 읽을 수 있는 크기를 바이트 단위로 리턴 

int read() : 하나의 바이트를 읽어서 정수로 리턴 못 읽으면 음수를 리턴 

int read(byte[] b ) : b배열의 크기만큼을 읽어서 b에 저장하고 읽은 바이트 수를 리턴 데이터를 못 읽으면 0보다 작거나 같은 수를 리턴 

int read(byte [] b , int offset, int length) : b배열에 offset 부터 length만큼을 읽어서 저장하고 읽은 개수를 리턴 데이터를 못 읽으면 0보다 작거나 같은 수를 리턴 




** File OutPutStream - 파일에 byte 단위로 기록하기 위한 스트림 



[생성자]


FileNotFoundException을 처리해야 합니다.

FileOutputStream(File file) : 매개변수로 파일의 경로를 문자열로 주지않고 File 객체로 생성해서 대입합니다.

FileOutputStream(File file, boolean append) : 

FileOutputStream(String name)  : 파일 경로에 파일이 없으면 생성하고  파일이 존재하면 기존 파일의 시작부분부터 기록합니다.

FileOutputStream(String name, boolean append) 파일경로와 쓰기모드를 설정하는데 두번째 매개변수가  true 이면 파일이 있는 경우에 뒤에서 이어서 기록합니다.





**File IntputStream - 

[생성자]

FileIntputStream(File file) : File 객체를 대입

FileInputStream(String file) : 파일의 경로를 문자열로 대입


[sample.txt 파일 불러 오기 ]






[[text] 파일 한글을 입력한경우 or 한꺼번에 읽기 ]

위의 방법으로는 출력을 할 수가 없다. 


[코드]

 




그러나 위의 방식의 출력은 문제가 있습니다.


단점 : 파일의 크기가 크다면 읽는데 시간이 많이 걸립니다. 



[단점 보완 ]

이를 해결하기 위해서는 아래방식을 이용하면됩니다.


[코드]





단 위 방법을 사용할 때 나눠서 출력한다면 홀수로 배열을 주어서는 안됩니다 

잘못하면 오류가 날 수 있습니다. 

궁금하신 것은 직접출력해보시면 될 것 같습니다.


Tip

 [배열의 크기는 짝수인 패킷의 수로 정해주는 것이 좋습니다.]


 64 128 512 1024 





 


package IO;


import java.io.FileInputStream;

import java.io.FileOutputStream;


public class ByteMain {


public static void main(String[] args) { // TODO Auto-generated method stub

// 파일에 바이트 단위로 기록할 수 있는 스트림을 생성


// try {

// // true를 쓰면 이어붙이기가 됩니다.

// FileOutputStream fos = new FileOutputStream("test.txt", true);

//

// byte [] b ="Hello".getBytes();

//

// fos.write(b);

//

//

// //계속 예외처리하라고 하면 Exception으로 바꿔주기

// fos.close();

// } catch (Exception e) {

// // TODO Auto-generated catch block

// e.printStackTrace();

// }


// FileOutputStream fos = new FileOutputStream("test.txt", true);


FileOutputStream의 매개변수 자리에 true 를 사용하면 

test 파일 안에 문자가 리셋되는 것이 아니라 

계속 추가되어 문자가 쓰여진다.


/***************************************************************************************************/

// try {

//

// FileInputStream fis = new FileInputStream("test.txt");

// // 1개 읽기

// int r = fis.read();

// System.out.println(r);

// fis.close();

// } catch (Exception e) {

// System.out.println(e.getMessage());

// }



//텍스트 파일 생성 

/***************************************************************************************************/

try {


FileInputStream fis = new FileInputStream("test.txt");

byte[] b = new byte[fis.available()];

fis.read(b);


// String(byte[] bytes)

// Constructs a new String by decoding the specified array of bytes using the

// platform's default charset.


//new String 생성자를 생성해서 

// byte의 숫자를 문자로 형변환 해준다. 

//String 클래스의 생성자중 byte 배열을 Charset으로 변화해주는 생성자를 쓰면 쉽게 숫자를 문자로 바꾸어 

읽어 올 수 있다.  

System.out.println(new String(b));


// for(byte x : b ) {

// System.out.println(x);

// }

// System.out.println(b);

fis.close();

} catch (Exception e) {

System.out.println(e.getMessage());

}

}


}









+ Recent posts