데이터베이스 ?

- 논리적으로 연관된 하나 이상의 자료의 모음으로 그 내용을 고도로 구조함으로써 검색과 갱신의 효율화를 꾀한 것이다. 즉, 몇 개의 자료 파일을 조직적으로 통합하여 자료 항목의 중복을 없애고 자료를 구조화하여 기억시켜 놓은 자료의 집합체라고 할 수 있다.

- 어느 한 조직의 여러 응용 시스템들이 공유(shared)할 수 있도록 통합(integrated), 저장(stored)된 운영(operational)데이터의 집합이다.

 

특징

- 실시간 접근(real-time accessibility) : 질의에 대한 실시간 처리 및 응답을 처리할 수 있도록 지원해 준다.

- 계속적인 변화(continuous evolution) : 삽입, 삭제, 갱신을 통해서 현재의 정확한 데이터를 동적으로 유지할 수 있다.

- 동시 공유(concurrent sharing)가 가능하여 여러 사용자가 동시에 공용할 수 있다.

- 내용에 의한 참조(content reference) : 위치나 주소가 아닌 데이터의 내용, 즉 값에 따라 참조할 수 있다.

 

DBMS ( Database Management System)

- DBMS란 파일 관리 시스템의 단점을 개선하여 데이터를 통합적으로 관리하는 소프트웨어로 컴퓨터에 수록한 수많은 자료들을 쉽고 빠르게 추가, 수정, 삭제, 검색 등을 할 수 있다.

- 종류 : Oracle, MS-SQL, Sybase, MySQL, MariaDB, ... emd

 

SQL (Structured Query Language)

1) SQL이란 ?

- 구조화 질의어

- 관계형 데이터베이스 관리 시스템(RDBMS)의 데이터를 관리하기 위해 설계된 특수 목적의 언어

- 관계형 데이터베이스 관리 시스템에서 자료의 검색과 관리, 데이터베이스 스키마 생성과 수정, 데이터베이스 객체 접근 조정 관리를 위해 고안

- 비 절차 언어

2) 종류

- DQL (Data Query Language) 데이터 질의 언어

  - SELECT문

- DML (Data Manipulation Language) 데이터 조작 언어

  - INSERT, UPDATE, DELETE, MARGE 문 - ROLLBACK 가능

- DDL (Data Definition Language) 데이터 정의 언어

  - 객체의 생성, 변경, 삭제 등의 명령어

  - CREATE, ALTER, DROP, RENAME, COMMENT(주석 달기), TRUNCATE 문 등

  - 자동 COMMIT, ROLLBACK불가능

- DCL (Data Control Language) 데이터 제어 언어

  - GRANT(권한부여), REVOKE(권한회수) 문

  - 자동 COMMIT, ROLLBACK불가능

 

JDBC ?

- 자바에서 데이터베이스에 일관된 방식으로 접근할 수 있도록 제공하는 API(Application Program Interface)

 - 자바를 이용한 데이터베이스 접속

 - SQL 문장 실행

 - SQL 실행 결과 얻어진 데이터 가져오기

 - 데이터베이스의 정보 및 실행 결과의 정보 가져오기

- JDBC API 클래스와 인터페이스는 자바 패키지 java.sql과 javax.sql에 포함되어 있다.

 

특징

- JDBC는 ANSI SQL-92 표준을 지원

- JDBC는 공통된 SQL인터페이스를 바탕으로 만들어짐

 

 

직렬화(Serialization)

- 직렬화란 자바 시스템 내부에서 사용되는 객체 또는 데이터를 자바 외부에서도 사용할 수 있도록 바이트(byte)단위로 변환하는 것을 말한다.

- 직렬화가 가능한 자료형 및 객체

  기본형 타입 (boolean, char, byte, short, int, long, float, double)

  Serializable 인터페이스를 구현한 클래스의 객체

  transient가 사용된 멤버변수(null 전송), static 멤버변수, 메소드는 직렬화 대상에서 제외된다.

 

역 직렬화(Deserialization)

- 직렬화된 바이트(byte)단위의 데이터를 다시 원래 데이터로 복원하는 것을 말한다.

 

java.io.Serializable 인터페이스

- 객체를 직렬화하기 위해서는 먼저, 객체를 직렬화가 가능하도록 Serializable 인터페이스를 구현해야 한다.

- 이 인터페이스는 객체 직렬화가 제공되어야 함을 자바 가상 머신에 알려주는 역할을 한다.

- Serializable 인터페이스는 다른 인터페이스와는 달리 구현해야 할 메소드가 없으므로 단지 Serializable 인터페이스만 implements 하면 된다.

- 객체의 직렬화 대상에서 제외되는 것은 멤버 변수가 static으로 선언된 경우, 멤버 변수가 transient로 선언된 경우와 메소드이다.

 

형식

public class 클래스명 implements Serializable {

 // 클래스 정의 부분

}

 

transient

- 직렬화 대상에서 제외할 멤버 변수는 transient 키워드를 사용하여 제외한다.

- transient 키워드가 붙은 멤버 변수가 복원되면, 숫자변수는 0, 객체는 null로 설정된다.

public class 클래스명 implements Serializable {

 접근제어자 자료형 변수1;

 접근제어자 transient 자료형 변수2;

 // 클래스 구현

}

 

SerialVersionUID 필드

- serialVersionUID 는 직렬화에 사용되는 고유 아이디로, 선언하지 않으면 JVM에서 디폴트로 자동생성된다.

  serialVersionUID는 역 직렬화 해서 읽어 들일 때 캐스팅한 클래스의 serialVersionUID와 역직렬화 한 serialVersionUID가 맞는지 확인하기 위해 사용된다.

- 선언하지 않아도 동작하는데 문제는 없지만, JVM에 의한 디폴트 serialVersionUID 계산은 클래스의 세부 사항을 매우 민감하게 반영하기 때문에 컴파일러 구현체에 따라서 달라질 수 있어 역 직렬화(deserialization) 과정에서 예상하지 못한 InvalidClassException을 유발할 수 있다. 

- Java에서는 명시적으로 serialVersionUID를 선언할 것을 적극 권장하고 있다.

- 선언 예

private static final long serialVersionUID = 1L;

 

예시>>

더보기

Main

import java.io.EOFException;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class Ex004_transient {
	public static void main(String[] args) {
		UserService ov = new UserService();
		ov.saveFile();
		ov.loadFile();
	}
}

 

Class

// Serializable : 직렬화
// 직렬화에서 제외되는 것 : 메소드, static 변수, transient 변수

class UserDTO implements Serializable { // 바이트로 고쳐서 저장해줌
	private static final long serialVersionUID = 1L; // 같은 클래스인지아닌지 확인용도
	
	private String name;
	private transient String tel; // 직렬화에서 제외됨. 네트워트로 전송이 되지 않음.
	private int age;

	public UserDTO() {
		
	}
	
	public UserDTO(String name, String tel, int age) {
		this.name = name;
		this.tel = tel;
		this.age = age;
	}
	
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getTel() {
		return tel;
	}

	public void setTel(String tel) {
		this.tel = tel;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}
}

class UserService {
	private String pathname = "object2.txt";
	
	public void loadFile() {
		try( ObjectInputStream ois = new ObjectInputStream(new FileInputStream(pathname))) {
			
			System.out.println("파일 내용...");
			while(true) {
				UserDTO vo = (UserDTO) ois.readObject(); // 역직렬화수행
				System.out.println(vo.getName()+"\t"+vo.getTel()+"\t"+vo.getAge());
			}
			
		} catch (EOFException e) {
			// ObjectInputStream 스트림은 파일의 내용을 더 이상 읽을 수 없으면
			// EOFException 예외가 발생한다. 따라서 EOFException 예외를 catch하고
			// 아무런 코드도 작성하지 않는다. // 안잡으면 터짐
		}catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public void saveFile() {
		// ObjectOutputStream : Serializable 인터페이스가 구현되어 있어야 저장가능하다.
		try ( ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(pathname))){

			oos.writeObject(new UserDTO("다자바", "010-0000-0000", 20));
			oos.writeObject(new UserDTO("너자바", "010-1111-0000", 20));
			oos.writeObject(new UserDTO("구자바", "010-2222-0000", 20));
			
			System.out.println("파일 저장 완료...");
		} catch (IOException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

클래스를 파일로 저장하고 그 파일을 읽어들이는 프로그램을 작성

 

소스 보기 >>

더보기

Main

import java.io.EOFException;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class Ex003_ObjectStream {
	public static void main(String[] args) {
		User ov = new User();
		ov.saveFile();
		ov.loadFile();
	}
}

Class

// Serializable : 직렬화
// 직렬화에서 제외되는 것 : 메소드, static 변수, transient 변수

class UserVO implements Serializable { // 바이트로 고쳐서 저장해줌
	private static final long serialVersionUID = 1L; // 같은 클래스인지아닌지 확인용도
	
	private String name;
	private String tel;
	private int age;

	public UserVO() {
		
	}
	
	public UserVO(String name, String tel, int age) {
		this.name = name;
		this.tel = tel;
		this.age = age;
	}
	
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getTel() {
		return tel;
	}

	public void setTel(String tel) {
		this.tel = tel;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}
}

class User {
	private String pathname = "object.txt";
	
	public void loadFile() {
		try( ObjectInputStream ois = new ObjectInputStream(new FileInputStream(pathname))) {
			
			System.out.println("파일 내용...");
			while(true) {
				UserVO vo = (UserVO) ois.readObject(); // 역직렬화수행
				System.out.println(vo.getName()+"\t"+vo.getTel()+"\t"+vo.getAge());
			}
			
		} catch (EOFException e) {
			// ObjectInputStream 스트림은 파일의 내용을 더 이상 읽을 수 없으면
			// EOFException 예외가 발생한다. 따라서 EOFException 예외를 catch하고
			// 아무런 코드도 작성하지 않는다. // 안잡으면 터짐
		}catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public void saveFile() {
		// ObjectOutputStream : Serializable 인터페이스가 구현되어 있어야 저장가능하다.
		try ( ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(pathname))){
			UserVO vo = new UserVO("거자바", "010-1010-0000", 19);
			oos.writeObject(vo); // 주소 저장함. 직렬화해서 저장
			
			oos.writeObject(new UserVO("다자바", "010-0000-0000", 20));
			oos.writeObject(new UserVO("너자바", "010-1111-0000", 20));
			oos.writeObject(new UserVO("구자바", "010-2222-0000", 20));
			
			System.out.println("파일 저장 완료...");
		} catch (IOException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

클래스 UserVO를 Object 바이트 스트림으로 보내고 다시 Object 바이트 스트림으로 받았기 때문에. loadFile() 할때는 (UserVO)로 형변환을 해주어야 한다.  

 

 

 

 

 

 

java.io.ObjectOutputStream

- ObjectOutputStream 클래스는 객체들을 출력하는 기능을 제공하는 클래스로 출력 스트림에 출력하기 전에 직렬화를 수행한다.

- 파일이나 네트워크로 데이터를 전송하기 위해 직렬화를 수행하며, 이때 writeObject() 메소드를 사용하여 변환한다.

- 스트림에 저장할 수 있는 객체는 Serializable 인터페이스를 구현한 클래스의 객체만 가능하다.

import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.util.Hashtable;

public class Ex001_ObjectOutputStream {

	public static void main(String[] args) {
		Hashtable<String, String> ht = new Hashtable<String, String>();
		
		ht.put("자바", "프로그래밍");
		ht.put("HTML", "웹 프로그래밍");
		ht.put("오라클", "데이터베이스");
		
		String pathname = "object.txt";
		ObjectOutputStream oos = null;
		
		try {
			// ObjectOutputStream : 객체를 저장 할 수 있는 스트림
			// 객체를 저장하면 파일 선두에는 객체의 클래스명이 저장된다.
			oos = new ObjectOutputStream(new FileOutputStream(pathname));
			oos.writeObject(ht);
			System.out.println("파일 저장 완료...");
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if(oos !=null ) {
				try {
					oos.close();
				} catch (Exception e2) {
				}
			}
		}
		
	}

}

 

위 코드를 실행하면 object.txt 파일이 저장되고 안에는 이렇게 되어있다.


java.io.ObjectInputStream

- ObjectOutputStream 클래스에 의해 파일에 저장되거나 네트워크를 통해 전달된 객체의 직렬화를 해제하는 기능을 제공한다.

- 파일이나 네트워크를 통해 받은 직렬화된 데이터를 다시 원래 데이터로 복원하는 역할을 하며, 이때 readObject() 메소드를 사용하여 복원한다.

- readObject() 메소드를 통해 읽어 들인 데이터는 원래 데이터로 캐스팅하여 사용한다.

- 스트림으로부터 읽어들일 수 있는 객체는 Serializable 인터페이스나 Externalizable 인터페이스를 구현한 클래스의 객체만 가능하다.

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.Hashtable;
import java.util.Iterator;

public class Ex002_ObjectInputStream {

	public static void main(String[] args) {
		String pathname = "object.txt";
		
		try ( ObjectInputStream ois = new ObjectInputStream(new FileInputStream(pathname))){
			// 제너릭은 다운 캐스팅하면 경고가 나옴.
			@SuppressWarnings("unchecked") // 경고없앰
			Hashtable<String, String> ht = (Hashtable<String, String>)ois.readObject();
			
			Iterator<String> it = ht.keySet().iterator();
			while(it.hasNext()) {
				String key = it.next();
				String value = ht.get(key);
				System.out.println(key+" -> "+value);
			}
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

}

위에서 만든 object.txt파일을 읽어들인 결과

Hashtable 은 Map의 구현 클래스로 동기화를 지원한다.

Map은 <키, 값>의 구조로 키는 중복을 허용하지 않는다. 키는 순서가 없으므로 반복자도 존재하지 않는다.

만들 예제의 실행모습 

종료 후 재실행시 출력을 누르면 전에 입력받았던 값들을 출력하는 프로그램

 

소스 보기 >>

더보기

Main

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class Ex017_DataStream {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		Test t = new Test();
		int ch;
		
		try {
			while(true) {
				do {
					System.out.print("1.입력 2.출력 3.종료 => ");
					ch = sc.nextInt();
				}  while(ch<1 || ch> 3);
				
				if (ch ==3) {
					t.saveFile();
					return;
				}
				
				switch(ch) {
				case 1 : t.add(); break;
				case 2 : t.printAll(); break;
				
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			sc.close();
		}
		

	}

}

Class

class TestVO {
	private String name;
	private String tel;
	private int age;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getTel() {
		return tel;
	}

	public void setTel(String tel) {
		this.tel = tel;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

}

class Test {
	private String pathname = "address.txt";
	private List<TestVO> list = new ArrayList<>();
	private BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
	
	public Test() {
		loadFile();
	}
	
	private void loadFile() {
		File f = new File(pathname);
		if( ! f.exists()) {
			return;
		}
		
		// 파일이 존재하면 파일의 내용을 읽어ㅣlist에 저장
		DataInputStream dis = null;
		try {
			dis = new DataInputStream(new FileInputStream(f));
			
			String name, tel;
			int age;
			while(true) {
				name = dis.readUTF();
				tel = dis.readUTF();
				age = dis.readInt();
				
				TestVO vo = new TestVO();
				vo.setName(name);
				vo.setTel(tel);
				vo.setAge(age);
				list.add(vo);
			}
		} catch (EOFException e) {
			// DataInputStream은 더 이상 읽을 데이터가 없으면 EOFException예외가 발생한다.
			// 따라서 이곳에서는 코드를 작성할 필요없이 예외만 catch한다.
		} catch (IOException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (dis != null) {
				try {
					dis.close();
				} catch (Exception e2) {					
				}
			}
		}
	}
	
	public void saveFile() {
		try(DataOutputStream dos = new DataOutputStream(new FileOutputStream(pathname))) {
			for(TestVO vo : list) {
				dos.writeUTF(vo.getName());
				dos.writeUTF(vo.getTel());
				dos.writeInt(vo.getAge());
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public void add() {
		System.out.println("\n데이터 등록");
	
		try {
			TestVO vo = new TestVO();
			
			System.out.print("이름 ? ");
			vo.setName(br.readLine());
			
			System.out.print("전화번호 ? ");
			vo.setTel(br.readLine());
			
			System.out.print("나이 ? ");
			vo.setAge(Integer.parseInt(br.readLine()));
			
			list.add(vo);
			
			System.out.println("등록 완료...\n");
		} catch (NumberFormatException e) {
			System.out.println("나이는 숫자만 가능합니다.");
		} catch (IOException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public void printAll() {
		System.out.println("\n데이터 출력");
		for(TestVO vo : list) {
			System.out.print(vo.getName()+"\t");
			System.out.print(vo.getTel()+"\t");
			System.out.println(vo.getAge());
		}
		System.out.println();
	}
}

Test의 생성자에 loadFile() 을 넣어 종료 후 다시 실행했을 때는 파일을 불러오도록 한다.

 

loadFile() 메소드에서는 파일의 pathname 으로 된 파일의 객체를 생성해준다. 그 파일이 없으면 exists() 메소드에서 false를 return해주므로 읽을 파일이 존재하지 않다는 것을 의미하므로 밖으로 나간다. 

 

pathname 의 파일이 있으면 그 파일을 읽어서 list에 저장해주어야 출력할 수 있으므로 리스트에 넣는 작업을 해준다.

EOFException을 잡지 않으면, 첫 실행시 생성자에서 loadFile() 메소드를 실행해 파일이 없으면 나가고 파일이 있으면 읽고 리스트에 넣는 작업을 하고 더 이상 넣을 데이터가 없으면 EOFException이 발생한다.

실행 시 EOFException 발생한 것을 볼 수 있다.

따라서 코드 작성 필요없이 예외만 catch한다.

 

saveFile() 을 통해 종료를 누르면 입력했던 데이터들을 파일에 저장한다.

FileOutputStream 은 파일이 없으면 생성하고 있으면 내용을 덮어씀으로 로드시 List에 넣어놨던 것들을 차례대로 저장시 넣어주어야 자료가 손실되지 않는다.

address.txt 안에 데이터가 저장된다. 인코딩이 UTF 로 되서 한글문자는 확인이 불가하다.

 

 

java.io.DataInputStream 클래스

- 기본 Java 데이터 유형을 플랫폼에 독립적인 방법으로 기본 입력 스트림에서 읽을 수 있다.

- 필터 스트림이기 때문에 다른 입력 스트림을 생성자의 인자로 받아 객체를 생성한다.

- InputStream, FilterInputStream의 하위 클래스

import java.io.DataInputStream;
import java.io.FileInputStream;

public class Ex016_DataInputStream {

	public static void main(String[] args) {
		
		// DataOutputStream으로 저장한 내용은 DataInputStream으로 읽어야 한다.
		// 저장한 자료형 순서대로 읽어 들인다.
		// 더 이상 읽을 데이터가 없으면 IOException이 발생된다.
		try(DataInputStream dis = new DataInputStream(new FileInputStream("text.txt"))) {
			System.out.println(dis.readUTF());
			System.out.println(dis.readByte());
			System.out.println(dis.readChar());
			System.out.println(dis.readInt());
			System.out.println(dis.readInt());
			System.out.println(dis.readUTF());
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

}


java.io.DataOutputStream 클래스

- 기본 Java 데이터 유형을 출력하는 기능을 가진 클래스로 필터 스트림이기 때문에 다른 출력 스트림을 생성자의 인자로 받아 생성한다.

- OutputStream, FilterOutputStream의 하위 클래스

 

import java.io.DataOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class Ex015_DataOutputStream {

	public static void main(String[] args) {
		try(DataOutputStream dos = new DataOutputStream(new FileOutputStream("text.txt"))) {
			dos.writeUTF("서울");
			dos.writeByte(10);
			dos.writeChar('A');
			dos.writeInt(50);
			dos.writeInt(70);
			dos.writeUTF("서울");
			
			System.out.println("파일 저장 완료...");
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}


필터 스트림 ?

- 필터 스트림은 기존의 스트림을 원하는 기능을 제공하는 새로운 스트림으로 바꾸어 주는 스트림이다.

- 필터 스트림의 최상위 클래스에는 FilterInputStream과 FilterOutputStream클래스가 있다.

 

FilterInputStream과 FilterOutputStream 클래스

- 이 클래스를 인스턴스 한 객체는 매개변수로 입력 받은 다른 스트림과 연결되어있다.

- 실제 데이터 소스에서 스트림을 처리하는 것이 아니라 다른 스트림과 연결하는 용도로 사용된다.

따라서 입/출력 스트림에서 받은 데이터를 다른 데이터로 변환하거나 추가 작업을 하는 클래스이다.

java.io.BufferedReader 클래스

- 문자, 배열 및 행을 효율적으로 읽을 수 있도록 문자를 버퍼링하여 문자 입력 스트림에서 텍스트를 읽어들인다.

- 버퍼 크기를 지정하거나 기본 크기(8192byte)를 사용한다.

- Reader 하위 클래스

 

java.io.BufferedWriter 클래스

- 다른 출력 스트림을 생성자의 인자로 받아 생성하며 버퍼링 하는 것에 따라 문자, 배열 또는 스트링을 문자 형태로 출력 스트림에 출력한다.

- Writer 하위 클래스

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.InputStreamReader;

// BufferedWriter : 문자를 버퍼링하여 문자 출력 스트림에 저장
public class Ex014_BufferedWriter {

	public static void main(String[] args) {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		String s;
		
		try ( BufferedWriter bw = new BufferedWriter(new FileWriter("test.txt"))){
			System.out.println("문자열 입력[종료:ctrl+z]....");
			while( (s = br.readLine()) != null) {
				bw.write(s);
				bw.newLine(); // 이거 있어야 Line이 넘어감
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}

 - user.txt 파일을 읽어서 합격자만 pass.txt에 저장하는 프로그램 작성
 - user.txt 파일 형식
   이름,국,영,수
 - pass.txt 파일 형식
   이름,국,영,수
 - 세과목 모두 40점 이상이고 평균이 60점 이상인 경우만 합격자
 - pass.txt에 저장할 때는 총점 내림차순으로 저장(단, 이것은 못하겠으면 안해도 됨)
 - UserDTO 만들고, UserPass 라는 클래스를 만들어서 작성할 것
 - ArrayList 사용하면 쉽다. (Map 사용 안함)
 - 작성할 수 있는데 까지 작성해서 메일로 보내기

 

Main

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Iterator;

public class Ex012_PassUser {
	public static void main(String[] args) {
		UserPass vo = new UserPass();
		
		vo.loadfile();
		vo.savefile();
		System.out.println("파일 생성 완료...");
		
	}
}

Class

class UserDTO {
	private String name;
	private Integer kor;
	private Integer eng;
	private Integer mat;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Integer getKor() {
		return kor;
	}

	public void setKor(Integer kor) {
		this.kor = kor;
	}

	public Integer getEng() {
		return eng;
	}

	public void setEng(Integer eng) {
		this.eng = eng;
	}

	public Integer getMat() {
		return mat;
	}

	public void setMat(Integer mat) {
		this.mat = mat;
	}

}

class UserPass {
	private ArrayList<UserDTO> list = new ArrayList<>();
	private String pathname1 = "user.txt";
	private String pathname2 = "pass.txt";

	
	public void loadfile() {
		try(BufferedReader br = new BufferedReader(new FileReader(pathname1))) {
			String s;
			while ( (s = br.readLine()) != null ) {
				String [] ss = s.split(",");
				
				if(ss.length < 2) {
					continue;
				}
				UserDTO vo = new UserDTO();
				vo.setName(ss[0]);
				
				int kor, eng, mat, tot;
				long ave;
				kor = Integer.parseInt(ss[1]);
				eng = Integer.parseInt(ss[2]);
				mat = Integer.parseInt(ss[3]);
				
				tot = kor+eng+mat;
				ave = tot / 3 ;
				if ( ave >=60 && (kor>=40 && eng>=40 && mat >=40)) {
					vo.setKor(kor);
					vo.setEng(eng);
					vo.setMat(mat);
					
					list.add(vo);
					
				} else {
					continue;
				}
				
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public void savefile() {
		try(PrintStream ps = new PrintStream(pathname2)) {
			Iterator<UserDTO> it = list.iterator();
			
			while(it.hasNext()) {
				UserDTO vo = it.next();
				ps.println(vo.getName()+"\t"+vo.getKor()+"\t"
							+vo.getEng()+"\t"+vo.getMat());
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

총점 내림차순은

 

혼자서 해보다가 못했음.

내가 하려고 했던 방법은,

1) int[] 를 만들어서 총점을 담는다.

2) list.add 할 때 만 총점 배열에 총점을 넣음. 그래야 출력(합격자)할 자료들만 모아지니까

3) list.add 가 끝나면 그 배열을 선택정렬을 통해 정렬할때 리스트도 list.set() 으로 바꿈.

 

너무 길어져서 >>

더보기
int [] total = new int[] {list.size()};
int count = 0;

total[count++] = tot;

UserDTO vo2;
int c;

for (int i = 0; i<list.size() -1 ; i++){
	for(int j = i+1; i<list.size() ; j++){
		if(total[i] < total[j]){
        	c = total[i];
            total[i] = total[j];
            total[j] = c;
            
        	vo2 = list.get(i);
            list.set(i, list.get(j));
            list.set(j, vo2);
        }
    }
}

 

원래 합격자들만 출력한 결과는

이것인데 총점 내림차순은 못했음.

public void loadfile() {
		int [] total = new int[] {list.size()};
		try(BufferedReader br = new BufferedReader(new FileReader(pathname1))) {
			String s;
			while ( (s = br.readLine()) != null ) {
				String [] ss = s.split(",");
				
				if(ss.length < 2) {
					continue;
				}
				UserDTO vo = new UserDTO();
				vo.setName(ss[0]);
				
				int kor, eng, mat, tot;
				long ave;
				kor = Integer.parseInt(ss[1]);
				eng = Integer.parseInt(ss[2]);
				mat = Integer.parseInt(ss[3]);
				
				tot = kor+eng+mat;
				ave = tot / 3 ;
				if ( ave >=60 && (kor>=40 && eng>=40 && mat >=40)) {
					vo.setKor(kor);
					vo.setEng(eng);
					vo.setMat(mat);
					
					list.add(vo);
					
					int count = 0;
					
					total[count++] = tot;
					
					
				} else {
					continue;
				}
				
				UserDTO vo2;
				int c;

				for (int i = 0; i<total.length-1 ; i++){
					for(int j = i+1; i<total.length ; j++){
						if(total[i] < total[j]){
							c = total[i];
							total[i] = total[j];
							total[j] = c;
							
							vo2 = list.get(i);
							list.set(i, list.get(j));
							list.set(j, vo2);
						}
					}
				}
				
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

이렇게 하니까 안터지긴 하는데 결과가 정렬부분 있든 없든 똑같음...

 

그럼

아예 UserDTO 에 총점입력하는 칸을 넣어서 하는 것이 어떨까? 

public class Ex012_PassUser {
	public static void main(String[] args) {
		UserPass vo = new UserPass();

		vo.loadfile();
		vo.sort();
		vo.savefile();
		System.out.println("파일 생성 완료...");

	}
}

class UserDTO {
	private String name;
	private Integer kor;
	private Integer eng;
	private Integer mat;
	private Integer tot;

	public Integer getTot() {
		return tot;
	}

	public void setTot(Integer tot) {
		this.tot = tot;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Integer getKor() {
		return kor;
	}

	public void setKor(Integer kor) {
		this.kor = kor;
	}

	public Integer getEng() {
		return eng;
	}

	public void setEng(Integer eng) {
		this.eng = eng;
	}

	public Integer getMat() {
		return mat;
	}

	public void setMat(Integer mat) {
		this.mat = mat;
	}

}

class UserPass {
	private ArrayList<UserDTO> list = new ArrayList<>();
	private String pathname1 = "user.txt";
	private String pathname2 = "pass.txt";

	public void loadfile() {
		try (BufferedReader br = new BufferedReader(new FileReader(pathname1))) {
			String s;
			while ((s = br.readLine()) != null) {
				String[] ss = s.split(",");

				if (ss.length < 2) {
					continue;
				}
				UserDTO vo = new UserDTO();
				vo.setName(ss[0]);

				int kor, eng, mat, tot;
				long ave;
				kor = Integer.parseInt(ss[1]);
				eng = Integer.parseInt(ss[2]);
				mat = Integer.parseInt(ss[3]);

				tot = kor + eng + mat;
				ave = tot / 3;
				if (ave >= 60 && (kor >= 40 && eng >= 40 && mat >= 40)) {
					vo.setKor(kor);
					vo.setEng(eng);
					vo.setMat(mat);
					vo.setTot(tot);

					list.add(vo);

				} else {
					continue;
				}

			}
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	public void savefile() {
		try (PrintStream ps = new PrintStream(pathname2)) {
			Iterator<UserDTO> it = list.iterator();

			while (it.hasNext()) {
				UserDTO vo = it.next();
				ps.println(vo.getName() + "\t" + vo.getKor() 
						+ "\t" + vo.getEng() + "\t" + vo.getMat());
			}

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void sort() {
		UserDTO vo2;
		for (int i = 0; i < list.size() - 1; i++) {
			for (int j = i + 1; j < list.size(); j++) {
				if(list.get(i).getTot() < list.get(j).getTot()) {
					vo2 = list.get(i);
					list.set(i, list.get(j));
					list.set(j, vo2);
				}
			}
		}
	}
}

 예!! 이렇게 정렬하는 것을 따로 메소드로 만들어서 거기서 총점을 가지고 바꾸는 것을 해보았다.

예! 총점은 확인용으로 출력해보았다.

 

앗싸 - 이게 맞는지는 내일 수업을 듣고 업데이트 하겠다.

 

총점 내림 차순 추가

Main

public class Ex012_PassUser {
	public static void main(String[] args) {
		UserPass vo = new UserPass();

		vo.loadfile();
		vo.sort();
		vo.savefile();
		System.out.println("파일 생성 완료...");

	}
}

Class

class UserDTO {
	private String name;
	private Integer kor;
	private Integer eng;
	private Integer mat;
	private Integer tot;

	public Integer getTot() {
		return tot;
	}

	public void setTot(Integer tot) {
		this.tot = tot;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Integer getKor() {
		return kor;
	}

	public void setKor(Integer kor) {
		this.kor = kor;
	}

	public Integer getEng() {
		return eng;
	}

	public void setEng(Integer eng) {
		this.eng = eng;
	}

	public Integer getMat() {
		return mat;
	}

	public void setMat(Integer mat) {
		this.mat = mat;
	}

}

class UserPass {
	private ArrayList<UserDTO> list = new ArrayList<>();
	private String pathname1 = "user.txt";
	private String pathname2 = "pass.txt";

	public void loadfile() {
		try (BufferedReader br = new BufferedReader(new FileReader(pathname1))) {
			String s;
			while ((s = br.readLine()) != null) {
				String[] ss = s.split(",");

				if (ss.length < 2) {
					continue;
				}
				UserDTO vo = new UserDTO();
				vo.setName(ss[0]);

				int kor, eng, mat, tot;
				double ave;
				kor = Integer.parseInt(ss[1]);
				eng = Integer.parseInt(ss[2]);
				mat = Integer.parseInt(ss[3]);

				tot = kor + eng + mat;
				ave = tot / 3;
				if (ave >= 60 && (kor >= 40 && eng >= 40 && mat >= 40)) {
					vo.setKor(kor);
					vo.setEng(eng);
					vo.setMat(mat);
					vo.setTot(tot);

					list.add(vo);

				} else {
					continue;
				}

			}
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	public void savefile() {
		try (PrintStream ps = new PrintStream(pathname2)) {
			Iterator<UserDTO> it = list.iterator();

			while (it.hasNext()) {
				UserDTO vo = it.next();
				ps.println(vo.getName() + "\t" + vo.getKor() 
						+ "\t" + vo.getEng() + "\t" + vo.getMat());
			}

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void sort() {
		UserDTO vo2;
		for (int i = 0; i < list.size() - 1; i++) {
			for (int j = i + 1; j < list.size(); j++) {
				if(list.get(i).getTot() < list.get(j).getTot()) {
					vo2 = list.get(i);
					list.set(i, list.get(j));
					list.set(j, vo2);
				}
			}
		}
	}
}

user.txt
pass.txt

 

+ Recent posts