[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개가 있기 때문에 수에 제약을 받지 않습니다. 




ChractorStream의 Write와 Read



[Stream Class ]

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

이번 시간에는 Character 스트림의 FileWriter, BufferdWrite, PrintWriter에 대해 공부해보자



**Chractor Stream 

=> 데이터를 문자 단위로 주고 받는 스트림 

=> 문자 단위로 주고 받을려면 인코딩 방식이 같아야 합니다.

1. 인코딩 방식 

=> 문자 데이터를 컴퓨터의 메모리에 저장하기 위해서 숫자로 변경하는 방식


1) ASCII Code 

=> 영문자와 숫자를 표현하기 위한방식으로 전세계 모든 곳에서 공통으로 사용

=> 영문자나 숫자 1개를 8bit 로표현 ( 시험에서는 7bit )

=> '0' -> 48 , 'A'-> 65, 'a'->97, NULL->0


2)EUC-KR(MS949, CP949)

=> Microsoft가 한글을 표현하는 방법 

=> Windows는 기본적으로 cp949 이고 IE(Internet Explorer) 예전버전이 사용 

=> 예전에 만들어진 웹 사이트의 인코딩이 이 방식입니다. 


3) UTF - 8 

=> microsoft를 제외한 운영체제에서의 한글 표현방법

=> IE를 제외한 모든 브라우저가 UTF-8 방식이

=> 최근에 만들어진 웹사이트의 인코딩방식은 거의 이방식입니다. 


문자기반 스트림은 단순히 2byte로 스트림처리하는 것만을 의미하지 않는다. 

더 중요한 것은 인코딩이다 자바에 Read와 Write는 자동으로 인코딩하여 저장한다.

그 예로 한글을 저장한 파일을 읽어서 출력을 해보면 

 byte스트림과 Charater의 차이는 확연해진다. 

byte 스트림의 FileInputStream을 사용하면 한글을 깨지지만, 

문자기반스트림인 FileReader는 한글이 깨져서 나오지 않는다 

즉, 인코딩해서 나오지 않기 때문에 파일이 깨져서 나오는 것이다.


**Writer -문자 단위로 기록하기 위한 메소드의 이름을 가진 추상클래스 


메소드 

void close() : 닫기 

void flush() : 버퍼에 있는 모든 내용을 출력 

void write(String str ) : 문자열 전체를 기록 

void write(String str, int off,int len) : 문자열에서 off 부터 len만큼 기록 



** FileWriter

FileWriter(File file) : File 객체로 만들기 

FileWriter(File file, boolean append) : File 객체와 추가모드를 설정해서 객체 만들기 

FileWriter(String filepath) : 파일경로를 가지고 만들기 

FileWriter(String filepath,boolean append) :파일 경로와 추가 모드를 설정해서 객체만들기 




**BufferedWriter -> PrintWriter -

BuffredWriter 보다 PrintWriter을 더 사용하길 추천합니다. 

BuffredWriter 는 Writer만 사용할 수 있지만 .

 PrintWriter 는 Writer 뿐만 아니라 기록하는 메소드로 print, printf, println이 추가되어 있습니다.

[생성자]

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

printWriter(File file): File 객체를 가지고 생성과

printWriter(OutPutStream out) : NetWork를 통해서 얻어온 OutPutStream객체를 가지고 만들 때 주로 사용 

printWriter(Writer out) : FileWriter와 같은 객체를 이용해서 생성



 [ PrintWriter 코드 ]


[결과]


Read



**Reader- 문자 단위로 데이터를 읽기 위한 메소드를 소유한 추상 클래스 


[메소드]

void close() : 닫기

int read() : 한 글자를 읽어서 리턴, 글자를 못읽으면 음수를 리턴 

int read(char[] cbuf) :  cbuf의 크기만큼 읽어서 cbuf에 저장하고 읽은 개수를 리턴하는데 못 읽으면 0보다 작거나 같은 수 리턴 

int read(char[] cbuf, int off, int len) : cbuf 배열에 off 부터 len만큼 읽어서 cbuf 에 저장하고 읽은 개수를 리턴하는데 못 읽으면 0보다 작거나 같은 수를리턴 



[File Reader] 

**File Reader 

[생성자]

FileReader(File file) : File 객체 가지고 만들기 

FileReader(FileDescriptor fd) : 파일의 경로를 문자열로 대입해서 만들기 




**BufferdReader

[생성자]

BufferedReader(Reader in) : Reader 객체를 가지고 만들기 

BufferedReader(Reader in, int sz) : Reader 객체와 버퍼의 크기를 설정해서만들기 

BufferdReader 생성자에는 Reader형태의 자료형이 들어가야합니다. 

그러나 Reader는 추상 클래스 이므로 Reader 아래에 있는  File Reader 생성해서 사용하면됩니다.

[메소드]

String readLine() : 줄 단위로 읽어서 리턴하는데 읽은게 없으면 null을 리턴 

[BufferdReader 코드]









split이용한 배열의 마지막 값을 가져오는 방법






String filepath = "C:\\Users\\402-08\\Desktop\\jp\\Penguins.jpg";


// \\을 기준으로 데이터를 나누어 ar에 데이터를 넣어준다 . 

String[] ar = filepath.split("\\\\");


//데이터의 길이를 length로 확인하여 -1을 해주면 마지막 데이터를 가져올 수 있다.


String file = ar[ar.length - 1];


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 JTableMake;


import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;


import javax.swing.JButton;

import javax.swing.JComboBox;

import javax.swing.JFrame;

import javax.swing.JLabel;

import javax.swing.JOptionPane;

import javax.swing.JPanel;

import javax.swing.JScrollPane;

import javax.swing.JTable;

import javax.swing.JTextField;

import javax.swing.table.DefaultTableModel;

import javax.swing.table.TableModel;


public class DataWindowTable extends JFrame {

private static final long serialVersionUID = 1L;


// 기본설정은 항상 생성자에서

public DataWindowTable() {


// 테이블에 출력할 데이터 만들기

// 컬럼이름

String[] columns = { "학생", "장래희망", "나이" };


// 데이터 만들기

String[][] datas = { { "김영진", "DJ", "27" }, { "김민호", "경호원", "28" }, { "김기남", "바텐터", "28" },

{ "모인재", "바리스타", "28" }


};


// 데이터를 테이블에 출력하기 위해서 TableModel로 변경


TableModel model = new DefaultTableModel(datas, columns);


// 위의 데이터를 가지고 테이블을 생성

JTable table = new JTable(model);


// Scrollpane을 생성해서 JTable을 배치하고 중앙에 배치

// 컬럼이 나오지 않는다 이걸 출력하기 위해서

JScrollPane sc = new JScrollPane(table);


add("Center", sc);


JPanel p = new JPanel();

JLabel l = new JLabel("이름");

p.add(l);


JTextField Field = new JTextField(5);


p.add(Field);


JLabel category = new JLabel("분야");

p.add(category);

JComboBox<String> cbdream = new JComboBox<String>();


cbdream.addItem("경호원");

cbdream.addItem("경찰");

cbdream.addItem("의사");

cbdream.addItem("비행사");

p.add(cbdream);


JLabel age = new JLabel("나이");

p.add(age);


JTextField ageput = new JTextField(3);

p.add(ageput);


JButton btn = new JButton("삽입");

p.add(btn);

JButton btn1 = new JButton("삭제");

p.add(btn1);

add("North", p);


setTitle("표만들기");

setBounds(700, 300, 500, 500);

setVisible(true);

setDefaultCloseOperation(EXIT_ON_CLOSE);


// 버튼을 눌렀을 때는 ActionEvent 발생


ActionListener listener = new ActionListener() {


@Override

public void actionPerformed(ActionEvent e) {


// 이벤트 라우팅


switch (e.getActionCommand()) {


case "삽입":

// 입력하거나 선택한 데이터 가져오기


String name = Field.getText();

String age1 = ageput.getText();

String category1 = cbdream.getSelectedItem().toString();

System.out.println(name);

System.out.println(age1);

System.out.println(category1);


// 오류 메세지

if (name.trim().length() < 1) {

JOptionPane.showMessageDialog(null, "이름은 필수 입력", "입력오류", JOptionPane.ERROR_MESSAGE);

// 중간에 빠져나가고 싶으면 리턴을하면됩니다.

return;

}

 

if (age1.trim().length() < 1) {

JOptionPane.showMessageDialog(null, "나이를입력 필수", "입력오류", JOptionPane.ERROR_MESSAGE);

// 중간에 빠져나가고 싶으면 리턴을하면됩니다.

return;

}

// age는 숫자로만 구성되어야합니다.

int i = 0;

while (i < age1.length()) {


char ch = age1.charAt(i);

if (ch < '0' || ch > '9') {

JOptionPane.showMessageDialog(null, "나이는 숫자로만 입력", "입력오류", JOptionPane.ERROR_MESSAGE);

return;

}


i = i + 1;

}


// 데이터 삽입작업

String[] row = { name, category1, age1 };


// 테이블의 모델을 꺼내기

// 형변환한 이유

// JTable의 Model은 DefaultTableModel 클래스 타입인데

// getModel로 리턴받게 되면 TableModel로 리턴되서

// 원래의 자료형으로 형변환해서 사용합니다.

// 테이블에 삽입이 아닌 테이블의 모델이 삽입한 것 

DefaultTableModel m = (DefaultTableModel) table.getModel();

m.addRow(row);

JOptionPane.showMessageDialog(null, "삽입에 성공", "데이터 삽입",JOptionPane.INFORMATION_MESSAGE);

Field.setText("");

age.setText("");

cbdream.setSelectedIndex(0);

break;

case "삭제":

int rownum = table.getSelectedRow();

//선택이 안된경우는 음수값

if(rownum<0) {

JOptionPane.showMessageDialog(null, "삭제할 행을 선택하세요", "데이터 삭제",JOptionPane.INFORMATION_MESSAGE);

return;

}

// Confirm 대화상자 출력 

int r =  JOptionPane.showConfirmDialog(null, "정말로삭제? ","데이터삭제",JOptionPane.YES_NO_CANCEL_OPTION);

if(r==0) {

DefaultTableModel m1 = (DefaultTableModel)table.getModel();

m1.removeRow(rownum);

JOptionPane.showMessageDialog(null, "삭제완료","삭제",JOptionPane.INFORMATION_MESSAGE);

}


break;

}


}


};

btn.addActionListener(listener);

btn1.addActionListener(listener);

}


}



+ Recent posts