반응형

quickSort

package algorithm;

public class URLRouting {
	public static void main(String[] args) {
		String requestURI = "https://localhost:9000/webproject/request.jsp";
		String contextPath = "https://localhost:9000/webproject";
		
		String command = requestURI.substring(contextPath.length()) ;
		System.out.println(command);
	}
}
​

 

SelectionSort

package algorithm;

public class QuickSort {
	
	private static void quickSort(int left, int right, int[] data) {
		//정렬 결과 출력
		for(int temp: data) {
			System.out.print(temp+"\t");
		}
		System.out.println();
		
		//가장 왼쪽의 데이터를 pivot으로 설정
		int pivot = left;
		//피봇의 취치를 .j에 대입
		int j = pivot;
		//피복솨 비교할 데이터의 위치의 초기값을 설정
		int i = left+1;
		if(left < right) {
			for(; i <= right; i= i+1) {
				if(data[i] < data[pivot]) {
					j= j+1;
					int temp = data[j];
					data[j] = data[i];
					data[i] = temp;
				}
			}
			int temp = data[left];
			data[left] = data[j];
			data[j] = temp;
			//1 
			pivot = j;
			quickSort(left, pivot -1, data);
			//2
			quickSort(pivot +1, right, data);
		}
	}
	
	
	public static void main(String[] args) {
		int[] list = {5,3,8,4,9,1,6,2,7};
		int n = list.length;
		//퀵 정렬 수행(left: 배열의 시작 = 0 ,right: 배열의 끝 = 8)
		quickSort(0, n-1, list);
		//정렬 결과 출력
		for(int temp: list) {
			System.out.print(temp+"\t");
		}
		System.out.println();
	}

}

 

URLRouting

package algorithm;

public class SelectionSort {
	public static void main(String[] args) {
		int [] ar = {20,30,10,50,40};
		for(int i = 0; i< ar.length ; i = i+1) {
			for(int j = i+1; j < ar.length; j= j+1) {
				if(ar[i] > ar[j]) {
					int temp = ar[i];
					ar[i] = ar[j];
					ar[j] = temp;
				}
			}
		}
		
		for(int item:ar) {
			System.out.print(item+"\t");
		}
	}
}

 

반응형

'Study > Java' 카테고리의 다른 글

java-20  (0) 2020.10.10
java-19  (0) 2020.10.10
java-18  (0) 2020.10.10
java-17  (0) 2020.10.10
java-16  (0) 2020.10.10
반응형

 

 

 

Ops -> AWS(유료). Docker

 

 

Java

.Net(VC#, VC++, VB )

실행 환경을 구성해야 실행된다.

 

MS – Windows용 실행 파일 만들기

×         소스를 작성한 것은 IDE 안에서만 실행된다.

×         PC용 애플리케이션을 만들어서 IDE가 없어도 실행이 되도록 하기 위해서 생성

1.     Jsmooth 프로그램 설치: https://sourceforge.net/projects/jsmooth/files/ 에서 다운로드

2.     Jsmooth가 바로 안되고 자바를 다운로드 받아야 한다는 메시지가 출력되는 경우

A.     Jdk jre가 설치되어 있지 않으면 설치

B.     JAVA_HOME이라는 환경변수를 만들어서 jdkjre 경로를 설정해주면 된다.

C.     Mac이나 Linux를 처음 공부하면 vi 에디터를 이용해서 환경변수 설정하는 방법을 알아 두어야 한다.

                       i.        Vimvi의 발전된 editor

D.     [탐색기] 실행 -> PC 선택하고 마우스 오른쪽을 눌러서 [속성] 클릭 -> 왼쪽 화면에서 [고급 시스템 설정]을 클릭 -> [고급] 탭에서 [환경변수]를 클릭 -> [새로 만들기] 클릭

E.     변수이름은 JAVA_HOME

F.      변수 값은 jdkjre가 설치된 디렉토리(C:\Program Files\Java\jdk1.8.0_231)

3.     .exe로 만들 프로젝트를 jar(java archive의 약자 자바 압축) 파일로 export

A.     프로젝트를 선택하고 마우스 오른쪽을 클릭해서 [export] 선택

B.     Java 탭에서 Runnable jar file을 선택하고 실행할 클래스(main 메소드 소유)를 선택하고 저장할 위치와 이름을 설정하면 된다.

4.     Jsmooth를 실행

A.     Skeleton 아이콘을 클릭해서 프로그램 종류를 설정

                       i.        gui가 아닌 경우는 console wrapper을 선택하고 gui인 경우는 windowed wrapper를 선택

B.     executable 아이콘을 클릭해서 실행 파일 이름과 아이콘을 설정

C.     application 아이콘을 클릭하고 실행 파일을 만들 jar 파일을 선택하고 실행할 클래스를 선택

                       i.        실행파일을 만들 jar 파일 선택: CLASS PATH에서 + 아이콘을 눌러서 선택

D.     톱니바퀴 아이콘 이나 [Project] – [Compile]을 클릭해서 프로젝트 이름을 설정하고 실행 파일 생성

 

 

public class Java

{

 

           public static void main(String[] args) {

                       System.out.println("JAVA EXE만들기");

                       //실행 파일을 만들었을 때 콘솔화면을 유지하기 위해서 입력받는 문장을 추가한다.

                       Scanner sc = new Scanner(System.in);

                       System.out.print("아무거나 누르면 종료합니다.");

                       sc.nextLine();

                       sc.close();

           }

}

 

 

 

jframe

 

 

 

 

 

 

 

 

 

 

 

jQuery: Cross Browing(어디에서도 다 할 수 있는 것)

BootStrap : 반응법 웹

Bue, reac, angular: mvc 구현 만드는 회사가 뷰 , facebook , google

Node.js : 서버

 

 

예전에는 media player하는데 요즘에는 필요 없다. html5로 한다.

공인 자격증 일본과 한국만 있다. 국가에서 하는 것

미국은 주립대학

vicadic ->it 취업비자가 나온다.

이것 없으면 정보처리기사 등 따야 한다.

프레임워크는 유행이 있고 해서 하면 안된다.

 

iphone swift

 

web server was -> 배포 서버 서버용 언어 ->html

 

**Web Programming준비

1.코딩을 할 수 있는 IDE 또는 Editor -> Eclipse

2. 출력되는 결과를 확인하기 위한 Web Borwser

=> THML5를 확인하기 위해서는 IE보다는 Chrome

Chrome보다는 FirefoxOpera(html5)브라우저가 조금 더 잘 지원  

 

3. 2번까지만 있으면 html을 만들어서 결과 확인은 가능

 

4.만들어진 결과를 배포한고자 하면 Web Server가 있어야 합니다.

 

5.Back End언어로 만들어진 내용을 브라우저를 이용해서 확인하고자 하는 경우에는 WAS(Web Application Server - Web Container)가 있어야 합니다.

WAS는 웹 서버의 요청을 받아서 Back End 언어로 처리한 결과를 HTML로 변환해주는 역할을 수행해주는 프로그램

 

JavaWAS 중에서 가장 유명한 프로그램이 apache tomcat 이고 국내 공공기관 SI에서는 티맥스에서 만든 제우스를 많이 사용합니다.

기업들은 사용하는 was가 다양합니다.

하나의 선택이지 필수는 아니다.

 

 

**WAS - Tomcat설치

=>windows의 경우는 installer 버전을 다운로드 받아서 설치 가능

=>나머지 운영체제는 압축된 버전을 다운로드 받아서 압축을 해제한 후 실행할 때 연결해서 사용(startup.sh 또는 startup.bat)

https://tomcat.apache.org/download-80.cgi

 

2.설치

=>windows에서 oracle이 설치된 상태에서 tomcat을 설치할 때는 되도록 포트번호를 변경해주는 것이 좋습니다.

=>oracle8080번 포트를 사용하는데 tomcat의 기본포트가 8080번 입니다.

포트충돌이 발생해서 tomcat이 제대로 구동되지 않을 수 있습니다.

 

windwos 실행파일 bat, com , exe(메모리 사용량이 많다.)

.sh=-> unix , mac, linux에서 사용

su -  : 관리자 번호로 하는 명령어 비밀번호가 설정되어 있어야 한다.

 

=>압축된 파일의 경우는 압축을 해제하는 것으로 설치가 끝난 것입니다.

 

**Eclipse 환경 설정

=>대다수의 ide는 워크스페이스 단위로 환경설정을 합니다.

워크스페이스를 변경하면 이전 환경설정은 사라지게 됩니다.

=>web programming 할 때는 encoding방식을 utf-8 로 설정하고 출력하는 브라우저를 설정을 합니다.

 

1,출력 브라우저 변경

[windows] - [Preferences] -[Applicatioin] - [web browser]  에서 설정

 

2. [Apperance] - [workspace]에서 text file encodingutf-8  로 변경

 

3.[web]에서 html, css, jspencodingutf-8 로 변환

브라우저에서 한글이 깨지면 이 설정을 확인

 

 

4.Mac에서는 encoding설정을 할 필요 없음

 

 

 

반응형

'Study > Java' 카테고리의 다른 글

quickSort, SelectionSort,URLRouting  (0) 2020.11.03
java-19  (0) 2020.10.10
java-18  (0) 2020.10.10
java-17  (0) 2020.10.10
java-16  (0) 2020.10.10
반응형

**오라클 연동

1. 프로젝트에 ojdbc.jar 파일을 복사하고 build path에 추가

 

2. 접속 정보를 저장할 텍스트 파일을 생성

=>프로젝트 안에 db.txt 파일을 생성하고 작성

oracle.jdbc.driver.OracleDriver

jdbc:oracle:thin:@ip주소:1521:xe

user29

user29

 

3.main메소드를 소유한  Main클래스를 만들고 접속하는 코드를 만듬

소스는 배포 안한다.

public class OracleMain {

           public static void main(String[] args) {

                       try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("./src/java/db.txt")))){

                                  String driverClass = br.readLine();

                                  String url = br.readLine();

                                  String id = br.readLine();

                                  String pw = br.readLine();

                                 

                                  //드라이브 클래스 로드

                                  Class.forName(driverClass);

                                  //데이터베이스 연결  객체 생성

                                  Connection con = DriverManager.getConnection(url,id, pw);

                                 

                                  con.close();

                       } catch (Exception e) {

                                  System.out.println("데이터베이스 예외: "+e.getMessage());

                                  e.printStackTrace();

                       }

           }

}

 

4.SQL 실행

1).Select 를 제외한 구문

PreparedStatement pstmt= con.prepareStatement("SQL작성");

=>입력받는 값들은 ? 로 설정

pstmt.set자료형(?번호, 실제데이터);

 

int result = pstmt.executeUpdate();

//리턴되는 값은 영향받은 행의 개수입니다.

//0이 리턴되면 조건에 맞는 데이터가 없는 것이고 1이상의 숫자면 테이블에 변화가 생김

//sql이 잘못되면 예외가 발생

pstmt.close();

 

 

python에서는 "num=" + str(3) ;

java "num="+3

c언언는 itoa 사용해야 한다.

 

로그인 만들때 아이디와 비밀번호 확인 해야 하는데

select *

from member

where id = ?

   and pw = ?;

이 경우에는 id가 비밀번호중 하나만 틀리면 안나온다.

pw '' or 1=1; =>이 경우 무조건  true가 된다.

id = ? and pw = ? or 1=1

이 경우 true가 되기 때문에

대입되는 데이터는 sql예약어를 못 쓰게 하는 것을 확인해야 한다. or못들어 오게 검사를 해야 한다.

비번은 복호화가 불가능한 암호화를 해야 합니다.복호화를 해도 안된다.

암호화의 가장 기본은 다른 값으로 바꿔야 한다.

    5

a ->f

비밀번호 보이는 것 다르게 보이지만 관리자는 해석할 수 있다. +5 할 수 있으면 -5하면 안된다.

복호화는 불가능하고 비교는 가능하도록 저장 하는 것에 대해서 고민을 해야 한다.

비밀번호 찾기 하면 최근에는 없다 . 왜냐하면 복호화가 불가능해서 다른 것을 준다.

비교는 되는데 복호화는 안된다.

 

각대입하기 전에 검사를 해야 한다. 유효성검사이다.

 

자주 사용하는 것은 a , an , the

2)삽입하는 구문을 작성하고 실행

String sql = "INSERT INTO TRANSACTIONS (NUM, ITEMCODE, ITEMNAME, PRICE, CNT, TRANSDATE,USERID) VALUES (?,?,?,?,?,?,?)";

                                  PreparedStatement pstmt = con.prepareStatement(sql);

                      

                                  pstmt.setInt(1, 1);

                                  pstmt.setString(2, "k101");

                                  pstmt.setString(3, "안경");

                                  pstmt.setInt(4, 2000000);

                                  pstmt.setInt(5, 1);

                                  Calendar cal = new GregorianCalendar(2021,0,31,14,34,00);

                                  Date transdate = new Date(cal.getTimeInMillis());

                                  pstmt.setDate(6, transdate);

                                  pstmt.setString(7, "gg");

                                  System.out.println(sql);

                                  int result = pstmt.executeUpdate();

                                  if(result>0) {

                                              System.out.println("삽입 성공");

                                  }

                                  pstmt.close();

 

3)수정하는 구문을 삽입한 구문 대신 작성하고 실행

                                  String sql = "UPDATE TRANSACTIONS SET ITEMCODE = ? ,ITEMNAME = ?, PRICE =?, CNT = ?, TRANSDATE = ?, USERID=?"

                                                         + " WHERE NUM = ?";

                                  PreparedStatement pstmt = con.prepareStatement(sql);

                      

                                  //값 검증 작업을 해야 합니다.

                                  //값이 들어가도 되는지 확인 해야 한다.

                                 

                                  pstmt.setString(1, "t1000");

                                  pstmt.setString(2, "터미네이터");

                                  pstmt.setInt(3, 20000);

                                  pstmt.setInt(4, 1);

                                  Calendar cal = new GregorianCalendar(2021,2,27,14,34,00);

                                  Date transdate = new Date(cal.getTimeInMillis());

                                  pstmt.setDate(5, transdate);

                                  pstmt.setString(6, "gg1");

                                 

                                  pstmt.setInt(7, 1);

                                  System.out.println(sql);

                                  int result = pstmt.executeUpdate();

                                  if(result>0) {

                                              System.out.println("수정 성공");

                                  } else if(result == 0) {

                                              System.out.println("조건에 맞는 데이터가 없습니다.");

                                  }

                                 

                                  pstmt.close();

 

 

4) 삭제하는 구문을 수정하는 구문 대신 작성하고 실행

//데이터 삭제 - 기본키로 가지고 데이터를 삭제하는 것이 일반적

                                  String sql = "DELETE FROM TRANSACTIONS WHERE NUM = ?";

                                  PreparedStatement pstmt = con.prepareStatement(sql);

          

                                  pstmt.setInt(1, 1);

                                  int result = pstmt.executeUpdate();

                                  if(result>0) {

                                              System.out.println("삭제 성공");

                                  } else if(result == 0) {

                                              System.out.println("조건에 맞는 데이터가 없습니다.");

                                  }

                                  pstmt.close();

 

2. 복호화가 불가능한 암호화

=>비밀번호와 같은 데이터를 저장할 때는 관리자도 알아볼수 없도록 복호화가 불가능한 형태로 저장해야 합니다.

=>Java에서 JBcrypt 라이브러리를 이용해서 구현

암호화 할 떄는 BCrypt.hashpw(String 평문 , Bcrypt.getSalt()) ;//암호화 방식을 설정한다.

비교할 때는 BCrypt.checkpw(String 평문, String 암호화된 문장); //두개가 일치하면 true 그렇지 않으면 false

암호화를 할 때는 최소 64자리 이상 저장할 수 있습니다.

 

1)www.mvnrepository.com에서 jbcrypt를 검색해서 다운로드 받아서 프로젝트에 복사하고 build path에 추가

2)데이터를 삽입하는 부분을 수정

                                  //암호화된

                                  System.out.println(BCrypt.checkpw("더미네이터", BCrypt.hashpw("더미네이터", BCrypt.gensalt())));

                                  System.out.println(BCrypt.checkpw("더미네이터1", BCrypt.hashpw("더미네이터", BCrypt.gensalt())));

                                 

                                  System.out.println(BCrypt.hashpw("더미네이터", BCrypt.gensalt()));

                                  System.out.println(BCrypt.hashpw("더미네이터", BCrypt.gensalt()));

똑같은 것도  다르게 저장된다.

A ->3E

A ->4E

gensalt가 라운드 값이다.

 

                                  System.out.println(BCrypt.checkpw("더미네이터", "$2a$10$UZeN.BWhdf6ITyNXOFv18Om1S8y/9UKVPVS8RXfkfK.ZgEPy5lIye"));

                                  System.out.println(BCrypt.checkpw("더미네이터", "$2a$10$tK7xnYE5gxy0TlI0iQbGNeK359rQbUaUHd17m7m8IPxXx5mrF70.m"));

 

복호화가 가능한 것 이메일 이메일은 암호화되서 하는 것이다.

https -> 보안에 적용된 것

 

 

텍스트 마이님 일 경우 replace 해서 "" 으로 치환해서 한다.

비밀번호는 대소문자 구분하지만 아이디는 대소문자 구분하지 않는다.

 

 

//데이터베이스 데이터를 저장하거나 수정할 때 사용할 수 없는 단어를 확인해서 저장하거나 수정하는 것이 좋습니다.

                                  //특히 sql예약어는 확인해서 데이터로 사용하지 못하도록 하는 것이 좋습니다.

                                  String[] stop_words = {"or", "and"};//나중에는

                                  //워드 클라우드 시 관련 된 것을 빼고 할 것이다.

                                 

                                  String sql = "INSERT INTO TRANSACTIONS (NUM, ITEMCODE, ITEMNAME, PRICE, CNT, TRANSDATE,USERID,PASSWORD) VALUES (?,?,?,?,?,?,?,?)";

                                  PreparedStatement pstmt = con.prepareStatement(sql);

                      

                                  pstmt.setInt(1, 6);

                                  String str = "dkdskfasand";

                                  //stop_words의 모든 데이터를 수행

                                  for(String temp : stop_words) {

                                              //idnexOftemp가 몇번째 있는지 검색해주는 메소드

                                              //찾으면 찾은 위치를 리턴하고 못 찾으면 -1을 리턴

                                              if(str.indexOf(temp) >= 0) {

                                                         System.out.println("사용할 수 없는 단어가 포함되어 있습니다.");

                                                         //return 을 하면 작업을 수행하지 않음

                                                         //return;

                                                         //찾으면 ""으로 치환 - 제거

                                                         str = str.replace(temp, "");

                                              }

                                  }

                                  //id나 검색어 등은 모두 대문자 또는 소문자로 변경해서 저장하는 것이 일반적

                                  pstmt.setString(2, str.toUpperCase());

                                  pstmt.setString(3, "안경");

                                  pstmt.setInt(4, 2000000);

                                  pstmt.setInt(5, 1);

                                  Calendar cal = new GregorianCalendar(2021,0,31,14,34,00);

                                  //java.sql.Date

                                  Date transdate = new Date(cal.getTimeInMillis());

                                  pstmt.setDate(6, transdate);

                                  pstmt.setString(7, "gg");

                                  pstmt.setString(8, BCrypt.hashpw("터미네이터", BCrypt.gensalt()));

                                  //BCrypt두가지 방법 밖에 없어서 확인하는 것 밖에 안된다.

                                  //BCrypt두가지 방법 밖에 없어서 확인하는 것 밖에 안된다.

                                  int result = pstmt.executeUpdate();

                                  if(result>0) {

                                              System.out.println("삽입 성공");

                                  }

                                  pstmt.close();

 

3.Transaction

=>한번에 이루어 져야 하는 작업의 논리적인 단위

=>SQL은 명령어 단위로 실행되는데 실제 업무에서는 여러 개의 SQL이 모여서 하나의 작업을 구성하는 경우가 많습니다.

이런 경우에는 트랜잭션을 만들어서 전부수행되거나 전부 수행되지 않도록 해주어야 합니다.(ALL Or Nothing)

 

1) commitrollback

=>commit은 현재 까지 수행한 내용을 원본에 반영

=>rollback은 현재 까지 수행한 내용을 원본에 반영하지 않음

=>savepointrollback할 지점을 생성

 

2)트랜잭션 처리 방법

auto commit: sql문장을 성공적으로 수행될 때 마다 바로 commit

 

manual commit : 명시적으로 commit이나 rollback을 호출해야 하는 방법

 

 

3)트랜잭션 생성

=>commit이나 rollback을 한 후 첫번째 dml(insert, update, delete)을 만났을 때 생성

 

4)commit을 하지 않아도 commit을 수행하고 트랜잭션을 종료하는 경우

=>접속 프로그램을 정상적으로 종료할 때

=>DDL(create, alter, drop,truncate, rename) 이나 DCL(grant, revoke)을 성공적으로 수행한 경우

 

5)자동으로 rollback되는 경우

=>데이터베이스나 접속 프로그램이 비정상적으로 종료되는 경우

 

6)java에서의 트랜잭션 처리

=>java는 기본적으로 auto commit

=>manual commit을 하고자 하는 경우에느느 Connection객체가 setAutoCommit(false)를 호출하고

Connection객체 가지고 commit()이나 rollback()을 호출하면 됩니다.

 

RDBMS(ORACLE)

selectsms 되는데 commit가 된 경우는 다른데서 트랜잭션을 사용하고 있다.

관계형 데이터베이스 하나의 장점은 강력한 트랜잭션이다.

 

commit();//복제의 것을 원본으로 덮어 씌우는 것이다.

트랜잭션은 원본에 하는 것이다.

 

4.select 구문 실행

=>select구문은 PreparedStatement객체를 가지고 executeQuery()를 호출하면 됩니다.

ResultSet을 리턴합니다.

=>ResultSet은 조회된 데이터에 접근할 수 있는 Cursor의 역할을 합니다.

next()메소드를 이용해서 다음 데이터가 있는지 확인하고 있으면 다음 데이터를 가리킵니다.

=>각 컬럼의 데이터를 읽고자 하는 경우에는 ResultSet.get자료형(컬럼의 인덱스 또는 컬럼이름)으로 가져옵니다.

 

=>데이터를 읽어서 다른 곳에서 사용을 하고자 할 때는 검색된 데이터를 하나의 변수에 저장을 해야 합니다.

여러개의 데이터의 경우는 컬럼의 데이터를 저장할 수 있는 DTO클래스를 생성하고나 mAP을 이용해서 저장하고 이러한 DTO클래스나 mAP클래스의 인스턴스들은 lIST에 저장합니다.

이런 구조를 r이나 Pythonpandas에서는 DataFrame이라고 합니다.

MapList구조입니다.

public class SelectMain {

           public static void main(String[] args) {

                       try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("./src/java/db.txt")))){

                                  String driverClass = br.readLine();

                                  String url = br.readLine();

                                  String id = br.readLine();

                                  String pw = br.readLine();

                                 

                                  //드라이브 클래스 로드

                                  Class.forName(driverClass);

                                  //데이터베이스 연결  객체 생성

                                  Connection con = DriverManager.getConnection(url,id, pw);

                                 

                                  //transactions테이블의 모든 데이터 가져오기

                                  String sql = "Select * from transactions";

                                  PreparedStatement pstmt= con.prepareStatement(sql);

                                  ResultSet rs = pstmt.executeQuery();

                                 

                                  //여러개의 컬럼으로 구성된 여러 개의 데이터를 저장

                                  List<Map<String , Object>> list = new ArrayList<Map<String , Object>>();

                                 

                                  //데이터를 순회

                                  while(rs.next()) {

                                              //하나의 행을 저장할 Map을 생성

                                              Map<String , Object> map = new HashMap<String ,Object>();

                                             

                                              map.put("num", rs.getInt("num"));

                                              map.put("itemcode", rs.getString("itemcode"));

                                              //3번째 컬럼의 값을 itemname으로 가져오는 것

                                              map.put("itemname", rs.getString(3));

                                              map.put("price", rs.getInt("price"));

                                              map.put("cnt", rs.getInt("cnt"));

                                              map.put("userid", rs.getString("userid"));

                                              map.put("transdate", rs.getDate("transdate"));

                                              map.put("password", rs.getString("password"));

                                             

                                              //하나의 행을 list에 저장

                                              list.add(map);

                                  }

                                 

                                  //list의 데이터 출력

                                  for(Map<String , Object> map :list) {

                                              //System.out.println(map);

                                              System.out.println(map.get("num"));

                                  }

                                 

                                  pstmt.close();

                                  con.close();

                       } catch (Exception e) {

                                  System.out.println("데이터베이스 예외: "+e.getMessage());

                                  e.printStackTrace();

                       }

           }

}

 

=>DTO패턴: Map 대신에 여러 개의 데이터를 저장할 수 있는 별도의 클래스를 만들어서 사용하는 패턴

이러한 클래스를 DTO(Data Transfer Object)또는 VO(Variable Object) 또는 Domain 클래스라고 합니다.

public class Transactions {

           private int num;

           private String itemcode  ;

           private String itemname  ;

           private int price     ;

           private int cnt       ;

           private Date transdate ;

           private String userid    ;

           private String password  ;

          

           public Transactions() {

                       super();

           }

          

           public Transactions(int num, String itemcode, String itemname, int price, int cnt, Date transdate, String userid,

                                  String password) {

                       super();

                       this.num = num;

                       this.itemcode = itemcode;

                       this.itemname = itemname;

                       this.price = price;

                       this.cnt = cnt;

                       this.transdate = transdate;

                       this.userid = userid;

                       this.password = password;

           }

          

           public int getNum() {

                       return num;

           }

           public void setNum(int num) {

                       this.num = num;

           }

           public String getItemcode() {

                       return itemcode;

           }

           public void setItemcode(String itemcode) {

                       this.itemcode = itemcode;

           }

           public String getItemname() {

                       return itemname;

           }

           public void setItemname(String itemname) {

                       this.itemname = itemname;

           }

           public int getPrice() {

                       return price;

           }

           public void setPrice(int price) {

                       this.price = price;

           }

           public int getCnt() {

                       return cnt;

           }

           public void setCnt(int cnt) {

                       this.cnt = cnt;

           }

           public Date getTransdate() {

                       return transdate;

           }

           public void setTransdate(Date transdate) {

                       this.transdate = transdate;

           }

           public String getUserid() {

                       return userid;

           }

           public void setUserid(String userid) {

                       this.userid = userid;

           }

           public String getPassword() {

                       return password;

           }

           public void setPassword(String password) {

                       this.password = password;

           }

 

           @Override

           public String toString() {

                       return "Transactions [num=" + num + ", itemcode=" + itemcode + ", itemname=" + itemname + ", price=" + price

                                              + ", cnt=" + cnt + ", transdate=" + transdate + ", userid=" + userid + ", password=" + password + "]";

           }

          

}

 

=>데이터 읽어서 DTO List만들기

 

                                  List<Transactions> list = new ArrayList<Transactions>();

                                 

                                  //데이터를 순회

                                  while(rs.next()) {

                                              //하나의 행을 저장할 Map을 생성

                                              Transactions transactions = new Transactions();

                                              transactions.setNum(rs.getInt("num"));

                                             transactions.setItemcode(rs.getString("itemcode"));

                                             transactions.setItemname(rs.getString("itemname"));

                                              transactions.setPrice(rs.getInt("price"));

                                              transactions.setCnt(rs.getInt("cnt"));

                                             transactions.setTransdate(rs.getDate("transdate"));

                                             transactions.setUserid(rs.getString("userid"));

                                             transactions.setPassword(rs.getString("password"));

                                             

                                              //하나의 행을 list에 저장

                                              list.add(transactions);

                                  }

                                 

                                  //list의 데이터 출력

                                  for(Transactions transactions :list) {

                                              //System.out.println(transactions);

                                             System.out.println(transactions.getNum());

                                  }

장점은 오타가 적다 .

하지만 테이블 구조를 바꾸고 다시 생성할 경우 다시 실행할 때 데이터가 있을 경우 오류가 난다.

 

mapwhile에만 바꾸면 된다.

 

5.MapDTO비교

=>DTO는 메소드를 호출해서 대입하고 가져오기 때문에 오류를 발생시킬 가능성이 줄어든다는 장점은 있지만 데이터 구조가 변경되는 경우에 수행할 부분이 많아 집니다.

관계형 데이터베이스 (RDBMS - 테이블 기반의 데이터베이스)의 특징입니다.

 

=>Map을 사용하면 put이라는 메소드를 이용할 때 문자열로 키를 지정하고 get으로 읽어올 때 문자열로 키를 대입해야 하는데 이 때 키 이름등의 오류가 많이 발생합니다.

데이터 구조가 변경되더라도 저장과 읽기 할 때 키만 변경하면 됩니다.

NoSQL 데이터베이스의 특징

 

 

**Web From End

HTML ->CSS-> JavaScript ->HTML5

HTML5javaScript를 사용

IDEEclipse를 사용하는데 Front End만 하는 경우에는 느려서 다른 VSCode, Aptana Studio등을 이용해서 됩니다.

EclipseWAS가 없으면 웹프로그램을 실행할 수 없음

 

반응형

'Study > Java' 카테고리의 다른 글

quickSort, SelectionSort,URLRouting  (0) 2020.11.03
java-20  (0) 2020.10.10
java-18  (0) 2020.10.10
java-17  (0) 2020.10.10
java-16  (0) 2020.10.10
반응형

**Design Pattern

=>객체의 사용 용도에 따라 클래스를 디자인하는 것

1. 생성과 관련된 패턴

1)Singleton

=>인스턴스를 1개만 만들 수 있도록 클래스를 디자인 하는 것

=>관리자 클래스(Controller, Manager)나 애플리캐이션 전체가 공유해야 하는 공유 데이터를 갖는 클래스 또는 서버에서 클라이언트의 요청을 처리하는 클래스 등은 일반적으로 인스턴스를 1개만 만들어서 사용

=>java.lang.Runtime클래스가 이 패턴으로 디자인

 

2)Decorator Pattern (커피)

=>외부에서 데이터를 주입받아 인스턴스를 생성하는 구조

=>하는 일은 유사한데 일을 수행해야 하는 대상이 여러가지 종류일 때 사용하는 패턴

=>작업을 수행하는 대상을 클래스 내부에서 직접 생성하지 않고 외부에서 생성한 후 주입받는 형태의 구조

=>java.io.BufferedReader클래스가 Decoragor Pattern의 대ㅍ적인 예

BufferedReader는 문자 스트림에서 문자열을 읽어오는 스트림

new BufferedReader(new InputStreamReader(new FileInputStream(String filepath))); 파일에서 읽어오기

new BufferedReader(new InputStreamReader(Socket.getInputStream())); 소켓에서 읽어오기

new BufferedReader(new InputStreamReader(HttpURLConnection.getInputStream())); 웹에서 읽어오기

                            

 

=>매개변수가 여러 개가 될 수 있습니다.

=>C++이나 JAVA는 생성자 오버로딩을 이용해서 구현하거나 매개변수로 대입되는 클래스의 다형성을 이용해서 구현

 

 

2.구조와 관련된 패턴

1)템플릿 메소드 패턴

=>메소드의 원형을 인터페이스(추상 클래스)에 선언하고 인터페이스를 구현한 클래스에 메소드를 구현하는 방식

c++은 인터페이스가 없고 추상클래스이다.

=>cc++(추상 클래스)는 인터페이스 대신에 헤더파일을 이용해서 구현

최근에는 이런 방식은 잘 사용되지 않음

 

스마트폰이나 게임해야 할때 조심해야 하는 부분

 

최근에 등장하는 GUI를 구현하는 언어들 중에도 파일을 2개로 나누어서 구현하는 경우가 있는데 이 경우는 디자인 파일과 구현 파일을 분리하는 형태잊 헤더 파일을 이용하는 형태가 아닙니다.

최근에는 INTERFACE, SWAFT등으로 작업한다.

 

=>프로그래밍을 할 때 사용자의 요청을 처리하는 클래스는 이 패턴으로 디자인 합니다.

이렇게 사용자의 요청을 처리하는 메소드를 소유한 클래스를 Service 클래스 라고 합니다.

데이터베이스 연동 프로그램에서 트랜잭션을 적용하는 지점은 Service 클래스의 메소드입니다.

 

=>어떤 Unit이라는 클래스를 설계하는데 사용자가 공격과 이동이라는 동작을 수행해야 합니다.

uml에서 확인

 

Interface mpl

classEx

int i

Controller controller =

소문자로 시작

변수

메소드

패키지

 

대문자로 시작

클래스

 

모두 대문자

상수

 

c언어 일 경우 macro는 대문자로 해라

numpy ndarray

pandas Series

python은 소문자로 시작했다 나중에 개발자들이 name을 사용하기 시작했다.

series() Series() 생성자

 

인터페이스 생성

//이 프로그램은 설계에 가깝다.

public interface Unit {

           //공격을 수행하는 메소드

           public void attack();

           //이동을 수행하는 메소드

           public void move();

           //자바는 코드로 도여있지만 uml로 하면 알기 쉽다.

}

 

인터페이스를 구현한 class를 생성

public class UnitImpl implements Unit {

 

           @Override

           public void attack() {

                       System.out.println("공격");

           }

 

           @Override

           public void move() {

                       System.out.println("이동");

           }

 

}

 

main메소드를 만들어서 사용

public class UnitMain {

           public static void main(String[] args) {

                       //탬플릿 메소드 패턴이 적용된 클래스의 인스턴스 만들기

                       //변수는 인터페이스 이름을 사용하고 생성자는 클래스 이름을 이용하는 형태로 많이 작성합니다.

                       UnitImpl unitImpl = new UnitImpl();

                       unitImpl.attack();

                       unitImpl.move();

                      

                       List<String> list = new ArrayList<String>();

           }

}

2)Adapter Pattern

=> 구현된 인터페이스를 이용해서 상속받은 클래스의 메소드를 호출하는 패턴

=>상속받은 클래스의 메소드를 직접 호출하기가 어려운 경우 이용

=>상속을 받았기 때무에 상위 클래스의 메소드를 호출해서 사용하는 것이 가능한데 상위 클래스의 메소드 이름을 다른 용도로 사용하는 경우 - 상위 클래스의 메소드의 내용을 변경해서 오버라이딩 하는 경우

=>원래 오버라이딩응ㄴ 상위 클래스의 메소드 기능을 확장하기 위해서 사용하는데 확장이 아니라 변경한 경우

 

=>Base 클래스 생성

public class OldSystem {

           public void process() {

                       System.out.println("예전 처리");

           }

}

 

=>Targe인터페이스 생성

public interface Target {

           //OldSystem process 를 호출하기 위한 메소드

           public void legacyProcess();

}

 

=>Derived 클래스 생성

public class NewSystem extends OldSystem implements Target{

           @Override

           public void process() {

                       //구현된 메소드의 오버러이딩 : 상위 클래스의 메소드를 호출하고 기능을 추가

                       /*

                       super.process();

                       System.out.println("기능 추가");

                       */

                       System.out.println("새로운 기능");

           }

           //java는 예전것도 지원한다.

 

           @Override

           public void legacyProcess() {

                       super.process();

           }

}

 

=>main메소드를 만들어서 실행

public class AdapterMain {

           public static void main(String[] args) {

                       NewSystem newSystem = new NewSystem();

                       //새로 만들어진 메소드

                       newSystem.process();

                       //이전에 만들어진 메소드

                       newSystem.legacyProcess();

           }

}

 

3)Composite Pattern

=>재귀적 구조를 쉽게 처리하기 위한 패턴

=>Recursive Call(Recursion- 함수가 내부에서 함수 자신을 다시 호출하는 경우)

=>파일 시스템에는 파일과 디렉토리가 있는데 디렉토리를 삭제할려고 하는 경우 디렉토리 안의 내용을 확인해서 디렉토리이면 다시 그 안에 있는 내용들을 삭제해야 합니다.

=>하나의 인터페이스를 만들고 인터페이스에 공통된 메소드 이름을 만들어주고 파일과 디렉토리 처리를 위한 클래스를 별도로 만들어서 처리하는 메소드를 구현합니다.

다형성을 구현하는 방식과 유사합니다.

 

=>인터페이스는 Entry- addremove그리고 rename

=>클래스는 FileDirectory로 생성

 

=>인터페이스 생성

//파일의 디렉토리 클래스에서 공통으로 사용할 메소드를 소유한 인터페이스

public interface Entry {

           public void add(Entry entry);

          

           void remove();//자기 자신을 지우는

          

           void rename(String name);

}

 

=>File클래스 생성

public class File implements Entry {

          

           //파일 이름을 저장할 변수

           private String name;

          

           public File(String name) {

                       this.name = name;//생성자로 부터 대입 받을 때

           }

          

           @Override

           public void add(Entry entry) {

                       System.err.println("파일에는 파일이나 디렉토리를 추가할 수 없습니다.");

           }

 

           @Override

           public void remove() {

                       System.out.println(name+"가 삭제 되였습니다.");

           }

 

           @Override

           public void rename(String name) {

                       this.name = name;

           }

 

}

 

=>Directory 클래스

public class Directory implements Entry {

           private String name;

          

           //FIle이나 Deriectory 를 소유할 수 있기 때문에 Entry를 여러 개 저장할 수 있는 자료구조를 소유

           List<Entry> list;

           public Directory(String name) {

                       this.name = name;

                       list = new ArrayList<Entry>();

           }

          

          

           @Override

           public void add(Entry entry) {

                       list.add(entry);

           }

 

           @Override

           public void remove() {

                       //list null이면 NullPointerException

                       //list가 인스턴스 생성은 되였는데 멤버가 없으면 수행을 안함

                       //Iterator 를 이용해서 데이터 접근

                       Iterator<Entry> iter = list.iterator();

                       while(iter.hasNext()) {

                                  Entry entry = iter.next();

                                  //file 은 지우지만 direcoty는 지우는 지 확인 해야 한다.

                                  entry.remove();

                       }

                       System.out.println("내부 데이터는 전부 삭제 되였습니다.");

                       /*for(Entry entry: list) {

                                  //디렉토리인지 확인해서 작업을 수행을 하지 않을 수 도 있습니다.

                                 

                                  //FIle이 있으면 File remove를 호출하고 Directory이면 Direcoty remove를 호출 - 다형성(Polymoriphism)

                                  //일반 다형성과 다른점은

                                  //Direcotory file를 할 수있다 .. .list가 있어서

                                  //이것 때문에 composite라고 한다.

                                  //file 은 지우지만 direcoty는 지우는 지 확인 해야 한다.

                                  entry.remove();

                       }*/

           }

 

           @Override

           public void rename(String name) {

                       this.name = name;

           }

 

}

 

=>main메소드를 만들어서 테스트

public class CompositeMain {

           public static void main(String[] args) {

                       File f1 = new File("파일1");

                       File f2 = new File("파일2");

                       File f3 = new File("파일3");

                      

                       Directory subDirectory = new Directory("하위 디렉토리");

                       subDirectory.add(f1);

                       subDirectory.add(f2);

                      

                       Directory superDirectory= new Directory("상위 디렉토리");

                       superDirectory.add(subDirectory);

                       superDirectory.add(f3);

                      

                       superDirectory.remove();

                      

                       //자료형 이름 출력

                       System.out.println(superDirectory.getClass().getName());

                       Entry entry = new Directory("디렉토리");

                       System.out.println(entry.getClass().getName());

           }

}

 

3.행동에 관련된 패턴

1)Command Pattern

=>처리 내용이 비슷한 명령을 모아서 실행하는 처리가 필요할 때 명령을 인스턴스로 취급해서 처리하는 패턴

 

=>데이터를 삽입하는 처리와 수정하는 처리가 필요한 경우

 

interface Action{

           public void execute(DTO dto); //다형성 구현한 것 처럼 한다.

}

 

class InsertAction Implement Action{

           public void execute(DTO dto){

                       오버라이딩 하고 삽입하는 크도

}

}

 

class updateAction Implement Action{

           public void execute(DTO dto){

                        수정하는 크도

}

}

 

//action에 대입되는 인스턴스 자체가 명령어와 유사한 역할을 수행

Action action = null;

if(command == 삽입){

           action = new insertAction();

}else if(command == 삭제){

           action = new updateAction();

}

action.execute(dto);

 

=>이러한 패턴은 서버의 Controller 클래스를 만들어서 요청에 따라 처리를 많이 사용

웹 서버 프로그래밍을 하다보면 URL에 따른 Routing구조를 만들 때도 이 구조를 이용합니다.

 

 

2)Observer Pattern

=>어떤 인스턴스의 내부 상태가 자주 변경되는 경우 내부 상태가 변경되는지를 감시하고 있다가 변경이 되면 알려줘서 처리를 할 수 있도록 해주는 패턴

=>알려준다고 해서 Notification이라는 표현을 많이 사용합니다.

=>이 패턴을 사용하는 대표적인 예가 스마트 폰의 뷰에서 키보드가 화면에서 보여지고 사라지는 것을 감시해서 뷰의 컴포넌트들을 재배치 하는 형태

 

3)Strategy Pattern

=>어떤 클래스가 공통된 부분이 있고 서로 다른 부분이 있는 경우 공통된 부분은 클래스 안에서 만들어 사용하고 서로 다른 부분은 외부에서 주입(Injection)받아 사용하는 패턴

public class Injection {

           private String common;//모든 인스턴스들이 "Java"라고 저장해서 사용

           private String diff1; //인스턴스들 마다 다름

           private String diff2; //인스턴스들 마다 다름

          

           public Injection(String diff1) {

                       common = "java";

                       //생성자를 이용한 주입

                       this.diff1  =diff1;

           }

          

           //diff2에 대한 setter메소드 - setter getter를 소유한 인스턴스 변수를 property라고 합니다.

           public void setDiff2(String diff2) {

                       this.diff2 = diff2;

           }

          

           //common diff1 null일 가능성이 없지만

           //diff2 setter 를 이용해서 대입받기 때문에 null일 가능성이 존재

           //서버 프로그래밍을 할 때는 메모리 부담이 되더라도 처음부터 만들어두고 사용하는 것이 좋고

           //클라이언트 프로그래밍을 할 떄는 속도가 느리더라고 필요할 때 생성하는 것이 좋습니다.

           //서버에서 하는 것인지 클라이언트 ㅎ하는 지 완전히 다르다ㅏ.r은 메모리 부담이 많이 된다.

           public void disp() {

                       System.out.println(common.toUpperCase());

                       System.out.println(diff1.toUpperCase());

                       System.out.println(diff2.toUpperCase());

           }

 

}

public class InjectMain {

           public static void main(String[] args) {

                       Injection injection = new Injection("JavaScript");

                       //다른 메소드들을 호출

                       //diff1을 가져고 다녀야 한다.

                      

                       //다른 메소드들을 호출              

                       injection.setDiff2("Spring");//사용하기 직전에 만들어서 사용한다. 메모리 절략은 되는데 속도가 느리다.

                       injection.disp();

                      

                       //setDiff2를 호출하지 않았기 때문에 diff2 null인 상태에서  toUpperCase를 호출해서 예외

                       injection = new Injection("FrontEnd");

                       injection.disp(); //java.lang.NullPointerException

           }

}

 

 

 

=>Design Pattern은 하나의 클래스에 여러가지를 적용하기도 합니다.

=>Design Pattern의 개념은 절대적인 개념이 아니라서 개발자마다 약간씩 다르게 설명하기도 합니다.

Singleton, Template Method, Command Pattern은 모두 동일하게 설명합니다.

=>이외에도 인스턴스 생성을 대신해주는 Factory Method Pattern이나 개발자가 만든 클래스에 코드를 더해서 실제로는 개발자가 만든 클래스와 다른 형태의 인스턴스를 만들어내느느 Proxy Pattern 등도 있습니다.

=>객체지향 프로그래밍에서는 디자인 패턴이 중요합니다.

 

객체지향 프로그래밍 언어 문법 -> 자료구조&알고리즘 ->디자인패턴 ->SW공학(개발 방법론 ..)

CCLASS가 없다. 디자인패턴이 없다.

 

 

**외부로 부터 데이터를 방아서 사용하는 경우

=>주입을 받는 방법은 생성자를 이용하는 방법이 있고 프로포티(setter)를 이용하는 방법

생성자를 이용하는 방법은 처음부터 가지고 있기 때문에 NullPointerException이 발생할 가능성이 적지만 메모리에 부담이 되고  setter을 이용하는 방식은 사용하기 전에 주입받아서 사용하기 때문에 메모리를 절약할 수 있지만 항상 NullPointerExcetpion에 대비해야 합니다.

 

**데이터 저장 및 읽기

1.로컬이나 원격에 Flat file형태로 저장

=>text 형식 : txt, csv형식 -용량이 작다는 장점이 있지만 전체가 아닌 일부 검색은 어려움

=>xml,json형식 : 구격화된 포맷 형식 - 인간이 알아보기 쉬움, 인간이 직접 작성도 가능,사이즈가 커지면 용량도 커지고 알아보기도 어려워집니다.

설정 내용을 저장할 때 나 실시간으로 작은 용량의 데이터를 주고받을 때 이용

 

2. 별도의 저장 프로그램 이용

=>Database:앞의 방법 들보다 보안이 우수하고 검색 조건을 다양하게 설정할 수 있음 , 데이터이외이 많은 것들을 저장해야 하기 때문에 오버헤드가 큼 (돈이 많이 든다.)

비밀번호 보안예기 많이 나온다.

 

 

**관계형 데이터베이스 인 오라클 사용

1.프로그래밍 언어에서 관계형 데이터베이스를 사용하는 방법

1)언어가 제공하는 기능만을 이용해서 구현 - java의 경우는 jdbc그리고 윈도우는 odbc

2)프레임워크를 이용해서 구형 - 언어가 제공하는 기능을 편리하게 사용할 수 있도록 만들어진 프레임워크 이용

-SQL Mapper: Java코드와 SQL을 분리해서 작성하는 구조 , Mybatis(iBatis가 예전 이름)(c#도 사용가능)가 대표적

=>성능은 떨어지지만 쉬워서 si(시스템 통합 - 기업의 전산화 , 외주를 많이 줌)에서 많이 사용

-Object Relation Mapper (ORM)

=>최근에 많이 사용하는 프레임워크로 하나의 행을 하나의 인스턴스와 매핑하는 프레임워크

하나의 테이블을 하나의 클래스와 매핑

데이터베이스에 대한 구조를 파악하고 있어야만 사용이 가능

어렵지만 성능이 우수해서 솔루션 제작에 많이 이용

JavaJPA(구현체로는 Hibernate)가 대표적인 프레임워크 - 다른 언어에도 대부분 있음

카카오와 배민이 이것 사용하고 있다.

sql없이 데이터베이스 작업이 가능 - dbms를 변경해서 적용하더라고 설정파일만 수정하면 됩니다.

 

 

iBatis, MyBatis

MariaDB, MySQL

Fedora(테스트형), Cent OS(stable버전), Red Hat Enterprise(stable해서 사용화 버전 ) <->Ubuntu

 

sqlite ->autoincrement : sqlite의 일련번호

오라클 ->sequence nextval()

 

서비스를 작은 마이크로 서비스 단위로 만들고

 

2.java에서 관계형 데이터베이스 연동 방법

1)사용하고자 하는 데이터베이스와의 인터페이스를 제공하는 드라이버를 사용할 수 있도록 설정

=>자바는 드라이버를 build path에 추가하고 클래스를 로드

 

 

드라이브 사용하는 것은 프린트 서로 다른 것 통신해주기로 해서

python은 예외 sqlite3가 예외이다 드라이브에 lib에 있어서 할 필요없다.

pip install

 

2)데이터베이스 접속 정보를 가지고 데이터베이스 연결 객체(java.sql.Connection)를 생성

=>접속정보는 데이터베이스 URL, 포트번호 , 데이터베이스이름(오라클의 경우는 SID또는 serviceName)이 필요하고 접속계정과 비밀번호도 필요

=>데이터베이스 종류에 따라서 접속 계정과 비밀번호가 필요없는 경우가 있음

=>데이터베이스 중에는 자신의 기본 포트를 사용하는 경우 포트번호 생략이 가능(Mysql3306 포트인 경우 생략가능 )

=>자바의 경우는 연결 객체를 이용해서 트랜잭션 사용 방법을 설정합니다.

 

3)Connection을 이용해서 SQL을 주고받을 객체를 생성하고 실행 - JavaStatement(완성된 sql) ,PreparedStatement(나중에 데이터를 매핑할 수 있는 sql - 대부분의 언어가 사용), CallableStatement (Procedure 실행)

 

4)결과를 사용

-select 를 제외한 구문 : 영향받은 행의 개수를 정수로 리턴

- select 구문 : select의 결과를 사용할 수 있는 Cursor를 리턴

 

5)트랜잭션 처리를 하고 사용한 객체를 close를 합니다.

 

6)java에서는 이 과정 전체가 예외처리를 강제합니다.

다른 언어에서 예외처리를 강제하지 않더라도 예외처리를 해주는 것이 좋습니다

문제가 발생하면 어떤 조치를 취할 수 있도록 해 주어야 합니다.

데이터베이스는 외부에 존재하는 경우가 많기 떄무에 어떤 문제가 발생할 지 우리가 예측할 수 없습니다.

 

3.애플리케이션 프로그램이 잘 수행하지 않는 sql

=>Grant(권한 부여), Revoke(권한 회수)

=>Create(개체 생성) ,Alter(개체 구조 변경), Drop(개체 삭제) ,Truncate(테이블의 데이터만 삭제), Rename(테이블의 이름 변경)

=>주로 관리자가 사용하는 sql명령들이고 이 명령들은 Rollback이 안됩니다.

관리자만 로컬에서 사용하는 애플리케이션을 만들어서 수행하도록 하는 경우는 종종 있습니다.

(원격으로 잘 안한다.)

 

4.데이터베이스 계정

ip: 

PORT:1521

SID:xe

계정 : user01-user30

비번 : user01-user30

 

강사님 계정 user00

 

5.샘플 테이블을 생성

=>Oracle의 자료형

숫자는 - number(정수자릿수),number(전체자릿수 ,소수자릿수)

 

문자열 - char(글자수),varchar2(글자수), clob

한글은 곱하기 3

char를 사용하면 글자수보다 작은 양의 글자를 입력하면 뒤에 공백이 있습니다.

clob는 아주 많은 글자인 경우 사용

 

날짜 - date

 

=>거래정보 테이블

거래번호 - 정수이고 기본키, 일련번호 형식

품목코드 - 거래한 품목의 코드 , 문자열 20자리

품목명 - 거래한 품목이름 , 문자열  100자리

단가 - 정수 7자리

수량 - 정수 3자리

거래일 - 날짜

거래 id -거래한 유저의 id, 문자열 50자리

 

create table transactions(

           num number(10) primary key,

           itemcode varchar2(20),

           itemname varchar2(100),

           price number(7),

           cnt number(3),

           transdate date,

           userid varchar2(50)

);

 

6. 프로젝트를 생성하고 오라클을 사용할 준비

=> 데이터베이스 드라이브를 프로젝트의 build path애 추가

오라클은 ojdbc>.jar

ojdbc6.jar :숫자의 의미는 자바 버전이고 이 이외의 숫자가 추가로 있으면 오라클 버전입니다.

상위버전은 하위버전을 지원

 

7.애플리케이션이 시작될 때 1번 드라이버 클래스를 로드

=>Class.forName("드라이버 클래스 이름"); //여기에 직접 쓰지 않는다.

=>실제 애플리케이션을 만들 때는 드라이버 클래스 이름을 별도의 파일에 작성하고 읽어들이는 구조로 만듭니다.

=>오라클의 경우 드라이버 클래스 이름: oracle.jdbc.driver.OracleDriver

=>드라이브 클래스 이름이 틀리거나 jar파일을 build path에 추가하지 않았다면 예외가 발생합니다.

public class OracleMain {

           public static void main(String[] args) {

                       try {

                                  //이 코드는 애플리케이션 전체에서 1번만 수행하면 됩니다.

                                  Class.forName("oracle.jdbc.driver.OracleDriver");

                                  System.out.println("드라이브 클래스 로드 성공");

                       } catch (Exception e) {

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

                                  e.printStackTrace();

                       }

           }

}

 

8. 데이터베이스 연결 및 해제

=>데이터베이스에 연결할 때 는 3가지 정보가 필요

데이터베이스 url:  데이터베이스 종류마다 설정 방법이 다름

계정

비번

=>계정과 비번은 없어도 되는 경우가 있습니다.

=>오라클의 url: -jdbc:oracle:thin:@IP또는 domain :port:sid

sid가 아니고 serviceName인 경우는 : 대신에 /serviceNmae

 

=>데이터베이스 접속

Connectioin ? = DriverManager.getConnection(url, id, pw);

 

=>데이터베이스 접속 해제

?.close();

 

=>url이 잘못 된 경우는 기본적인 접속시간동안 접속을 해보고 네트워크 문제라고 예외를 발생시킵니다.

=>idpw가 잘못된 경우는 login denied라는 예외를 발생시킵니다.

           public static void main(String[] args) {

                       try {

                                  //이 코드는 애플리케이션 전체에서 1번만 수행하면 됩니다.

                                  Class.forName("oracle.jdbc.driver.OracleDriver");

                                  System.out.println("드라이브 클래스 로드 성공");

                                 

                                  //데이터베이스 접속

                                  Connection con = DriverManager.getConnection("jdbc:oracle:thin:@ip주소:1521:xe","user29","user29");

                                  //ip주소 잘못되면 멍때리고 있다.후에 나온다.

                                  //포트번호가 틀리면 빨리 떤다.

                                  //login denined

                                  System.out.println("접속 성공");

                                 

                                  //접속 해제

                                  con.close();

                       } catch (Exception e) {

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

                                  e.printStackTrace();

                       }

           }

 

9.데이터베이스 드라이버이름이나 접속 정보는 별도로 작성한 후 읽어 들이는 구조로 만드는 것을 권장

개발환경과 운영환경이 다를 가능성 때문입니다.

 

프로그래밍 언어별 실행방법

1. 줄 단위로 읽어가면서 실행 - 인터프리터 방식

(대표적인 언어가 python)

python은 코드를 작성할 때 한줄 씩 실행한다.idle에서는 줄단위로 해서 불편해서 파일로 실행한다.

 

 

2.소스 전체를 번역한 후 실행

1).줄단위로 실행

 

2).전체로 한꺼번에 실행

 

 

source code -> compile(번역) -> java에서는 byte code(중간코드)만든다. -> build -> 실행 가능한 코드가 만들어진다. -> 로드 (메모리에 적재) -> 실행 (Run)

 

                

개발 환경 -------------------------------------> 운영환경

localhost:1521 : xe                         211....:1521 : xe

getConnection("localhost:1521:xe")=>이것을 운영에 올릴 때

=> getConnection("211..:1521:xe")으로 소스 코드 바꿔야 한다.

소스 코드 바꾸면 처음 부터 해야 한다.

예기치 않는 문제가 발생

이런 경우를 줄이려면 이쪽에 작업을 안할려고 하는 방법

setting.xxx=>파일 을 만들어서 db : localhost: 1521:xe

getConncetion(파일의 내용을 읽는 코드를 사용)

데이터를 바꿀 경우 파일의 내용을 바꾸면 된다. 자바 코드를 바꾸지 않았다.

BUILD를 다시 할 필요없다. 배포만 다시 하면 된다.

SETTING.XXX-> properties

xml -> json

자원이 넉넉하면 클릭해서 손을 댈 수 있어서 별도에 디비에 여는 경우가 있다.

별도의 디비에 작성

 

 

 

반응형

'Study > Java' 카테고리의 다른 글

java-20  (0) 2020.10.10
java-19  (0) 2020.10.10
java-17  (0) 2020.10.10
java-16  (0) 2020.10.10
java-15  (1) 2020.10.05
반응형

**스트림 api

=>java.io패키지에 있는 스트림은 입출력을 위한 스트림

=>java.util.stream패키지의 스트림은 Collection 에 대한 작업을 위한 스트림 -1.8버전에 추가

=>기존에는 동일한 자료형의 데이터 여러 개를 다룰 때 Collection이나 배열을 이용

Collection이나 배열을 이용하게 되면 코드가 길어지고 재사용성이 떨어집니다.

Collection과 배열에 있는 동일한 작업을 수행하는 메소드가 이름은 같은데 사용방법이 조금씩 다릅니다.

예를 들면 LIst의 정렬을 위한 sort메소드는 instance메소드인데 배열의 정렬을 위한 메소드는 Arrays클래스의 SORT라는 STATIC메소드입니다.

배열의 데이터를 하나씩 가져올 때는 [인덱스]를 이용하고 list의 데이터는 get(인덱스)을 이용합니다.

=>메소드의 매개변수로 인터페이스를 이용하는 경우에 별도의 클래스를 만들거나 anonymous class를 이용해야 해서 코드가 길어지고 메모리 낭비가 발생했는데 스트림api에서는 매개변수에 람다식을 사용해서 코드를 간결하게 만들 수 있습니다.

=>병렬처리도 쉽게 할 수 있음

 

1.배열의 데이터 접근

CollectionUse.java

public static void main(String[] args) {

                       //List의 데이터를 사용

                      

                       //배열을 이용해서 lIST만들기

                       List<String> list = Arrays.asList("C","Python","Java");

                      

                       //인덱스를 이용해서 하나씩 접근 - 배열이나 List의 데이터 개수를 알아야 합니다.

                       System.out.println();

                       System.out.println("데이터를 인덱스를 이용해서 하나씩 접근");

                       int length = list.size();

                       int i = 0;

                       //for보다 while이 좋다.

                       //for은 집단으로 접근하는게 좋다.

                       while(i < length) {

                                  String temp = list.get(i);

                                  System.out.println(temp);

                                  i++;

                       }

                      

                       System.out.println();

                       System.out.println("반복자(Iterator - Enumeration : __iter__:python)을 이용해서 하나씩 접근");

                       //반복자는 데이터 개수를 알 필요가 없습니다.

                       Iterator<String> iterator = list.iterator();

                       //다음 데이터 존재 여부를 확인하고 다음 데이터에 접근 - 데이터베이스에서는 Cursor라고 합니다.

                       //데이터베이스나 c++에서는 이런 방법으로 접근을 하지만 JavaPython같은 언어는 다른 방법을 제공

                       //간경해졌고 길이를 알 필요없다.

                       while(iterator.hasNext()) {

                                  System.out.println(iterator.next());

                       }

                      

                       System.out.println();

                       System.out.println("빠른 열거 (for-each)를 이용하는 방법");

                       //반복자가 구현된 객체의 경우는 빠른 열거를 사용하는 것이 가능

                       //예약어만 다른것이지 접근 방법은 똑 같다.

                       for(String temp: list) {

                                  System.out.println(temp);

                       }

                      

                      

                       System.out.println();

                       System.out.println("스트림을 이용하는 방법");

                       //스트림 생성

                       Stream<String> stream = list.stream();

                       //람다식을 이용해서 메소드의 내용을 매개변수로 대입 - 함수형 프로그래밍

                       //스트림을 만들때 사용한 Collection의 데이터를  name에 순서대로 대입해서 {}안의 내용을 수행

                       //반복문을 사용하지 않아도 forEach가 알아서 순서대로 실행

                       //python에서의 numpyndarray pandas Series, DataFrame등의 동작방식에 이와 동일

                       stream.forEach((name) -> {System.out.println(name);});

           }

 

2. 스트림의 특징

1)스트림은 데이터 소스를 변경하지 않습니다.

원본 데이터에 변경을 가하지 않습니다.

중간 연산한 결과를 별도로 저장할 수 있습니다.

 

2)스트림은 일회용

=>한 번 읽고 나면 재사용이 안되므로 다시 만들어서 사용

 

3)스트림은 작업을 내부적으로 반복해서 처리

=>반복문이 내부에 숨어있는 것 입니다.

=>단순하게 스트림을 사용한다고 해서 실행 속도가 빨라지는 것은 아닙니다.

 

4)다양한 기본 연산 제공

=>중간 처리 (매핑 - 변환, 필터링, 정렬) 연산과 최종 처리(반복 ,카운팅, 평균,합계)연산을 제공

 

5)스트림의 연산은 지연된 연산

=>중간 연산이 중간에 수행되는 것이 아니고 최종 연산을 수행하기 전에 수행

 

6)Fork & join을 이용해서 병렬처리를 구현하는 것보다 휠씬 쉽게 병렬 처리를 구현

 

 

3.Stream생성

1)Collection(List, Set)을 가지고 생성

 

 

2)배열을 가지고 생성

Arrays.stream(배열)

 

3)디렉토리 경로를 가지고 생성

Stream<Path> Files.list(Path path): path에 있는 모든 디렉토리 및 파일에 접근할 수 있는 스트림

 

4) 텍스트 파일의 내용을 줄 단위로 접근

Stream<String> BufferedReader.lines()

 

5)랜덤한 스트림

Random.doubles(), ints(), longs()를 이용

 

6)배열을 이용해서 스트림을 생성하고 모든 데이터 출력

 

똑같은 것을 여러개 할 수있다. 요즘에는 메모리를 많이 사용하지만 속도가 빠르다.

CollectionUse.java

//현재 디렉토리에 있는 pl.csv파일의 내용을 읽어서 문자열 배열 만들기

                       try {

                                  //파일을 읽을 수 있는 스트림을 생성

                                  BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("C:\\project\\JAVA_PROJECT\\java\\src\\java\\pl.csv")));

                                  //데이터 한 줄 읽기

                                  String line = br.readLine();

                                  //, 단위로 분할해서 문자열 배열로 만들기

                                  String [] ar  = line.split(",");

                                  Stream<String> stream1 = Arrays.stream(ar);

                                  //출력

                                  stream1.forEach(System.out::println);//System.out::println메소드 이름 을 할 수 있는 것

                                  br.close();

                       } catch (Exception e) {

                                  System.out.println("파일 내용 읽기 실패: "+e.getMessage());

                       }

 

텍스트 파일 데이터 읽어올때 발생하는 문제

 

123

처음에 1을 읽는다.

su : 0 su * 10 +('1' - '0')  => 1

su  su * 10 + ('2'-'0') =>12

계산기를 이렇게 바꾼다. 그래서 숫자를 문자로 해서 한다. 숫자 입력이 안되면 계산이 안된다.

0-> 48이다.

//현재 디렉토리에 있는 pl.csv파일의 내용을 읽어서 문자열 배열 만들기

               try {

                      //파일을 읽을 있는 스트림을 생성

                      BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("C:\\project\\JAVA_PROJECT\\java\\src\\java\\pl.csv")));

                      //데이터 읽기

                      String line = br.readLine();

                      //, 단위로 분할해서 문자열 배열로 만들기

                      String [] ar  = line.split(",");

                      Stream<String> stream1 = Arrays.stream(ar);

                      //출력

               stream1.forEach(System.out::println);//System.out::println메소드 이름 있는

                      br.close();

                     

                      //ar[3]에는 12345건이라는 문자열에 존재 - 12345라는 정수로 변환

                      int su  =0;

                      for(i = 0; i < ar[3].length(); i++) {

                             //한글 자씩 가져오기

                             char ch = ar[3].charAt(i);

                             // 숫자인지 확인

                             if(ch >= '0' && ch <= '9') {

                                    su = su * 10 +(ch - '0');

                             }else {

                                    break;//, 콤마 있을 빼기

                             }

                      }

                      System.out.println(su);

               } catch (Exception e) {

                      System.out.println("파일 내용 읽기 실패: "+e.getMessage());

               }

4.스트림의 중간 연산(Reduction)

map reduce비슷한 것이다.

=>데이터를  변환, 필터링, 정렬, 그룹화 하는 것 등이 있습니다.

1)distinct():중복 제거 - 요소의 equals 메소드를 가지고 비교해서 equals   true를 리턴할 경우를 중복으로 간주

2)Filter(): 조건에 맞는 데이터만 필터링

=>하나의 매개변수를 받아서 boolean을 리턴하는 메소드를 대입

=>스트림의 모든 데이터를 매개변수에 대입해서 true리턴한 데이터만 골라서 Stream으로 리턴

 

3)map(); 데이터를 변환

=>하나의 매개변수를 받아서 리턴을 해주는 메소드를 대입

하나받아서 바꿔야 하나깐 리턴해야 한다.

 

4)sorted():데이터를 정렬

=>매개변수가 없으면 Comparable 인터페이스의 compareTo메소드를 이용해서 비교한 후 오름차순 정렬행

=>매개변수로 Comparator인터페이스를 구현한 객체나 2개의 매개변수를 받아서 정수를 리턴하는 람다식을 대입하면 대입된 객체나 람다식에 의해서 오름차순 정렬

앞의 데이터가 크다라고 할때는 양수를 리턴하면 되고 같으면 0 뒤의 데이터가 클 때는 음수를 리턴

 

5)peek(): 모든 데이터를 순회하면서 작업을 수행

=>매개변수로 1개의 데이터를 설정하고 return 이 없는 메소드를 대입

 

5.중간 연산 실습

1) 변호, 이름 , 성별 ,나이 ,점수를 소유한 dto(Data Transfer Object -VO)크래스르 생성

Student.java

private int num;

       private String name;

       private String gender;

       private int age;

       private int score;

      

       //데이터가 없는 경웨 사용할 생성자

       public Student() {

               super();

       }

      

       //데이터가 제공되는 경웨 사용할 생성자 - 테스트 데이터를 빠르게 입력해서 확인하기 위해서 생성

       public Student(int num, String name, String gender, int age, int score) {

               super();

               this.num = num;

               this.name = name;

               this.gender = gender;

               this.age = age;

               this.score = score;

       }

      

       //접근자 메소드

       public int getNum() {

               return num;

       }

       public void setNum(int num) {

               this.num = num;

       }

       public String getName() {

               return name;

       }

       public void setName(String name) {

               this.name = name;

       }

       public String getGender() {

               return gender;

       }

       public void setGender(String gender) {

               this.gender = gender;

       }

       public int getAge() {

               return age;

       }

       public void setAge(int age) {

               this.age = age;

       }

       public int getScore() {

               return score;

       }

       public void setScore(int score) {

               this.score = score;

       }

      

       //데이터를 빠르게 확인하기 위한 메소드

       @Override

       public String toString() {

               return "Student [num=" + num + ", name=" + name + ", gender=" + gender + ", age=" + age + ", score=" + score

                             + "]";

       }

 

2)main메소드를 소유한 main메소드 생성

stream사용하고있을경우오류가난다 .

ReductionMain.java

c++은 예약어가 거의 없다.

public static void main(String[] args) {

               // 샘플 데이터 작성

               Student student1 = new Student(1,"강좌진","",28, 98);

               Student student2 = new Student(2,"유관순","",19, 89);

               Student student3 = new Student(3,"김구","",38, 99);

               Student student4 = new Student(4,"안중근","",29, 100);

               Student student5 = new Student(5,"남자현","",25,97);

              

               ArrayList<Student> list = new ArrayList<Student>();

               list.add(student1);

               list.add(student2);

               list.add(student3);

               list.add(student4);

               list.add(student5);

              

               //distinct- 중복을 제거해주는 메소드

               String[] ar = {"데니스 리치히","귀도 로섬","제임스 고스링","데니스 리치히"};

               Stream<String> arStream =Arrays.stream(ar);

              arStream.distinct().forEach(System.out::println);

              

               //filter 원하는 데이터만 골라내는 것이다.

               //fileter - 조건에 맞는 데이터만 추출하는 중간 연산

               //fileter에는 매개변수 1개를 갖고 boolean 리턴하는 람다식을 대입

               Stream<Student> stream = list.stream();

               //score 90보다 데이터만 추출해서 출력

               //stream.filter((student)->{return student.getScore()>= 90;}).forEach(System.out::println);

               //gender 여인 데이터만 추출해서 출력

               stream.filter((student)->{return student.getGender().equals("");}).forEach(System.out::println);

               //filter 한번에 한번 밖에 안된다.

               //boolean 리턴한면 된다.

              

              

               //변환을 하는 것이고

               //return 해줘야 한다.

               //map() 데이터를 변환할 사용하는 메소드

               // 숫자 -> 문자열 , 문자열 -> 숫자 , 날짜 -> 문자열 , 인스턴스 -> 기본형

               //Student score 변환

               System.out.println();

               stream = list.stream();//스트림은 사용하면 소멸되기 때문에 다시 사용할 떄는 새로 생성해야 합니다.

               //어떤 메소드를 수행만 하는 경우에는 클래스이름 :: 메소드이름만 입력해도 됩니다.

               //stream.mapToInt((student)->{return student.getScore();}).forEach(System.out::println);

               //함수형 프로그래밍

       stream.mapToInt(Student::getScore).forEach(System.out::println);

               //합계 구하기 편하다. 점수만 출력 된다.

              

               System.out.println();

               //정렬 sorted

               //데이터 정렬은 sorted메소들 이용

               // 요소가 크기 비교가 가능하다면 바로 오름차순 정렬을 수행

               //요소가 크기비교가 불가능하다면 크기 비교가 가능한 메소드를 대입해야 합니다.

               //크기비교가 가능한 데이터는 속성을 하나만 가진 데이터들입니다.

               //기본 자료형, 문자열 ,날짜 정도가 하나의 데이터만을 가진 자료형입니다.

               //항상 예외가 되는 언어가 있다. c언어이다.

               //c언어는 stack .linkedList 만들어서 해야 한다. doubleLinekedList 3000라인 작성하면 된다.

               arStream = Arrays.stream(ar);

               //string 크기 비교가 가능하기 때문에 바로 오름차순 정렬

               arStream.sorted().forEach(System.out::println);

         //arStream.distinct().sorted().forEach(System.out::println);

              

               System.out.println();

               stream = list.stream();

               //student 여러개의 항목을 소유하고 있기 때문에 어떤 항목으로 크기 비료를 알지 못하기 때문에 예외가 발생

               //stream.sorted().forEach(System.out::println);

              

               //크기 비교하는 메소드를 만들어서 정렬

               //크기 비교를 때는 2개의 매개변수를 가지고 정수를 리턴하는 메소드를 만들면 됩니다.

               //양수를 리턴하면 앞에것이 크다고 간주하고 0이면 같다고 음수이며 뒤의 데이터가 크다고 간주

               // 123 < 65 잘못 될수 있다.

               //점수의 오름차순

              

               //숫자 데이터를 이용해서 비교하는 경우 - 오름차순

               //stream.sorted((a,b)->{return a.getScore()- b.getScore();}).forEach(System.out::println);

              

               //문자열인 경우는 compareTo 이용 - 순서를 변경하면 내림차순

               stream.sorted((a,b)->{return b.getName().compareTo(a.getName());}).forEach(System.out::println);

       }

 

3)중간 연산 메소드는 여러 연속해서 사용 가능

 

 

6. 최종 연산 메소드

=>마지막에 한번만 사용가능한 메소드

(여러번 사용할 수 가 없다.한번만 사용하는 것이다.)

 

1)매칭관 관련된 메소드

=>모두 boolean을 리턴

allMatch()

anyMatch()

noneMatch()

=>3가지 메소드 모두 filter와 동일한 메소드를 매개변수로 받아서 전부 true또는 하나 이상 true또는 모두 false로 리턴하는지 알려지는 메소드

 

2)데이터 개수

long count()

 

3)데이터 합계

int, long ,double sum()

 

4)평균

OptionalDouble average()

=>Optionalnulll을 저장할 수 있는 자료형을 최근에는 optional이라고 합니다.

평균은 null이 있을수 있다.그래서 데이터 확인하고 해야 한다.

 

5)최대값 및 최소값

OptionalXXX max()

OptionalXXX min()

 

6)누적 연산

OptionalXXX reduce()

현재 파이썬에서 동작하면 오류 난다. 버전 확인해야 한다.

 

7)모든 요소에게 메소드 수행

forEach()

 

8) 결과를 저장

R collect()

 

자바도 ,딥러닝 가능하는데 만들어진 것이 적어서 python등으로 한다.

 

7.Optional

=>어떤 클래스의 객체를 감싸는 클래스

=>null이 리턴될 가능성이 있을 때 이 데이터를 바로 사용하면 예외가 발생할 가능성이 존재하기 때문에 null여부를 확인하고 사용해야 합니다.

자바는 Optional이라는 자료형을 이용해서 null인 경우 다른 데이터로 치환할 수 있는 메소드를 제공합니다.

 

T get(): 값을 가져오고 null이면 예외 발생

T orElse(T 기본값 ): 결과가 null이면 기본값을 리턴

boolean isPresent(): null이면 false그렇지 않으면 true리턴

 

 

=>변형으로는 OptionInt, OptionalLong, OptionalDouble

LastMain.java

public static void main(String[] args) {

               //문자열 배열을 이용해서 스트림을 생성

               String [] ar = {"Python","Java","Closure","Scala","Kotlin","Swift","C#","C&C++","JavaScript"};

               Stream<String> asStream = Arrays.stream(ar);

              

               //match - 판별하는

               //배열의 모든 데이터가 3글자 이상인지 확인  - C# 때문에 false

               //anyMatch ture -any 하나라도 만족하면 true

               //noneMathc false -하나도 만족하는게 없으면 true

               boolean r = asStream.allMatch((language)->{return language.length() >3;});

               System.out.println(r);

               System.out.println();

              

               //집계 함수를 사용

               //글자가 5 이상이인 데이터의 개수를 파악

               // 샘플 데이터 작성

               Student student1 = new Student(1,"강좌진","",28, 98);

               Student student2 = new Student(2,"유관순","",19, 89);

               Student student3 = new Student(3,"김구","",38, 99);

               Student student4 = new Student(4,"안중근","",29, 100);

               Student student5 = new Student(5,"남자현","",25,97);

              

               ArrayList<Student> list = new ArrayList<Student>();

               list.add(student1);

               list.add(student2);

               list.add(student3);

               list.add(student4);

               list.add(student5);

              

               Stream<Student> stream =list.stream();

               //점수의 합계 구하기

               int tot = stream.mapToInt(Student::getScore).sum();

               System.out.println("score 합계:" +tot);

               System.out.println();

              

               //남자 나이 합계

               stream =list.stream();

               tot = stream.filter((student)->{return student.getGender().equals("");}).mapToInt(Student::getAge).sum();

               System.out.println("남자 나이 합계: " +tot);

               System.out.println();

              

               stream =list.stream();

               long cnt = stream.filter((student)->{return student.getGender().equals("");}).mapToInt(Student::getAge).count();

               System.out.println("데이터 개수: " +cnt);

               System.out.println();

              

               //gender 데이터의 score 평균

               //optional 기존 자료형의 데이터를 warping 자료형

               stream =list.stream();

               OptionalDouble avg = stream.filter((student)->{return student.getGender().equals("");}).mapToInt(Student::getScore).average();

               //getAsDouble 가져오면 결과가 null 예외가 발생

               //orElse 에서 기본값을 설정하면 결과가 null 기본값을 리턴

               System.out.println("여자 score평균" +avg.orElse(0));

               System.out.println();

              

               //max min comparator.comparing자료형(비교형 데이터의 메소드) 대입하면 Optional<제너릭>으로 결과를 리턴

               //Score 최대값

               stream =list.stream();

               Optional<Student> re =stream.filter((student)->{return student.getGender().equals("");}).max(Comparator.comparingInt(Student::getScore));

               System.out.println("score 최대값:" +re.get());

              

               stream =list.stream();

               Optional<Student> result =stream.filter((student)->{return student.getGender().equals("");}).min(Comparator.comparingInt(Student::getScore));

               System.out.println("남자의 최저 점수:" +result.get());

       }

9.collect

=>collect를 이용해서 중간 결과를 ListSet으로 리턴받고자 하면 이 때는 Collect에 매개변수로 Collectors.toList또는 toSet을 대입하면 됩니다.

 

 

=>결과를 Map으로 저장하고자 하면 Collector.toMap(키로 사용할 데이터를 리턴해주는 메소드, 매개변수 1개를 가지고 리턴하는 메소드)를 대입하면 됩니다.

앞의 메소드 결과로 key를 만들고 뒤의 메소드 결과를 value를 만듭니다.

 

=>toList()대신에 counting()을 설정하면 long타입의 데이터 개수를 리턴

=>summingIntsummingDouble메소드에 mapToIntmapToDouble을 대입하면 합계를 리턴

=>averagingInt averagingDouble메소드에 mapToIntmapToDouble을 대입하면 평균을 리턴

=>maxByminBy메소드에 비교하는 메소드를 대입하면 최대값이나 최소값을 리턴

최대나 최소는 실제 값이 아니고 최대값이나 최소값을 가진 데이터를 리턴

CollectorMain.java

public static void main(String[] args) {

               // 집계 함수를 사용

               // 글자가 5 이상이인 데이터의 개수를 파악

               // 샘플 데이터 작성

               Student student1 = new Student(1, "강좌진", "", 28, 98);

               Student student2 = new Student(2, "유관순", "", 19, 89);

               Student student3 = new Student(3, "김구", "", 38, 99);

               Student student4 = new Student(4, "안중근", "", 29, 100);

               Student student5 = new Student(5, "남자현", "", 25, 97);

 

               ArrayList<Student> list = new ArrayList<Student>();

               list.add(student1);

               list.add(student2);

               list.add(student3);

               list.add(student4);

               list.add(student5);

 

               Stream<Student> stream = list.stream();

               //gender 값이 남인 데이터만 가지고 List 생성

               List<Student> manList= stream.filter((student)->{return student.getGender().equals("");}).collect(Collectors.toList());

               for(Student temp:manList) {

                      System.out.println(temp);

               }

              

               //gender 값이 여인 데이터를 가지고 name key 하고 전체를 value 하는 mAP 생성

               stream = list.stream();

               Map<String,Student> womanMap = stream.filter((student)->{return student.getGender().equals("");})

                             .collect(Collectors.toMap(Student::getName, (student)->{return student;}));

               //Map 모든 데이터 출력

               Set<String> keys = womanMap.keySet();

               for(String key : keys) {

                      System.out.println(key+" : " + womanMap.get(key));

               }

              

               //결과를 저장하는 것이 collector이다.

              

               System.out.println();

               stream = list.stream();

               long count = stream.filter((student) ->{return student.getGender().equals("");}).collect(Collectors.counting());

               System.out.println("여자 인원수 :" +count);

       }

 

10.grouping이 가능

=>collect 메소드에 Collectors.groupingBy()를 이용해서 그룹화가 가능

어떤 메소드의 결과로 그룹화 할 것인지를 설정하면 됩니다.

=>두번째 매개변수로 구하고자 하는 집계함수를 설정하면 그룹화 한 후 집계도 가능

counting(),averagingDouble(),maxBy(),minBy(), summingInt(),summingLong(), summingDouble()등으로 합계도 구할 수 있음

=>결과는 그룹화 하는 함수의 결과를 key로 해서 Map으로 리턴합니다.

=>데이터들만 규격화가 잘 되어 있다면 데이터베이스의 sql을 사용하는 것처럼 사용이 가능

 

11. 그룹화 실습

GroupingMain.java

public static void main(String[] args) {

               // 집계 함수를 사용

               // 글자가 5 이상이인 데이터의 개수를 파악

               // 샘플 데이터 작성

               Student student1 = new Student(1, "강좌진", "", 28, 98);

               Student student2 = new Student(2, "유관순", "", 19, 89);

               Student student3 = new Student(3, "김구", "", 38, 99);

               Student student4 = new Student(4, "안중근", "", 29, 100);

               Student student5 = new Student(5, "남자현", "", 25, 97);

 

               ArrayList<Student> list = new ArrayList<Student>();

               list.add(student1);

               list.add(student2);

               list.add(student3);

               list.add(student4);

               list.add(student5);

              

               //List Stream으로 변환

               Stream<Student> stream = list.stream();

              

               //stream으로 그룹화

               Map<String,List<Student>> map =stream.collect(Collectors.groupingBy(Student::getGender));

               Set<String> keys = map.keySet();

               for(String key:keys) {

                      System.out.println(key +":" + map.get(key));

               }

              

               System.out.println();

              

               //스르팀은 한번 소모하면 소멸됩니다.

               //새로운 작업을 수행할 만다 스트림은 다시 생성

               stream = list.stream();

               //gender별로 그룹화   score 평균 구하기

               Map<String,Double> result = stream.collect(Collectors.groupingBy(Student::getGender,Collectors.averagingDouble(Student::getScore)));

               keys = result.keySet();

               for(String key:keys) {

                      System.out.println(key +":" + result.get(key));

               }

              

               System.out.println();

              

              

               stream = list.stream();

               //그룹화는 존재하는 메소드를 이용해도 되지만 람다로 직접 만들어도 됩니다.

               //하나의 매개벼수(스트림의 제너리) 받아서 데이터를 리턴하는 람다 식이면 됩니다.

               Map<String,Integer> result1 =

                             stream.collect(Collectors.groupingBy((student) ->{return student.getName();},

                                           Collectors.summingInt(Student::getScore)));

               keys = result1.keySet();

               for(String key:keys) {

                      System.out.println(key +":" + result1.get(key));

               }

              

               System.out.println();

              

               //성별 최대인 데이터를 추출

               stream = list.stream();

               Map<String,Optional<Student>> result2 =

                            stream.collect(Collectors.groupingBy(Student::getGender,

                                    Collectors.maxBy(Comparator.comparingInt(Student::getScore))));

               keys = result2.keySet();

               //Optional 출력할 Optional 함께 출력하기 때문에 이를 벗겨내기 위해서는 get()이나 orElse() 이용

               for(String key:keys) {

                      System.out.println(key +":" + result2.get(key).get());

               }

              

       }

 

12.병렬 스트림

=>java 1.8 이전 까지는 데이터의 모임에 병렬처리를 할려면 fork&join API 사용

API사용이 어려움

 

=>Stream api에서는 병렬 스트림을 만들기만 하면 자동으로 병렬 처리를 수행

스트림을 만들 stream()메소드 대신에 parallelStream()메소드를 호출하면 병렬 스트림이 됩니다.

Stream API 데이터 병렬성으로 구현

데이터들을 작은 데이터로 분할해서 작업하는 형태

 

=>작업의 병렬성

여러 작업의 요청이 작업들을 개별 스레드로 만들어서 병렬 처리하는 방식으로 서버가 대표적인 작업의 병렬성을 구현한 :

ParallelMain.java

// 문자열을 매개변수로 받아서 2 후에 출력하는 메소드

       public static void work(String str) {

               try {

                      Thread.sleep(2000);

                      System.out.println(str);

               } catch (InterruptedException e) {

                      // TODO Auto-generated catch block

                      e.printStackTrace();

               }

       }

 

       public static void main(String[] args) {

               String[] ar = { "", "", "", "", "" };

               List<String> list = Arrays.asList(ar);

 

               Stream<String> arStream = list.stream();

               // 일반 스트림을 생성해서 ar work 수행 - 10 정도 소요

               long start = System.currentTimeMillis();

 

               arStream.forEach((data) -> {

                      work(data);

               });

 

               long end = System.currentTimeMillis();

               System.out.println("순차 처리 :" + (end - start));

              

               //병렬 스트림을 생성해서 work 수행 -cpu 코더 개수에 따라 걸리는 시간이 다름

               //5 이상이여서 5개가 한번에 돈다.

               //코어가 5 이상이면 번에 수행하므로 2 =정도 소모

               //데이터 모임을 가지고 작업을 수행하는 경우 다른 영향을 전혀 받지 않고 수행되는 경우에는 병렬처리르 하는 것이 시간으로 이득

               //앞의 데이터의 연산결과를 가지고 다음 작업을 수행하는 작업은 병렬처리를 하는 것이 곤란

               //필터링 같은 경우는 병렬처리를 수행하기 좋은 작업 - 이러한 처리 방식을 Map - Reduce라고 합니다.

               //각각의 데이터에서 작업을 처리한 결과를 모아서 리턴

               Stream<String> paralleStream = list.parallelStream();

               // 일반 스트림을 생성해서 ar work 수행 - 10 정도 소요

               start = System.currentTimeMillis();

 

               paralleStream.forEach((data) -> {

                      work(data);

               });

 

               end = System.currentTimeMillis();

               System.out.println("순차 처리 :" + (end - start));

       }

 

 

 

**최근 언어의 자료형 구분

예전에는 value형과 reference형으로 구분(이것이 c언어일 경우)

수정 가능 여부에 따른 구분(mutableimmutable)

scalavector구분(데이터 개수를 구분)

null저장 가능 여부(OptionalnonOptional)(null을 저장할 수 있는 가 없는것인가)

객체지향언어에서  python에서 등에서는

a.b() ->이것하지 말라고 한다. .점이 있음녀 참조형이라고 한다. 데이터의 참조를 하고 있다가 찾아간다.

a null이고 None  nil => NullPointerException

그래서 참조형으로 할때 이렇게 쓰지 말라고 한다.

java에서는

if( a ! = null){ //null인지 확인한다.

           a.b();

}

참조형은 항상 null인지 물어봐야 한다.

optional : null저장 가능

NonOptional :null저장 못함

var a = new A();->NonOptional일경우 null체크 할 필요없다.

나누기 일 경우 문제가 생긴다. infinite등 문제 가 생긴다.

 

legacy - 전통적인 ,예전에 방식

 

변수를 선언할 때 뒤에 !를 붙이면 null저장가능

String temp; //에러 !표가 없기 때문에 그래서 값을 줘야 한다. => String temp ="Hello";//초기관을 설정하지 않으면 에러

String n! ;//초기값을 설정하지 않으면 null - 이 데이터는 사용할 때 null여부를 확인해야 합니다.

 

 

UML

시스템에 대한 지식을 찾고 표현하기 위한 언어

시스템을 개발하기 위한 탐구 도구

비주얼 모델링 도구

근거가 잘 정리된 가이드 라인

분석, 설계 작업의 마일스톤

실용적 표준

비주얼 프로그래밍 언어나 데이터베이스 표현도구 아님

개발 프로세스나 품질 보증 방안이 아님

 

가이드 라인이 있어서 작업할 때 편해진다.

base drived

파생 클래스

static은 밑줄을 건다. eclipse는 기울러져 있다.

 

보통 자료형을 쓰고 이름을 쓰는데

uml에서는 반대이다.

 

class A{

           String B ;//외부에서 받아서 사용했다.

}

List<String> ->string의 집한으로 이것이 aggregation이다.

 

Frame = new Frame():

Panel = new Panel();

 

Button = new Button();

button은 단독으로 만들 수 없다. buttondpanel이나 frame으로 해야 한다.

panelframe없으면 안된다.

frame아니면 보여질 수 없다.

 

Layout : container

widget 단독으로 사용불가

 

 

class의 상속 , interface..이다.

RectangularShape shape라는 interface 구현 한 것이다.

 

 

studentstudentiD CARD를 한계 가지고 있다.

대각선 적으로 바라봐야 한다.

 

분석  -> UML ->클래스 설계-> 구현

UML은 안하고 클래스 그냥 한다.

나중에는

분석  -> 클래스 설계-> 구현

설계 정보가 없다. 유지보수 할 경우 코드를 봐야 한다.

최근에는 역공학을 많이 사용한다. 나중에 하는 것이다.

eclipse에서 python이 가능하다.

eclipsevs code 조금 다르다.

vs code editor

eclipseid

python설치하고 설정해야 한다.

설치 다되면 ECLIPSE RESTART해야 된다.

그림파일이 만들어 질려면 체크해야 한다.

소스 코드 내부는 잘 안보고

상속이나 디자인 패턴이 잘 되여있는 지만 확인한다.

 

 

**디자인 패턴

Design Pattern

=>인스턴스의 사용용도에 따라 클래스의 모양을 만드는 것

GoF 디자인 패턴

runtime class의 생성자가 없다가 아니고 생성자가 안보인다. private로 만들어서 안보인다.

실글 패턴

보는 순간 실글 톤이고 인스턴스를 하나밖에 안된다.

날자를 설정할 경우 두개가 동시에 진행하면 안되서 하나가지고 순차적으로 해야 한다

entry point는 하나인게 좋다 그래야 제어가 쉽다.

1. 생성에 관련된 패턴

1)Singelton Pattern

=>인스턴스를 1개만 생성해서 사용하는 패턴

=>관리자 클래스(Controller)나 공유 데이터를 소유한 클래스 또는 서버에서 클라이언트의 요청을 처리하는 클래스 등에 적용

=>Java Server를 만들기 위한 FrameworkSpring은 기본적으로 클래스를 디자인해서 인스턴스를 만들면 Singelton Patternd으로 사용

 

 

python바이블인가 ? 이런것 봐야 한다.

jump to python

 

mainstatic으로 반든것이다 아무데에서도 부른 것이다.

메소드는 아무데에서나 부를 목적이고

변수는 하나만 만들어서 공유할 목적이다.

 

 

 

 

반응형

'Study > Java' 카테고리의 다른 글

java-19  (0) 2020.10.10
java-18  (0) 2020.10.10
java-16  (0) 2020.10.10
java-15  (1) 2020.10.05
java-14  (0) 2020.10.04
반응형

HTML

1.     Tag: 브라우저가 해석해서 랜더링하기 위한 명령어

A.     하나의 페이지에서 중복될 수 있다.

2.     class: 동일한 디자인을 적용하기 위해서 태그에 적용하는 속성

A.     하나의 페이지에서 중복될 수 있다.

3.     id: 자바스크립트에서 하나의 태그를 구분하기 위해서 적용하는 속성

A.     하나의 페이지에서는 절대로 중복될 수 없다.

4.     name: 서버에서 처리하기 위해 붙이는 이름

A.     중복될 수 있다.

5.     attribute: 태그 내에서 설정하는 옵션으로 key – value 형태로 설정

A.     <태그 옵션이름 = ‘’> : 스크래핑을 할 때는 a 태그의 href 속성이 가장 중요

6.     selector: 별도로 설정하는 것이 아니고 css에서 태그들을 선택하기 위해 만든 문법

A.     태그

B.     .클래스이름

C.     #id

7.     xpath: 별도로 설정하는 것이 아니고 브라우저가 태그의 경로를 나타내기 위해서 사용하는 문법

A.     태그의 경로를 구분해서 나타내기 때문에 중복될 수 없다.

 

 

Java가 실행을 할 때 클래스를 찾는 방법

1.     자신의 애플리케이션에서 찾는다.

2.     1번에서 없으면 jvm이 제공하는 라이브러리에서 찾는다.

3.     자바 실행을 할 때 자신의 build path에 추가된 라이브러리를 jvm에 로드 한다.

4.     2번에서도 없으면 build path에 추가된 라이브러리에서 찾는다.

A.     Build path에 추가될 때는 링크가 설정된다.

B.     외부 라이브러리를 사용할 때는 프로젝트에서 포함해서 배포 하던가 다운로드 링크를 같이 제공해야 한다.

 

 

HTML Parsing

×         Java에서는 PythonBeautifulSoup 과 유사한 JSoup 이라는 라이브러리를 이용

1.     https://www.naver.com에서 원하는 항목의 값 가져오기

A.     프로젝트의 build pathjsoup 라이브러리를 추가

                       i.        www.mvnrepository.com 에서 jsoup을 검색해서 다운로드

                      ii.        다운로드 받은 파일을 프로젝트에 복사

                     iii.        복사한 파일을 선택해서 마우스 오른쪽을 클릭하고 [Build Path] – [Add To Build Path]를 실행

B.     코드를 작성

 

       public static void main(String[] args) {

               //필요한 HTML 다운로드 : https://www.naver.com에서 다운로드

               String html = null;

               try {

                      //다운로드 받을 URL 생성

                      //URL 한글이 있으면 URLEncoder.encode 이용해서 인코딩을 해야 한다.

                      String addr = "https://www.naver.com";

                      URL url = new URL(addr);

                     

                      //연결

                      HttpURLConnection con = (HttpURLConnection)url.openConnection();

                      con.setConnectTimeout(30000);

                      con.setUseCaches(false);

                     

                      //데이터를 다운로드

                      StringBuilder sb = new StringBuilder();

                      BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));

                      while(true) {

                             String line = br.readLine();

                             if(line == null) {

                                    break;

                             }

                             sb.append(line + "\n");

                      }

                     

                     

                      //사용한 스트림 정리

                      br.close();

                      con.disconnect();

                     

                      //데이터 확인

                      html = sb.toString();

                      //System.out.println(html);

                     

                     

                     

               }catch(Exception e) {

                      System.out.println("다운로드 예외:" + e.getMessage());

                      e.printStackTrace();

               }

              

               if(html == null) {

                      System.out.println("다운로드 받은 문자열이 없습니다.");

                      return;

               }

              

               //HTML 파싱을 해서 원하는 자료구조를 만들기

               try {

                      //문자열을 메모리에 DOM(Document Object Model)으로 펼치기

                      Document document = Jsoup.parse(html);

                     

                     

                      //span 태그 가져오기 - 태그는 중복될 있으므로 여러 리턴

              

                      /*

                      Elements span = document.getElementsByTag("span");

                      //가져온 데이터를 순회하면서 출력

                      for(int i=0 ; i < span.size() ; i+=1) {

                             Element element = span.get(i);

                             System.out.println(element.text());

                      }

                     

                     

                     

                      //클래스 이름을 이용해서 찾아오기

                      Elements span = document.getElementsByClass("an_txt");

                      //가져온 데이터를 순회하면서 출력

                      for(int i=0 ; i < span.size() ; i+=1) {

                             Element element = span.get(i);

                             System.out.println(element.text());

                      }

                      */

                     

                      //선택자 이용

                      Elements span = document.select("#PM_ID_serviceNavi > li:nth-child(9) > a > span.an_txt");

                      //가져온 데이터를 순회하면서 출력

                      for(int i=0 ; i < span.size() ; i+=1) {

                             Element element = span.get(i);

                             System.out.println(element.text());

                      }

                     

                     

               }catch(Exception e) {

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

                      e.printStackTrace();

               }

       }

 

2.     한겨레 신문사에서 검색을 해서 실제 기사를 전부 읽어서 파일에 저장하기

A.     검색을 이용해서 데이터를 읽어올 때는 주소 패턴을 정확하게 이해

 

 

keyword가 검색어

datefrom 이 시작날짜 dateto가 종료날짜

pageseq 가 페이지 번호 – 0부터 시작

 

 

B.     기사 개수를 읽어오는 것이 먼저반복문을 언제까지 돌려야 하는지 설정

C.     기사 검색이나 게시판, sns 검색의 경우 검색의 결과로 나온 것은 대부분 제목과 본문의 링크이다.

                       i.        검색의 결과에서 링크를 전부 찾아 실제 기사나 본문의 내용을 읽어와야 한다.

   public static void main(String[] args) {

           //한겨레 신문사 페이지에서 코로나 검색된 기사 내용을 전부 파일에 저장하기

          

           //1. 코로나로 검색된 기사 개수 파악하기

           //기사 개수를 저장할 변수

           int cnt = 0;

           try {

                  //한글로 검색어를 인코딩

                  String keyword = URLEncoder.encode("코로나", "utf-8");

                  //한겨레 신문사 뉴스 검색 URL 만들기

                  String addr = "http://search.hani.co.kr/Search?command=query&keyword="+keyword+"&media=news&submedia=&sort=d&period=all&datefrom=2000.01.01&dateto=2020.01.28&pageseq=0";

                  URL url = new URL(addr);

                  //연결 옵션과 연결

                  HttpURLConnection con = (HttpURLConnection)url.openConnection();

                  con.setConnectTimeout(20000);

                  con.setUseCaches(false);

                 

                  //문자열을 전부 읽어서 sb 저장하기

                  StringBuilder sb = new StringBuilder();

                  BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));

                  while(true) {

                         String line = br.readLine();

                         if(line == null) {

                                 break;

                         }

                         sb.append(line + "\n");

                  }

                 

                  String html = sb.toString();

                  br.close();

                  con.disconnect();

                  //데이터 확인 - 확인되면 주석 처리

                  //System.out.println(html);

                 

                 

                 

                 

                  //html DOM으로 펼피기

                  Document document = Jsoup.parse(html);

                  //태그이름으로 찾기

                  //Elements spans = document.getElementsByTag("span");

                  //클래스 이름으로 찾기

                  //Elements spans = document.getElementsByClass("total");

                  //System.out.println(spans);

                  //선택자를 이용해서 찾기

                  Elements spans = document.select("#contents > div.search-result-section.first-child > div > span");

                 

                  String temp = spans.get(0).text();

                 

                  //240건이라고 temp 저장 240 추출해서 정수로 변환해서 cnt 저장

                  String [] ar = temp.split(" ");

                  cnt = Integer.parseInt(ar[0]);

                  //System.out.println(cnt);

                 

           }catch(Exception e) {

                  System.out.println("기사 개수 파악 예외:" + e.getMessage());

                  e.printStackTrace();

           }

          

          

          

           //검색된 데이터의 링크를 전부 찾아서 list 삽입

           ArrayList <String> list = new ArrayList<String>();

           try {

                  //페이지 개수 구하기

                  int pagesu = cnt / 10;

                  if(pagesu % 10 != 0) {

                         pagesu+=1;

                  }

                 

                  //페이지 단위로 순회

                  for(int i=0 ; i<pagesu ; i+=1) {

                         //한글로 검색어를 인코딩

                         String keyword = URLEncoder.encode("코로나", "utf-8");

                         //한겨레 신문사 뉴스 검색 URL 만들기

                         String addr = "http://search.hani.co.kr/Search?command=query&keyword="+keyword+"&media=news&submedia=&sort=d&period=all&datefrom=2000.01.01&dateto=2020.01.28&pageseq="+i;

                         URL url = new URL(addr);

 

                        

                         //연결 객체 만들기

                         HttpURLConnection con = (HttpURLConnection)url.openConnection();

                         con.setConnectTimeout(10000);

                         con.setUseCaches(false);

                        

                        

                         //특정 페이지의 데이터를 읽지 못하더라도 다음 페이지의 데이터를 읽기 위해서 박복문 안에 예외처리 문장 삽입

                         try {

                                 StringBuilder sb = new StringBuilder();

                                 BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));

                                 while(true) {

                                        String line = br.readLine();

                                        if(line == null) {

                                               break;

                                        }

                                     sb.append(line+"\n");

                                 }

                                 String html = sb.toString();

                                 br.close();

                                 con.disconnect();

                                

                                 Document document = Jsoup.parse(html);

                                 Elements links = document.select("dl > dt > a");

                                 for(int j=0 ; j<links.size() ; j+=1) {

                                        //a 태그 안에 있는 문자열을 가져오기

                                     //System.out.println(links.get(j).text());

                                       

                                        //a 태그의 href 속성의 가져오기

                                     //System.out.println(links.get(j).attr("href"));

                                     list.add(links.get(j).attr("href"));

                                 }

                             //System.out.println(list.size());

                         }catch(Exception e){

                                 System.out.println("링크 수집 예외:" + e.getMessage());

                                 e.printStackTrace();

                         }

                        

                         //반복문 안에 try catch 하는 경우는 권장하지않지만 해야 하는 경우도 있다.

                  }

           }catch(Exception e){

                  System.out.println("링크 수집 예외:" + e.getMessage());

                  e.printStackTrace();

           }

          

           //list 저장된 링크의 기사 데이터를 전부 읽어서 파일에 저장하기

           try {

                  for(String addr : list) {

                         try {

                                 URL url = new URL(addr);

                                 HttpURLConnection con = (HttpURLConnection)url.openConnection();

                                 con.setUseCaches(false);

                             con.setConnectTimeout(10000);

                                

                                 StringBuilder sb = new StringBuilder();

                                 BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));

                                

                                 while(true) {

                                        String line = br.readLine();

                                        if(line == null){

                                               break;

                                        }

                                     sb.append(line+"\n");

                                 }

                                 String html = sb.toString();

                                 br.close();

                                 con.disconnect();

                             //System.out.println(html);

                                 //파일에 기록

 

                                 Document document = Jsoup.parse(html);

                                 //class title 태그만 찾아오기

                                 Elements articles = document.getElementsByClass("title");

                                 //찾아온 데이터를 파일에 기록

                                 for(int i=0 ; i<articles.size(); i+=1) {

                                        PrintWriter pw = new PrintWriter(new FileOutputStream("./코로나.txt", true)); //true 써야 append모드

                                 pw.println(html);

                                 pw.flush();

                                 pw.close();

                                 }

                                

                                

                                

                                

                                 //실제 여러 개의 페이지에서 스크래핑할 딜레이를 주는 것이 좋다

                                 //Thread.sleep(1000);

                         }catch(Exception e) {

                                 System.out.println("기사 읽기 예외:" + e.getMessage());

                         }

                  }

                 

           }catch(Exception e) {

                  System.out.println("링크 읽기 예외:" + e.getMessage());

                 

           }

 

    }

 

 

 

**일반적인 방법으로 web 의 데이터를 못 읽는 경우

1.ajax를 이용해서 동적으로 데이터를 가져와서 출력하는 경우

=>ajax: 현재 페이지를 다시 호출하지 않고 동적으로 데이터를 가져오는 기술

javahttpURLConnectoin이나 pythonrequests 모듈은 접속햇을 때 존재하는 데이터 읽어 올 수 있다.

 

2.로그인을 해야만 사용가능한 데이터

 

**selenium

=>웹 페이지를 테스트 하기 위한 라이브러리로 출발

=>브라우저를 실행시켜 직접 제어 가능한 라이브러리

=>브라우저로 URL에 접속한 후 일정 시간 대기한 후 페이지의 데이터를 읽어내면 ajax형태로 읽어오는 데이터도 사용이 가능

=>자바스크립트를 이용해서 로그인과 같은 폼에 데이터 입력이 가능하기 때문에 로그인 한 후 접근 가능한 데이터도 사용이 가능

=>자바 이외 파이썬에서도 사용이 가능

 

1.준비

1)selenium라이브러리를 다운로드 받아서 프로젝트에 포함

- www.seleniumhq.org에서 다운로드받아도 되고 www.mvnrepository.com 에서 selenium검색 후 다운로드

- 다운로드 받은 파일을 프로젝트에 복사하고 선택한 후 [build path] -[Add To Build Path]

www.mvnrepository.com여기서 다운로드 실패

 

2) 동작시키고자 하는 브라우저의 드라이버 파일을 다운로드

=>브라우저 없이 하고자 하면 pantom.js를 다운로드 받으면 되는데 deprecated

=>chrome의 경우는 버전에 맞는 드라이버를 다운로드

chrome버전 확인

https://chromedriver.chromium.org/downloads 에서 다운로드 한 후 압축해제

 

2.크롬을 실행시켜 사이트에 접속

1) 크롬드라이버 이름과 드라이버 위치를 시스템 프로퍼티에 추가

System.setProperty("webdriver.chrome.driver",String 드라이브 파일의 경로);

 

2)크롬 실행

WebDriver driver = new ChromeDriver();

 

3)사이트 접속

driver.get("사이트 URL")

 

 

4)사이트의 HTML

driver.getPageSource();

 

5)크롬을 실행시켜 naver에 접속하고 html가져오기

public class ChromeRun {

       public static void main(String[] args) {

               //크롬 드라이버의 위치를 프로퍼티에 추가

               System.setProperty("webdriver.chrome.driver", "C:\\project\\JAVA_PROJECT\\java\\src\\java\\chromedriver.exe");

               //크롬실행

               WebDriver driver = new ChromeDriver();

               //크롬에서 사이트에 접속

               driver.get("https://www.naver.com");

               //접속한 사이트의 html 가져오기

               System.out.println(driver.getPageSource());

       }

}

 

3.Element선택

driver.findElement(By.id, "실제id"); //하나만 나온다.

driver.findElement(By.xpath, " xpath"); //하나만 나온다.

 

driver.findElements(By.tagName, "tag");

driver.findElements(By.class, "class");

 

선택한 요소가 폼의 입력도구 인 경우 .send_keys(String value)를 호출하면 value폼의 입력도구가 채워짐

선택한 요소가 폼의 버튼이나 링크 인 경우 .click()를 호출하면 버튼이나 링크를 클릭한 효과

폼의 submit이면 submit()을 호출하면 폼의 데이터를 전송

 

 

4.페이지 접속과 해제

get(String url): url에 접속

 

close(): 종료

 

5.프레임(페이지를 나누어서 다른 html을 불러온다던가 다른 dom 객체를 가져와서 출력) 전환

switchTo().frame(프레임 Element)

 

6.크롬을 실행시키지 않고 작업

ChromeOptions options = new ChromeOptions();

options.addArguments("headless");

WebDriver driver = new ChromeDriver(options);

 

7.다음 로그인을 해서 카페에 글 쓰기

public class DaumLogin {

       public static void main(String[] args) {

               // 크롬 드라이버의 위치를 프로퍼티에 추가

               // 맥에서는 아래것 필요없다.

               System.setProperty("webdriver.chrome.driver",

                      "C:\\project\\JAVA_PROJECT\\java\\src\\java\\chromedriver.exe");

               // 크롬실행

               WebDriver driver = new ChromeDriver();

               // 크롬에서 사이트에 접속

          driver.get("https://logins.daum.net/accounts/signinform.do?url=https%3A%2F%2Fwww.daum.net%2F");

               // https://accounts.kakao.com/login?continue=https%3A%2F%2Flogins.daum.net%2Faccounts%2Fksso.do%3Frescue%3Dtrue%26url%3Dhttps%253A%252F%252Fwww.daum.net%252F

               // driver.get("https://accounts.kakao.com/login?continue=https%3A%2F%2Flogins.daum.net%2Faccounts%2Fksso.do%3Frescue%3Dtrue%26url%3Dhttps%253A%252F%252Fwww.daum.net%252F");

               // 아이디와 비밀번호 입력받기

               Scanner sc = new Scanner(System.in);

               System.out.print("아이디를 입력하세요:");

               String id = sc.nextLine();

               System.out.print("비밀번호를 입력하세요:");

               String pwd = sc.nextLine();

               // 아이디란과 비밀번호 입력란에 입력받은 내용을 입력하기

       driver.findElement(By.xpath("//*[@id=\"id\"]")).sendKeys(id);

       driver.findElement(By.xpath("//*[@id=\"inputPwd\"]")).sendKeys(pwd);

               //// *[@id="id_email_2"]

               //// *[@id="id_password_3"]

               // driver.findElement(By.xpath("//*[@id=\"id_email_2\"]")).sendKeys(id);

               // driver.findElement(By.xpath("//*[@id=\"id_password_3\"]")).sendKeys(pwd);

 

               //// *[@id="login-form"]/fieldset/div[8]/button

       driver.findElement(By.xpath("//*[@id=\"loginBtn\"]")).click();

               // driver.findElement(By.xpath("//*[@id=\"login-form\"]/fieldset/div[8]/button")).click();

 

              

               try {

                      Thread.sleep(5000);

               } catch (InterruptedException e) {

                      // TODO Auto-generated catch block

                      e.printStackTrace();

               }

              

               // 카페에 접속

              driver.get("http://cafe.daum.net/samhak7/_memo");// 카페주소

               //// *[@id="memoForm__memo"]/div/table/tbody/tr[1]/td[1]/div/textarea

               // 이것이 안된다. 프레임 보기에서 봐야 하기 때문이다.

               // driver.findElement(By.xpath("//

       ////*[@id="memoForm__memo"]/div/table/tbody/tr[1]/td[1]/div/textarea")).sendKeys("내용");

               // 프레임을 전환: down이라는 프레임으로 전환

          driver.switchTo().frame(driver.findElement(By.id("down")));

               System.out.print("입력할 모드:");

               String memo = sc.nextLine();

               //입력받은 내용ㅇ을 입력란에 추가

               // driver.findElement(By.name("memo_content")).sendKeys("메코로 연습");;

       driver.findElement(By.xpath("//*[@id=\"memoForm\"]/div/table/tbody/tr[1]/td[1]/div/textarea")).sendKeys(memo);

       ////*[@id="memoForm"]/div/table/tbody/tr[1]/td[2]/a[1]/span[2]

               //등록 버튼 클릭

       driver.findElement(By.xpath("//*[@id=\"memoForm\"]/div/table/tbody/tr[1]/td[2]/a[1]/span[2]")).click();

              

               sc.close();

       }

}

 

8.네이브 로그인

public class NaverLogin {

       public static void main(String[] args) {

               // 크롬 드라이버의 위치를 프로퍼티에 추가

               // 맥에서는 아래것 필요없다.

               System.setProperty("webdriver.chrome.driver",

                      "C:\\project\\JAVA_PROJECT\\java\\src\\java\\chromedriver.exe");

               // 크롬실행

               WebDriver driver = new ChromeDriver();

               // 크롬에서 네이브 로그인 사이트에 접속

              driver.get("https://nid.naver.com/nidlogin.login?mode=form&url=https%3A%2F%2Fwww.naver.com");

              

               // 아이디와 비밀번호 입력받기

               Scanner sc = new Scanner(System.in);

               System.out.print("아이디를 입력하세요:");

               String id = sc.nextLine();

               System.out.print("비밀번호를 입력하세요:");

               String pwd = sc.nextLine();

               // 아이디란과 비밀번호 입력란에 입력받은 내용을 입력하기

              

               //아이디가 있으면 xpath 필요 없다.

               driver.findElement(By.id("id")).sendKeys(id);

               driver.findElement(By.id("pw")).sendKeys(pwd);

              

           driver.findElement(By.id("log.login")).click();//click으로 안되면 submit으로 하기

               //자동입력 방지 문자를 입력하는데 나중에 스크립트를 배우면 있다.

              

               //로그인해서 가져오는 것은 이렇게 하면 된다.

               String html = driver.getPageSource();

               Document document = Jsoup.parse(html);

              

               sc.close();

       }

}

 

 

**람다(Lambda)

부르는 언어마다 용도가 조금 다르다.

=>자바에서의 람다는 함수형 프로그래밍을 지원하기 위해서 1.7에서 부터 지원하기 시작한 이름없는 함수

=>메소드가 하나 뿐인 인터페이스를 구현해서 사용할 때 람다를 이용해서 대입하는 것이 가능

=>Intelli J Android Studio의 경우 메소드가 하나 뿐인 인터페이스를 anonymous를 이용해서 작성하면 람다로 자동 수정됩니다.

=>이전의 자바는 완전한 객체 지향 언어로서 메소드의 매개변수로 함수를 대입할 수 없었습니다.

누군가에게 작업만을 수행해달라고 요청을 해야 하는 경우 자바는 객체를 만들어서 메소드 형태로 대입한 후 요청을 했습니다.

이런 이유로 자바로 작업을 요청하는 경우 시스템이 무거워졌습니다.

이런함 문제를 해결하기 위해서 등장했던 언어들이 jvm을 사용하는 scala, Closure, Kotlin같은 언어들입니다.

위의 언어들은 마지막에는 java로 번역되서 jvm위에서 실행됩니다.

scala에서는 python을 쓸 수 있다. 자바에서는 아직 변환이 안됬다.

 

=>자바에서도 이러한 함수형 프로그래밍을 지원하기 위해서 등장시킨 개념이 람다와 스트림입니다.

1.8 이상에서만 사용이 가능

 

1.메소드가 하나뿐인 인터페이스의 구현

=>public void run이라는 메소드를 소유한 Runnable이라는 인터페이스가 있습니다.

이 인터페이스는 스레드를 만들어주는 인터페이스

1)인터페이스를 구현한 클래스를 생성하고 인스턴스를 만들어서 사용

public class RunnableImpl implements Runnable {

 

       @Override

       public void run() {

               // 클래스를 만들어서 사용한다고 출력

               try {

                      for (int i = 0; i < 10; i++) {

                             Thread.sleep(1000);

                             System.out.println("킆래스를 만들어서 사용");

                      }

               } catch (InterruptedException e) {

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

               }

       }

}

 

2)Main 메소드

public class ThreadMain {

       public static void main(String[] args) {

               //Runnable인터페이스를 구현한  클래스를 이용해서 스레드 생성 실행

               //인스턴스를 1개만 만들어서 사용한다면 메모리 낭비 - 클래스를 만들었기 때문에 클래스는 멤모리에서 삭제가 안됨

               Thread th1 = new Thread(new RunnableImpl());

               th1.start();

              

               //클래스를 만들지 않고 사용 -  anonymous class

               Thread th2 = new Thread(new Runnable() {

                      @Override

                      public void run() {

                             try {

                                    Thread.sleep(1000);

                                    System.out.println("anonymous class 이용");

                             } catch (InterruptedException e) {

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

                             }

                            

                      }

               });

               th2.start();

              

               //람다 이용

               //인스턴스를 만드는 과정도 없고 메소드 이름도 없지만 위와 동일한 기능을 수행

               Thread th3 = new Thread(()-> {

                      try {

                             Thread.sleep(1000);

                             System.out.println("람다 이용");

                      } catch (InterruptedException e) {

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

                      }

                     

               });

               th3.start();

       }

}

 

2.자바에서 람다

1) 직접 호출해서 메소드를 실행할 때는

인퍼페이스 변수 = 람다식 ;

변수 . 메소드 ()

 

2)1.8이상의 api를 사용하는 경우에는 람다식만 대입해서 메소드를 사용

대부분이 스트림 api

 

3.람다식 작성 요령

(타입 매개변수 , 타입 매개변수 ..) ->{메소드 내용 작성 : return 데이터}

=>매개변수의 자료형은 생략 가능: 호출할 때 대입되는 데이터를 가지고 자료형을 유추

=>매개변수가 없을 때는 ()을 해야 하지만 매개변수가 1개인 경우는 ()을 생략 가능

=>메소드 내용이 할 줄이면 {} 도 생략가능

=>리턴 타입은 작성할 필요없고 return을 해야하면 return 테이터 ; 만 해주면 됩니다.

 

4. 람다식을 사용할 수 있는 인터페이스는 메소드가 반드시 1개만 존재해야 합니다.

이러한 인터페이스는 @FunctionallInterface라는 어노페이션을 이용해서 생성

comparable는 사용할 수 없다.

 

5.매개변수가 없고 리턴 타입이 없는 메소드를 소유한 인터페이스의 경우

() -> {메소드 내용}

=>매개변수도 없고 리턴 타입도 없는 경우는 굉장히 드문 경우

=>이런 메소드는 출력하는 메소드 정도에서만 가능

메소드() python등에서도 줄 바꿈  준것도 없고 리턴도 없다.

 

 

5.람다 작성

//매개 변수가 없고 리턴 타입이 없는 메소드를 소유한 인터페이스

interface NoArgNoReturn{

       public void method1();

}

 

//매개변수가 있고 리턴 타입이 없는 경우 : 원본에 작업을 해서 원본을 변환시키는 인터페이스

interface ArgNoReturn{

       public void method2(int x);

}

 

//매개변수는 없고 리턴 타입만 있는 경우 : 거의 없는 경우

interface NoArgReturn{

       public double method3();

}

 

//재일 많은 형태 매개변수가 있고 리턴타입이 있는 경우 - 가장 많은 경우

interface ArgReturn{

       //문자열 주면 정수로 변환

       public int method4(String str);

}

 

public class LambdaMain {

       public static void main(String[] args) {

               //NoArgNoReturn ob1= 람다식;

               //매개변수가 없고 리턴도 없는 메소드를 활용

               NoArgNoReturn ob1= () -> {System.out.println("매개변수가 없고 리턴도 없는 람다");};

               //메소드 1 내용이 자동으로 들어간다.

               ob1.method1();

              

               //매개변수가 있는 경우 - 매개변수의 자료형은 생략이 가능 , 매개변수가 1개인 경우는 () 감싸지 않아도 됩니다.

               ArgNoReturn ob2= (int x)->{System.out.println(x+10);};

               ob2.method2(100);

              

               NoArgReturn ob3 = ()->{return 10.3;};

               double d = ob3.method3();

               System.out.println(d);

              

               //매개변수가 있고 리턴에 있는 경우 -데이터를 가공해서 리턴하는 함수

               ArgReturn ob4= (String str)->{return Integer.parseInt(str);};

               int d1 = ob4.method4("1343");

               System.out.println(d1);

       }

}

 

6.람다식을 사용할 있는 인터페이스

=>1.7 부터 사용했고 1.8버전 이상에서는 java.util.function패키지에서 기본적인 람다식을 사용할 수 있는 인터페이스를 제공

Consumer:매개변수는 있고 리턴 값은 없는 메소드를 소유한 인터페이스

Supplier:.매개변수는 없고 리턴 값만 있는 메소드를 소유한 인터페이스

Function: 매개변수가 있고 리턴 값도 있는 메소드를 소유한 인터페이스 - 변환

Operator : 매개변수가 있고 리턴 값도 있는 메소드를 소유한 인터페이스

            매개변수를 누적해서 연산해서 리턴하는 메소드를 소유한 인터페이스 - 연산(합계, 평균, 최대값, ..)

Predicate: 매개변수가 있는 리턴 값도 있는 메소드를 소유한 인터페이스

리턴 값이 boolean

조건에 맞는 데이터만 골라내는 메소드를 소유한 인터페이스

=>기본적으로 제너릭을 적용 - 매개변수의 자료형은 Generic으로 설정

//매개 변수가 없고 리턴 타입이 없는 메소드를 소유한 인터페이스

interface NoArgNoReturn{

       public void method1();

}

 

//매개변수가 있고 리턴 타입이 없는 경우 : 원본에 작업을 해서 원본을 변환시키는 인터페이스

interface ArgNoReturn{

       public void method2(int x);

}

 

//매개변수는 없고 리턴 타입만 있는 경우 : 거의 없는 경우

interface NoArgReturn{

       public double method3();

}

 

//재일 많은 형태 매개변수가 있고 리턴타입이 있는 경우 - 가장 많은 경우

interface ArgReturn{

       //문자열 주면 정수로 변환

       public int method4(String str);

}

 

public class LambdaMain {

       public static void main(String[] args) {

               //NoArgNoReturn ob1= 람다식;

               //매개변수가 없고 리턴도 없는 메소드를 활용

               NoArgNoReturn ob1= () -> {System.out.println("매개변수가 없고 리턴도 없는 람다");};

               //메소드 1 내용이 자동으로 들어간다.

               ob1.method1();

              

               //매개변수가 있는 경우 - 매개변수의 자료형은 생략이 가능 , 매개변수가 1개인 경우는 () 감싸지 않아도 됩니다.

               ArgNoReturn ob2= (int x)->{System.out.println(x+10);};

               ob2.method2(100);

              

               NoArgReturn ob3 = ()->{return 10.3;};

               double d = ob3.method3();

               System.out.println(d);

              

               //매개변수가 있고 리턴에 있는 경우 -데이터를 가공해서 리턴하는 함수

               ArgReturn ob4= (String str)->{return Integer.parseInt(str);};

               int d1 = ob4.method4("1343");

               System.out.println(d1);

              

               //consumer 인터페이스는 매개변수가 1개이고 리턴타입이 없는 메소드를 소유

               Consumer<String> consumer = (t)->{System.out.println(t);};

               consumer.accept("Java Lambda");

              

               //fUNCTION 인터페이스는 매개변수가 1개이고 리턴타입이 있는 메소드를 소유

               //제너릭에서 앞의 자료형은 매개변수의 자료형이고 뒤의 자료형은 리턴타입의 자료형

               //데이터를 받아서 변환한 리턴해주는 메소드

               //빅데이터 처리 할려고 하는데 반복문 쓰고 함수 적용할려고

               Function<String,String> function = (str)->{

                      if(str.length() <= 3)return str;

                      else return str.substring(0,3)+"...";};

               String r = function.apply("hi");

               System.out.println(r);

               r = function.apply("Hello World");

               System.out.println(r);

       }

}

 

 

 

 

반응형

'Study > Java' 카테고리의 다른 글

java-18  (0) 2020.10.10
java-17  (0) 2020.10.10
java-15  (1) 2020.10.05
java-14  (0) 2020.10.04
java-13  (0) 2020.10.03
반응형

** java.net. InetAddress

=>ip정보를 저장하는클래스

=>Static메소드인 HetLocalHost(),getByName(String hostname),getAllByName(String hostname)

getLocalHost():자기 컴퓨터의 ip정보를 리턴

getByName(): hostip정보 1개를 리턴

getAllByName(): host의 모든 ip정보를 리턴

 

**소켓 통신

Socket: NIC(Network Interface Card- LAN Card)를 추상화한 클래스

네트워크 프로그래밍이라는 용어 대신에 Socket Programming이라고도 합니다.

1.통신 방법

1)TCP 프로토콜을 사용하는 스트림 소켓

2)UDP 프로토콜을 사용하는 데이터그램 소켓

 

2.TCP (연결형 통신)

수신하는 쪽에서 송신하는 쪽으로 연결을 요청

송신하는 쪽에서 연결을 하고 요청하는 데이터에 대한 메타 정보(데이터에 대한 정보 - 데이터 크기 등) 를 송신

수신하는 쪽에서 그 정보를 보고 다시 요청을 합니다.

송신하는 쪽에서 데이터를 전송

수신하는 쪽에서 데이터 수신 여부를 송신하는 쪽에 전송하고 통신이 종료

신뢰성이 높지만 트래픽이 증가

http, https TCP통신

 

3.udp(비연결형 통신)

송신하는 쪽에서 수신하는 쪽으로 일방적으로 데이터를 전송하고 통신이 종료

DHCP(IP 동적 할당),DNS(DOmain ->ip)

콜 센터 ,appleapns(apple push Notification Service- 애플 제품의 알림)

수신 쪽에서 데이터를 제대로 받았는지 알 수 없음

public class IPInfo {

       public static void main(String[] args) {

              

               try {

                      //자신의 컴퓨터 ip정보 확인 - 자신의 컴퓨터 이름 (도메인) ip주소

                      InetAddress local = InetAddress.getLocalHost();

                      System.out.println(local);

                      // 구글의 ip장보 학인

                      InetAddress [] googles= InetAddress.getAllByName("www.google.com");

                      for(InetAddress imsi: googles) {

                             System.out.println(imsi);

                      }

               } catch (UnknownHostException e) {

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

               }

       }

}

 

4Socket 클래스

1)생성자

Socket()

Socket(InetAddress addr, int port): addr port번호에 해당하는 서비스에 접속

Socket(String addr, int port, InetAddress addr, int port ):addrport번호에 접속을 하는데 자신의 주소르 localaddr그리고 portlocalportㄹ 설정해서 접속

 

=>addr이 잘못 되면 NullPointerException 그리고 port번호가 잘못되면 illegalAgumentException이 발생

 

 

2)메소드

void close()

InetAddress getInetAddress():접속된 상대방 ip정보

int getPort():상대방 포트 번호

InputStream getInputStream() 상대방에게서 정보를 읽어오기 위한 스트림

OutputStream getOutputStream() 상대방에게서 정보를 전송하기 위한 스트림

 

 

5. 스트림 소켓 - tcp통신을 위한 소켓

1)수신 받는 쪽의 소켓 생성과 요청

Socket 소켓변수 = new Socket(서버 ip주소 ,포트번호);//연결

//요청 전송

OutputStream 출력스트림 변수 = 소켓변수.getOutputStream();

 

//바이트 단위 전송

출력스트림변수.write(byte[] b);

//문자단위 전송

PrintWriter pw = new PrintWriter(출력스트림변수);

pw.println(String msg);

pw.flush();

 

 

//데이터 읽어오기

InputSteam 입력스트림변수 = 소켓변수.getInputStream();

//바이트 단위로 읽어오기

입력스트림변수 .read(byte[] b);

 

//문자열 단위로 읽어오기

BufferedReader br = new BufferedReader(new InputStreamRader(입력스트림변수));

String msg = br.readLine();//한줄 읽어오기

//null을 리턴할 때 까지 읽으면 전송된 모든 내용을 읽을 수 있습니다.

 

 

6.www.daum.nethtml가져오기

=>www.daum.net이 호스트이름이고 http서버는 기본 포트 번호가 80

 

public class DaumMain {

       public static void main(String[] args) {

               try {

                      //daum 주소를 생성

                      InetAddress addr = InetAddress.getByName("www.daum.net");

                      //TCP 소켓 생성

                      Socket socket = new Socket(addr, 80);

                     

                      //요청 전송

                      PrintWriter pw = new PrintWriter(socket.getOutputStream());

                      pw.println("GET http://www.daum.net");

                      pw.flush();

                     

                      //데이터 읽기 - 문자 단위

                      BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));

                     

                      //읽을 데이터가 없을 까지 줄단위로 읽ㅇ오기

                      while(true) {

                             String line = br.readLine();

                             if(line == null) {

                                    break;

                             }

                             System.out.println(line);

                      }

                      br.close();

                      socket.close();

               }catch (Exception e) {

                      //예외 메시지 출력

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

                      //예외가 발생한 코드를 역추적

                      e.printStackTrace();

               }

       }

}

 

7.TCP Server:정보를 제공

=>ServerSocket 사용

1)생성자

ServerSocket()

ServerSocket(int port): port 개방해서 클라이언트의 요청을 받을 있도록 서버가 생성

ServerSocket(int port, int backlog): port 개방해서 클라이언트의 요청을 받을 있도록 서버가 생성되고 최대 접속 개수를 설정

 

2)메소드

void close()

 

Socket accept():호출하면 클라이언트의 요청이 까지 대기 상태가 되고 클라이언트의 요청이 오면 클라이언트와 통신할 있는 Socket 리턴하고 다음으로 넘어갑니다.

 

3)통신과정

=>ServerSocket 생성해서 클라이언트의 요청을 기다림

=>클라이언트 쪽에서 Socket 이용해서 서버에 접속

=>Socket 스트림을 가지고 메시지를 전송

=>ServerScoket 생성할 port 사용 중이 아닌 번호로 설정 -1024보다 숫자로 설정하는 것을 권장

서버 소켓을 생성하고 예외가 발생해서 프로그램이 중단되면 이전에 사용한 포트번호를 사용하지 못할 있습니다.

자바로 실행 중인 프로세스를 찾아서 중단해야 이전 포트를 다시 사용 가능합니다.

=>현재 사용 중인 포트를 확인:netstat - ano

자신의 ip확인 :ipconfig / (config -mac)

=>다른 컴퓨터에서 자신의 컴퓨터에 접속하도록 할려면 방화벽 해제 되어 있어야 합니다.

 

public class TCPServer {

       public static void main(String[] args) {

               try {

                      //서버 소켓을 생성

                      ServerSocket ss = new ServerSocket(9000);

                      while(true) {

                             System.out.println("서버 대기  ...");

                             //클라이언트의 접속을 기다림

                             Socket socket = ss.accept();

                             //접속한 클라이언트 정보 확인

                             System.out.println("접속한 클라이언트 : " +socket.getInetAddress());

                             //클라이언트가 전송한 메시지 확인

                             BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));

                             String msg = br.readLine();

                             System.out.println("메시지:" +msg);

                            

                             //클라이언트에게 메시지 전송

                             PrintWriter pw= new PrintWriter(socket.getOutputStream());

                             pw.println("서버가 보내는 메시지");

                             pw.flush();

                            

                             br.close();

                             pw.close();

                             socket.close();

                      }

               }catch (Exception e) {

                      //예외 메시지 출력

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

                      //예외가 발생한 코드를 역추적

                      e.printStackTrace();

               }

       }

}

 

public class TCPClinet {

       public static void main(String[] args) {

               try {

                      //서버에 접속하는 소켓을 생성 - 127.0.0.1

                      Socket socket = new Socket(InetAddress.getByName("ip주소") , 9000);

                      //메시지 전송

                      Scanner sc = new Scanner(System.in);

                      System.out.print("전송할 메시지:");

                      String msg = sc.nextLine();

                      PrintWriter pw= new PrintWriter(socket.getOutputStream());

                      pw.println(msg);

                      pw.flush();

                     

                      //메시지 읽기

                      BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));

                      String str = br.readLine();

                      System.out.println(str);

                     

                      br.close();

                      pw.close();

                      socket.close();

               }catch (Exception e) {

                      //예외 메시지 출력

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

                      //예외가 발생한 코드를 역추적

                      e.printStackTrace();

               }

       }

}

 

8.UDP

=>비연결형 통신

=>보내는 쪽에서 받는 쪽으로 메시지만 전송하고 통신이 종료

1)통신방식

unicast:1:1로 통신하는 방식

multicast:그룹에 속한 모든 클라이언트와 통신

 

broadcast:자신이 ip대역과 subnet mask를 이용해서 자신의 ip대역과 같은 그룹에 속한 모든 클라이언트에게 전소

 

 

2)DatagramPacket클래스와 DataGramSocket클래스 이용

=>DataGramSocket클래스

생성자

DataGramSocket(): 전송을 하기 위한 소켓

DataGramSocket(int socket):전송을 받기 위한 소켓

 

메소드

void close();

void recieve(DatagramPacket packet): 데이터를 받는 메소드

void sen(DatagramPacket packet): 데이터를 보내는 메소드

 

 

=>DatagramPacket클래스

생성자

DatagramPacket(byte [] bif, int length):전송을 받기 위한 패킷으로 byte배열에 데이터가 저장됩니다.

DatagramPacket(byte [] bif, int length, InetAddress addr, int port) :전송을 하기 위한 패킷으로 byte 배열의 내용을 length만큼 addrport에게 전송하기 위한 패킷

 

메소드

byte[] getData(): 데이터 리턴

int getLength():길이 리턴

 

=>String byte배열 변환

String ->byte배열 :String.getBytes();

byte배열 ->String : new String(byte배열)

public class UDPReceive {

       public static void main(String[] args) {

               try {

                      //받는 소켓을 생성

                      DatagramSocket socket = new DatagramSocket(7777);

                     

                      //데이터를 저장할 패킷을 생성

                      //byte[] b = new byte[65536];

                      //DatagramPacket dp = new DatagramPacket(b, b.length);

                      //데이터를 전송받아서 읽기

                      while(true) {

                            

                             //데이터를 저장할 패킷을 생성

                             // 두개의 문장을 반복문 바깥에 만들면 통신은 되는데 메시지를 보내고 짧은 메시지를 보내면

                             //짧은 메시지 뒤에 메시지의 내용이 추가되는 형태가 됩니다.

                             //반복문 안에서 계속 사용해야 하는 데이터는 반복문에서 초기화를 해주어야 합니다.

                             byte[] b = new byte[65536];

                             DatagramPacket dp = new DatagramPacket(b, b.length);

                            

                             //대기하고 있다가 데이터를 전송받으면 동작

                             socket.receive(dp);

                             //보낸곳 확인

                             System.out.println("보낸 :" +dp.getAddress().getHostAddress());

                             //데이터 확인

                            

                             String msg = new String(b);

                             System.out.println(msg);

                            

                      }

               }catch (Exception e) {

                      //예외 메시지 출력

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

                      //예외가 발생한 코드를 역추적

                      e.printStackTrace();

               }

       }

}

 

 

public class UDPSend {

       public static void main(String[] args) {

               try {

                      // udp전송을 위한 소켓 생성

                      DatagramSocket ds = new DatagramSocket();

                      Scanner sc = new Scanner(System.in);

                      while(true) {

                             //메시지 입력

                             System.out.print("전송할 메시지:");

                             String msg = sc.nextLine();

                            

                             //전송할 패킷 생성

                             DatagramPacket dp = new DatagramPacket(msg.getBytes(), msg.getBytes().length,InetAddress.getByName("127.0.0.1"),7777);

                             ds.send(dp);

                            

                             //sc.close();

                             //ds.close();

                      }

               } catch (Exception e) {

                      // 예외 메시지 출력

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

                      // 예외가 발생한 코드를 역추적

                      e.printStackTrace();

               }

       }

}

 

 

4)multicast

=>그룹에 속한 모든 단말에게 데이터를 전송하는 방식

=>244.0.0.0 ~ 239.255.255.255사이의 주소를 이용

이 주소 대역은  D class대역으로 Multicast용으로 예약된 ip주소 대역

=>MulticastScoket을 이용해서 구현

 

=>생성자

MulticastScocket();

MulticasetSocket(int port):

 

=>메소드

joinGroup(InetAddress addr) :그룹에 참여

leaveGroup(InetAddress addr):  그룹에서 빠져나오는 메소드

 

=>데이터 전송방식은 DatagramScocket과 동일

 

=>multicast 받는 쪽

 

public class MultiReceive {

       public static void main(String[] args) {

               try {

                      MulticastSocket ms = new MulticastSocket(9999);

                      //멀티케스트에 참여

                      //224.0.0.0 to 239.255.255.255

                      ms.joinGroup(InetAddress.getByName("ip주소"));

                      System.out.println("멀티 케스트 시작");

                     

                      while(true) {

                             //전송 받은 데이터를 저장할 바이트 배열 - 크기는 8 배수로 설정

                             byte [] b = new byte[65536];

                             //패킷을 생성

                             DatagramPacket dp = new DatagramPacket(b, b.length);

                             //데이터를 받을 있도록 대기

                             ms.receive(dp);

                            

                             //데이터 읽기

                             String msg = new String(dp.getData());

                             System.out.println(ms);

                      }

                     

               }catch (Exception e) {

                      //예외 메시지 출력

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

                      //예외가 발생한 코드를 역추적

                      e.printStackTrace();

               }

       }

}

 

 

=>multicast 보내는 쪽

public class MultiSend {

       public static void main(String[] args) {

               try {

                      MulticastSocket ms = new MulticastSocket();

                      Scanner sc = new Scanner(System.in);

                     

                      System.out.print("닉네임:");

                      String nickname = sc.nextLine();

                      while(true) {

                             System.out.print("전송할 메시지(종료는 end):");

                             String msg = sc.nextLine();

                             //자바에서 문자열은 == 비교하면 참조를 비교

                             //equals 비교해야 값을 비교

                             if(msg.equals("end")) {

                                    System.out.println("종료");

                                    break;

                             }

                             msg = nickname +" : "+ msg;

                             DatagramPacket dp =  new DatagramPacket(msg.getBytes(), msg.getBytes().length,InetAddress.getByName("ip주소"),9999);

                             ms.send(dp);

                      }

               } catch (Exception e) {

                      // 예외 메시지 출력

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

                      // 예외가 발생한 코드를 역추적

                      e.printStackTrace();

               }

       }

}

 

=>채팅 처럼 동시에 주고 받는 것이 가능하도록 할려면 보내고 받는 로직을 스레드를 이용해서 작업

콘솔에서는 쉽지 않습니다.

입력창과 출력창이 같아서 콘솔을 채팅은 동시에 입출력 한계가 있습니다.

 

 

**url 통신

=>소켓 통신을 저수준의 통신방식이라고 하고 그 이외의 통신 방식들은 고수준이라고 부릅니다.

성능은 소켓 통신이 우수한데 소켓 통신은 프로그램을 별도로 설치해야만 통신이 가능합니다.

url 통시은 브라우저를 통해서 사용이 가능하고 현재는 거의 모든 운영체제가 웹 브라우저를 하나씩 가지고 있습니다.

소켓 통신 : 증권 , 게임 등 주식거래는 조금한 시간의 차가 경제적으로 문제가 발생할 수 있다. 빨리 해야 한다.

최근에는 웹에서도 소켓 방식의 통신이 가능합니다.

WebSocket APIHTML5에서 제공

 

=>ULR 구성

프로토콜 : // 도메인이나 IP :포트번호 /파일 경로?이름=&이름=...

프포토콜과 도메인은 생략 못함

포트번호는 서비스의 기본포트를 사용하는 경우에는 생략이 가능

http:80, https:443

파일경로를 생략하는 경우가 있는데 이 경우는 서버의 설정을 이용해서 파일을 찾아옵니다.

 

파일 경로 뒤에 ? parameter라고 하는데 클라이언트가 서버에게 넘겨주는 데이터로 key-value형식으로 대입

parameter 전송 방식을 가지고 get방식과 post 방식을 구분

 

파일 경로 뒤에 #이 붙는 경우는 책갈피 입니다.

페이지 내엣 이동

 

1.java.net.URL클래스

=>URL을 만들기 위한 클래스

1)생성

URL(String url)

=>없는 url을 대입하면 MalformedURLException이 발생

 

2)메소드

URLConnection openConnection():URL과 양방향 통신이 가능한 Connection 을 리턴

여기서 리턴한 Connection HttpURLConnection이나 JarURLConnection으로 형변환해서 사용해야 합니ㅏㄷ.

 

URLConnection은 추상 클래스라서 메소드가 구현되어 있지 않습니다.

 

2.HttpURLConnection

=>URL 통신을 하기 위한 클래스

=>URL 클래스의 openConnection메소드를 이용해서 생성

=>메소드

setConnectTimeout(int timeout):밀리초 단위로 타입아웃을 설정하는 메소드로 타임 아웃 동안 접속이 안되면 접속 실패

 

setUseCaches(boolean isCache):이전에 접속했던 URL에 다시 요청할 때 이전 데이터를 가져올 것인지 설정 자주 변경되는 URL의 데이터는 반드시 false로 설정을 해주어야 합니다.

 

 

setRequestProperty(String field, String value)

addRequestProperty(String field, String value)

헤더에 값을 추가하는 메소드

카카오는 헤더에 추가해야 된다.

 

setRequestMethod(String method): 전송 방식을 설정

 

int getResponseCode():서버로 부터의 상태를 리턴

200번대 정상응답

300번대 리다이렉트 중

400번대 클라이언트 오류( 404- 잘못된 url)

500번대 서버 오류

 

InputStream getInputStream(): 데이터를 읽기 위한 스트림 리턴

 

3.웹의 데이터 포맷

xml: 태그 형식으로 표현하는 포맷, 별도의 라이브러리 없이 파싱 가능

JSON: 자바스크립트 객체 표현 방법으로 데이터를 표현, 별도의 라이브러리를 추가해야 파싱 가능

 

CSV: 구분자가 있는 문자열

HTML: 뷰의 용도로 사용되는 포맷인데 사이트에서 XML이나 JSON형태로 데이터를 제공해주지 않아서 수집해서 사용

 

 

4.OPEN API

데이터를 가진 곳에서 일반 사용자들에게 데이터를 사용할 수 있도록 XML이나 JSON형식으로 제공하는 것 데이터 뿐 아니라 라이브러리나 프레임워크 등을 제공하기도 함

 

데이터는 대부분의 경우 가입을 해서 키를 받는 형태로 제공

키 값을 주소에 넣기도 하고 헤더에 하는 방법

 

http://data.go.kr/

 

 

5.동기적 다운로드

public class StringDownload {

       public static void main(String[] args) {

               try {

                      //다운로드 받을 url 생성

                      URL url= new URL("https://www.naver.com");

                      //url연결 객체 생성

                       HttpURLConnection con = (HttpURLConnection)url.openConnection();

                       //연결 옵션 설정

                       con.setConnectTimeout(30000); //30 동안 연력이 안되면 연결시도 종료

                       //캐시 사용을 하지 않음

                       con.setUseCaches(false);

                       

                       //데이터를 읽어올 스트림을 생성

                       BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));

                       //많은 양의 문자열을 읽어야 하는 경우

                       StringBuilder sb = new StringBuilder();

                       while(true) {

                              // 읽기

                              String line = br.readLine();

                              //읽은 데이터가 없으면 반복은 중단

                              if(line == null) {

                                     break;

                              }

                              //데이터가 있으며면 sb 추가

                              sb.append(line+"\n");//메모리 낭비가 줄어들 있다.

                       }

                       //StringBuilder 데이터를 STring 으로 변환

                       String msg = sb.toString();

                       System.out.println(msg);

               }catch (Exception e) {

                      //예외 메시지 출력

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

                      //예외가 발생한 코드를 역추적

                      e.printStackTrace();

               }

       }

}

 

 

6.비동기 다운로드

=>위처럼 스레드를 사용하지 않고 다운로드 받는 방식을 동기식이라고 합니다.

동기식은 데이터를 다운로드 받는 동안 다른 작업을 할 수 없습니다.

데이터 다운로드와 관련없는 작업도 데이터를 다운로드 동안은 수행할 수 없습니다.

네트워크 작업은 스레드를 이용해서 비동기식으로 동작하도록 만드는 것을 권장(안드로이드는 필수)

다운로드와 관련없는 작업은 다운로드 받는 동안 수행되도록 작성한는 것이 좋습니다.

 

public class ImageDownload {

       public static void main(String[] args) {

               Thread th = new Thread() {

                      public void run() {

                             try {

                                    String addr = "https://img0.yna.co.kr/photo/yna/YH/2019/04/07/PYH2019040703010000700_P4.jpg";

                                    //파일명을 만들기 위해서 마지막/ 다음의 문자열 가져오기

                                    int len = addr.lastIndexOf("/");

                                    String filename =addr.substring(len+1);

                                    System.out.println(filename);

                                    //현제 디렉토리에 파일이 있으면 있다고 출력하고 없다면 다운로드 받아서 저장

                                    File f = new File("./"+filename);

                                    if(f.exists() == true) {

                                           System.out.println("파일이 이미 존재합니다.");

                                            return;

                                    }else {

                                            //한번에 읽어오기

                                            /*

                                            URL url = new URL(addr);

                                            HttpURLConnection con = (HttpURLConnection)url.openConnection();

                                           con.setConnectTimeout(30000);

                                           con.setUseCaches(false);

                                           

                                            //다운로드 받을 파일의 킈를 가져오기

                                            int length = con.getContentLength();

                                            //데이터 저장할 바이트 생성

                                            byte [] b = new byte[length];

                                            //바아트 단위로 데이터를 읽어옴 스트램 생성

                                           BufferedInputStream bis = new BufferedInputStream(con.getInputStream());

                                            //대이터틀 읽어서 b 저장

                                            bis.read(b);

                                            //읽어온 내용을 파일제 저장

                                            PrintStream ps = new PrintStream(new FileOutputStream("./src/java/"+filename));

                                            ps.write(b);

                                           

                                            //사용한 스트럼 닫기

                                            ps.close();

                                            bis.close();

                                            //연결 끝ㅎ기

                                            con.disconnect();

                                             */

                                           

                                            URL url = new URL(addr);

                                            HttpURLConnection con = (HttpURLConnection)url.openConnection();

                                           con.setConnectTimeout(30000);

                                           con.setUseCaches(false);

                                           

                                            //데이터 저장할 바이트 생성

                                           BufferedInputStream bis = new BufferedInputStream(con.getInputStream());

                                            //읽어온 내용을 파일제 저장

                                            PrintStream ps = new PrintStream(new FileOutputStream("./src/java/"+filename));

                                           

                                           while(true) {

                                                   //size 바이트 배열

                                                   byte [] b= new byte[512];

                                                   //내요을 읽어서 b 저장하고

                                                   //읽은 개수를 r 저장

                                                   int r = bis.read(b);

                                                   //읽은개 없으면 중닺ㄴ

                                                   if(r<= 0) {

                                                          break;

                                                   }

                                                   ///읽은 데이터가 있으면 기록

                                                   ps.write(b,0,r);

                                                   //버퍼에 내용이 남아있는 것을 방지하기 위해서 마지막에 flush 호출

                                                   ps.flush();

                                            }

                                           

                                            //사용한 스트럼 닫기

                                            ps.close();

                                            bis.close();

                                            //연결 끝ㅎ기

                                            con.disconnect();

                                           

                                    }

                             }catch(Exception e) {

                                    System.out.println("다운로드 예외:" + e.getMessage());

                                    e.printStackTrace();

                             }

                      }

               };

               th.start();

              

               //스레드 동작 쉬는 시간이 생기면 동작

               System.out.println("스레드와 상관없는 코드");

       }

}

 

 

**XML Parsing

=>RSS(Really Simple Syndication,Rich Site Summary): 빠른 속도로 변경되는 데이터를 제공하기 위한 서비스로 예전에는 xml 을 많이 사용

=>xml: 태그 형식으로 표현하는 데이터 포맷

xml으 해석은 xml상단에 dtd가 있으면 dtd가 하고 없으면 개발자가 해석

=>html은 브라우저가 해석하기 때문에 우리가 원하는 내용만 고라서 보는게 안되고 출력을 직접 하게 되면 화면 크기에 따라 원하는 모양으로 볼 수가 없습니다.

데이터를 제공해서 보고자 하는 쪽에서 원하는 것만 골라서 원하는 크기로 볼 수 있도록 해줍니다.

 

 

1.xml Parsing

=>DOM(Documnet Object Model) Parser 이용

내용을 메모리에 트리 형태로 전부 펼쳐 놓고 원하는 데이터를 찾아가는 방식

 

DocumentBuilderFactory factory  = DocumentBuilderFactory.newInstance();

DocumentBuilder bulder = factory.newDocumentBuilder():

Document document = builder.parse(String uri);

//uri 대신에 inputStream inputStream, FIle file을 대입해도 됩니다.

//Dom의 형태로 메모리에 펼칩니다.

 

//루트 찾기

Element root = document.getDocumentElement();

 

//원하는 태그 찾아오기

NodeList list = root.getElementsByTagName(String tag);

s->전체 가져오기 s없으면 하나 가져오기

//위에서 찾은 list를 가지고 반복문을 수행

int n = list.getLength();

for (int i = 0; i< n ; i++){

           Node item = list.item(i);

           Node text = item.getFirstChild();

           text.getNodeValue();//태그 안의 내용

}

 

 

 

=>http://hani.co.kr/arti/sports/sports_general/ :한겨래 스포츠 rss

위 주소에서 titlelink만 추출해서 출력

 

thread.sleep() 하면서 하면 된다.

기상층도 xml로 준다.

 

**java에서의 외부 라이브러리 사용

=>일반 java applicationjar(java압축파일)파일을 build path에 추가

=>java web applicationWEB-INF/lib 디렉토리에 jar파일을 복사

=>maver이나 gradle기반의 프로젝트는 설정 파일에 의존성을 설정

=>자바 라이브러리는 www.mvnrepository.com에서 다운로드 기능

 

 

 

 

**json parsing

1.JSON

=>자바 스크립트 객체 표현법으로 데이터를 표현

파이썬의 리스트와 DIC 표현법과도 동일

{"key":"value" ,"key":"value" ...}:객체

["data1","data2" ...]:배열

 

2.파싱을 할려면 외부 라이브러리 이용

1) www.mvnrepository.com에서 json을 검색

 

자바는 jar,war 은 자기가 풀수 있다.

python zip , tar은 자기가 풀수 있다.

 

2)다운로드한 파일을 프로젝트에 복사

 

3) 복사한 파일을 선택하고 마우스 오르쪽을 클릭해서 [Build Path]-[Add to Build Path]를 클릭

Build Path에 추가하면 실행할 때 이 파일에 있는 클래스 들을 jvm이 로드를 사용할 수 있도록 해줍니다.

 

3.파싱

1)JSONObject

=>객체를 가져올 때 사용하는 자료형

 

2)JSONArray

=>배열을 가져올 때 사용하는 자료형

 

3)파싱과정

문자열을 가지고 new JSONObject(String json)(중괄호)이나 new JSONArray(String json)(대괄호)을 호출해서 객체나 배열 생성

 

JSONObjectget자료형(String key):key 에 해당하는 데이터를 자료형으로 리턴

JSONArrayget자료형(int index): index에 해당하는 데이터를 자료형으로 리턴, 배열은 개수를 length메소드로 리턴

 

4) kakap open api사용

=>최근의 open api들은 인증키를 url에 포함시키지 않고 header에 포함시켜서 요청하도록 합니다.

=>developer.kakao.com에서 open api데이터 사용을 신청

developer.kakao.com여기에서 자기 아이디로 등록하기

 

네이티브 앱 키

REST API ->open api

JavaScript ->web

Admin

·       네이티브 앱 키: iOS, Android 앱 개발시 필요한 key

·       REST API : REST API 호출시 필요한 key

·       Javascript : Javascript 앱 개발시 필요한 key

·       Admin : Push, 앱관리 등 관리자 권한에서 필요한 key. 보안 유지 필수

 

 

자기가 어떤것으로 사용할 것인지 설정을 하셔야 합니다.

하루에 몇개 만큼 쓸 것인가?

 

도서 검색

"https://dapi.kakao.com/v3/search/book?target=title&query=검색할 도서명  

Header Authorization: KakaoAK kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk

                             (자신의 REST API 키 사용한다.)

 

 

 url은 받느시 인코딩을 해줘어야 합니다.

한글이 있으면 utf-8로 변환해서 대입해야 합니다.

java.net.Encode.encode(String str,String enctype);

java.net.Encode.encode("미움받을 용기","utf-8");

 

?뒤에 들어가는 데이터를 parameter라고 하는데 이름=&이름=..의 형태

파라미터는 순서가 없기 때문에 아무거나 먼저 입력해도 됩니다.

 

 

4.kakao 의 도서검색 api파싱

 

https://developers.kakao.com/docs/restapi/search#%EC%B1%85-%EA%B2%80%EC%83%89

참조해서 해야 한다.

 

json object ->meta

json array ->documents

 

utf-8 UTF8같다.

CP949 = MS949같다.

EUCKR euc-kr

 

 

public class KakaoOpenAPI {

       public static void main(String[] args) {

               //데이터를 다운로드 받는 부분

               String json = null;

               try {

                      //검색함 도서이름 거입력

                      System.out.print("검색함 도서명:");

                      Scanner sc = new Scanner(System.in);

                      String book = sc.nextLine();

                     

                      //book 한글로 입력할 있으므로 인코딩

                      book =URLEncoder.encode(book,"utf-8");

                      //다운 로드 받을 url생성

                      //항상 인코딩을 해야 한다. 아니면 조회가 안된다.

                      //입력 받는 것은 뒤에 하는것이 좋다.

                      URL url = new URL("https://dapi.kakao.com/v3/search/book?size=50&page=2&sort=latest&target=title&query="+book);

                     

                      //연결 객체 생성

                      HttpURLConnection con =(HttpURLConnection)url.openConnection();

                      //옵션 설정

                      con.setConnectTimeout(20000);

                      con.setUseCaches(false);

                     

                      con.addRequestProperty("Authorization", "자신의 REST API 키 사용한다");

                     

                      //문자열 읽어오기

                      BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));

                      StringBuilder sb = new StringBuilder();

                      while(true) {

                             String line = br.readLine();

                             if(line == null) {

                                    break;

                             }

                             sb.append(line+"\n");

                      }

                      //데이터를 문자열로 변환

                      json = sb.toString();

                     

                      br.close();

                      con.disconnect();

                      sc.close();

                     

                      //System.out.println(json);

               }catch (Exception e) {

                      System.out.println("다운로드 에러:" +e.getMessage());

                      e.printStackTrace();

               }

               //데이터를 파싱하는  부분

               if(json == null) {

                      System.out.println("읽어온 데이터가 없습니다.");

               }else {

                      //전체 문자열을 json 객체로 변환

                      JSONObject root = new JSONObject(json);

                      //System.out.println(root);

                      //meta 객체

                      JSONObject meta = root.getJSONObject("meta");

                      //System.out.println(meta);

                      //documents 배열

                      JSONArray documents = root.getJSONArray("documents");

                      //System.out.println(documnets);

                     

                      //배열의 데이터 개수 찾아오기

                      int len = documents.length();

                      for(int i = 0; i <len; i++) {

                             JSONObject document = documents.getJSONObject(i);

                             //System.out.println(documnet);

                             try {                       

                                    String title = document.getString("title");

                                    int price = document.getInt("price");

                                   

                                    //thumbnail

                                    String thumbnail = document.getString("thumbnail");

                                    //인코딩은 문자열을 메모리에 저장되는 코드로 변환하는 것이고

                                    //디코딩은 메모리에 저장된 코드를 원래의 문자열로 복원하는 것입니다.

                                    System.out.println(title+" : "+price+" "+URLDecoder.decode(thumbnail,"utf-8"));

                             }catch(Exception e) {}

                      }

               }

       }

}

 

 

**HTML 파싱

=>사이트에서 출력은 되어 있는데 Open API형태로 데이터를 제공하지 않는 경우 HTML을 읽어서 사용

twitteropen api있는 지 확인하고 없으면 html가져와서 해야 한다.

=>HTML가져올 때는 URL의 인코딩에 주의하고 읽어온 데이터의 인코딩에도 주의

읽어온 데이터나 싸이트 등 설정해야 한다.

=>읽어야 하는 데이터가 AJAX(비동기적으로 데이터 가져오는 기술)형태로 만들어져 있거나 로그인을 해야하는 경우 또는 자바스크립트 코드를 실행해야 하는 경우에는 selenium같은 라이브러리를 사용해야 합니다.

로그인을 해야 하는 경우도 있고 부모 경로로 가는 경우 도 잇다.

HTTPURL 스코롤 한 것은 나오지 않는다.

=>자바에서 HTML파싱에 많이 이용되는 라이버러리는 JSoup

 

 

tag :중복 될 수 있습니다. (여러개 가능하다.)

id :중복 될 수 없습니다. -개발자가 만든 것이라서 없는 태그도 있습니다.(없을 수 있다.)

class : 중복 될 수 있습니다.

xpath:중복 될 수 없습니다. -태그의 경로라서 개발자가 만드는 것이 아니고 브라우저가 위치를 찾는 개념

(이것은 무조건 있다.)

 

selector: dom객체를 선택하기 위한 문법

로그인은 xpath찾는 것이 좋다.chrom 검사할 경우 선태하실때 오른쪽 눌르시면 copy가보면 selector xpath가 있다.

xpath는 네이브 자동로그인 할 경우

 

 

 

 

반응형

'Study > Java' 카테고리의 다른 글

java-17  (0) 2020.10.10
java-16  (0) 2020.10.10
java-14  (0) 2020.10.04
java-13  (0) 2020.10.03
java-12  (0) 2020.10.02
반응형

 

파일 만든 것도 중요한데

jvm->가상머신 실제아니고 실제인것 처럼 동작

java는 직접적으로 handing안하고 jvm이 인수 있는 것

 

 

업데이트 ->

맨처음 있는 가 없는 가 확인해서 다운로드 한다.

다운르도 하면서 설치 파일 생긴다.

 

 

서버에 a.dat       ->업데이트 단순하게 있는가 없는 가 할때 클라이언트에 있을 때 크기를 비교한다.

                                  날짜도 비교할 수 있다.

                                 

클라이언트 a.dat

 

클라이언트 에서 수정을 안한다. 다운로드 하다가 수정하다가 다운로드 끄지면 a.dat 가 깨져서 사용할 수 없어서 서버에 a.data  임시.dat로 만든다.

클라이언트에 a.dat ->back후 생성

a.     dat 삭제하고 생선

 

window업데이트 중인데 끄면 안되는데 다운로드 할 경우 끌 수 있다.

다운로드 받을때 끄도 문제 없다.데이터 수정할 경우 끄면 안된다.

application 파일에 대한 정보가 중요하다.

업데이트 할 때 문제 가 생긴다 .

 

경로

절대 경로: root부터 불변의 경로 ->고정

상대 경로: 현재 위치에 따라서 변하게 된다 ->

 

\ 문자 : 제어문자 (프로그래밍 언어가 해석할려고 한다.)

            white space

\\

 

정규식에서는 \ -> \\\\

파일 :///

/시작할 셩우 최상위

./ ->현재 디렉토리

 

1. File 클래스

v  java.io 패키지에 존재하는 시스템에 있는 파일이나 디렉토리를 추상화한 클래스

v  File 클래스를 이용하면 파일의 크기, 생성, 삭제 작업 및 마지막 수정날짜 등 다양한 정보를 알 수 있는 메소드를 제공

v  경로

ü  절대 경로: 루트로부터의 위치

l  Windows -> 루트드라이브:\디렉토리경로\파일이름

l  Web -> 프로토콜://자원경로

l  그 이외의 경우 -> /루트디렉토리/디렉토리경로/파일이름

l  Windows 경우는 디렉토리 기호가 \ 그 이외의 경우는 /

ü  상대경로: 현재 위치로부터의 경로

l  ./: 현재 디렉토리

l  ../: 상위 디렉토리

 

Dev 개발(development) 환경 window  \

                                                         이 경우 절대 경로 면 문제 생긴다.

Ops 운영(operation) 환경    linux     /

 

dev - ops

개발환경에서 운영환경으로 바꿀때 소스를 적게 바꿔야 한다.

소스 바꾸는 것이 위험하다.

 

source- >내가 작성한 문장이지 실행은 안된다.

     compile

class

  

    buile

            load

  

    run

소스를 바꾸면 위에것 다 다시해야 한다. 그래서 문제가 생길수 도있다.

디렉토리 ->상대경로

 

app

         src

C:\\project\\JAVA_PROJECT\\java\\src\\java\\img\\"+(i%10)+".png" ->절대 경로

다른데서 사용할 없다.

그래서 상대경로를 사용한다.

 

./그림파일 집에  들고 가도  위치에 문제가 안생긴다. 소스 코드가 클 가능성이 있다.

 

절대 경로 사용할 수 있는 것은 파일이나 데이터베이스에 저장한다.  경로 바꿀 경우 여기 수정한다.

원만하면 상대경로로 써야 한다.

 

string ->예외를 발생시키는 것이 낮아진다.

path는 경로

name은 이름만 리턴한다.

isreturn 타입은 boolean이다.

 return long

mkdir ->디렉토리 만들어준다,

 

**File.클래스

=>파일을 생성하고 삭제 그리고 파일에 대한 정보를 리턴하는 클래스

1.생성자

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

File(String parent,String child) //parntchild를 조합해서 생성

File(File parent, String child) :parentchild를 조합해서 생성

 

2.파일 경로

1)절대 경로 : 루트로부터의 경로

=>window는 디렉트리 기호호 \나머지 운영체제는 /

=>절대 경로는 소스 상에서 등장하지 않는 것이 좋습니다.

개발환경에서 운영환경으로 이행할 때 소스의 수정을 유발할 수 있습니다.

절대경로를 사용해야 한다면 다른 파일이나 데이터베이스에 작성해두고 불러서 사용하는 형태로 작성해야 운영환경으로 이행할 떄 소스를 수정하지 않고 사용이 가능합니다.

 

2)상대경로 : 현재 디렉토리부터에서의 경로

./: 현재 디렉토리

../: 상위 디렉토리

 

File f = new File(cwd.getAbsoluteFile()+"/src/0.png");

src ->..으로 사용불가하다 .부모로 가기 때문이다.

예전에 ..으로 애매모호한디텍토리로 가능한 것은 정규식사용 가능하기 떄문이다.

 

public class FileInfo {

       public static void main(String[] args) {

               //절대 경로를 이용해서 파일 인스턴스 생성

               //File f = new File("C:\\project\\JAVA_PROJECT\\java\\src\\java\\img\\0.png");

              

               //상대경로를 이용해서 파일 인스턴스 생성 : 파일을 프로젝트 디렉토리에 복사하고 실행

               //java/ src/

               //C:\project\JAVA_PROJECT\java  ./0.png

               File cwd = new File(".");

               System.out.println(cwd.getAbsoluteFile());

              

               File f = new File(cwd.getAbsoluteFile()+"/src/0.png");

               //파일의 존재 여부 확인 -서버 & 클라이언트 환경에서 클라이언트에 파일 존재여부를 확인해서 다운로드

               boolean isExists = f.exists();

               System.out.println("존재여부: " +isExists);

               //파일의 마지막 수정시간 확인 - 업데이트할 시간이 서로 다르면 다운로드

               long modify = f.lastModified();

               System.out.println("마지막 수정시간: "+modify);

              

               //수정 시간을 우리가 사용하는 시간으로 변경

               Date date = new Date(modify);

               System.out.println("마지막 수정시간: "+date);

              

               //파일의 크기 확인 - 업데이트 때도 사용할 있고 다운르드 여부를 판저하는데도 이용

               //파일의 크기를 알려줘서 다운로드 여부를 판단하도록 하는 경우가 있습니다.

               long size= f.length();

               System.out.println("파일크기: "+size);

       }

}

 

 

**java.nio.Path 클래스

=>기존 File 클래스의 문제점을 해결하기 위해서 등장한 클래스

1.기존 File클래스의 문제점

1)파일의 메타 데이터(데이터를 위한 데이터- 데이터 자체에 대한 정보)와 심블릭 링크(윈도우즈의 바로가기와 유사한 개념)를 취급할 수 없는 제약

2)디렉토리 안에서 파일이 생성되고 수정되고 삭제되는 것을 감시하지 못함

 

2.Path의 문제점

=>이전에 만들어진 API들이 File클래스를 많이 이용

파일과 path를 두가지 쓰야 하는 문제가 발생

 

3.Path객체 생성

1)Paths.get(String 파일경로)

 

 

2) URI uri = URI.create(file://파일경로);

Paths.get(uri)

=>URI 클래스를 이용하면 네트워크 상에 있는 파일도 생성할 수 있음

 

4.Path의 메소드

File toFitle():파일  인스턴스 리턴

URI toURI();URI인스턴스 리턴

 

5.파일 작업 메소스

1)파일복사 :Files.copy

2)파일 삭제 :Files.delete

3)파일 생성:Files.createFile

4)디렉토리 생성 :Files.createDirectory()

 

6.임시 파일 만들기

=>네트워크에서 많은 양의 데이터를 다운로드 받아서 사용하는 경우 메모리에 계속 저장하면 메모리 부족 현상이 발생할 수 있습니다.

일시적으로 임시 파일에 저장한 후 전부 다운로드 받으면 그 때 임시파일의 내용을 이용

Files.createTempFile(Path path, String pre, String ext)

=>pre 는 임시파일 앞에 들어갈 문자열이고 ext는 임시파일의 확장자

public class PathUse {

       public static void main(String[] args) {

               //src디렉토리에 있는 o.png파일을 Path 객체로 생성

               Path path = Paths.get("./src/0.png");

               //복사할 파일 경로르 ㄹ생성

               Path to = Paths.get("./src/zero.png");

              

               try {

                      //path에서 to 복사

                      Files.copy(path, to);

                      Files.delete(path);

               } catch (IOException e) {

                      // TODO Auto-generated catch block

                      e.printStackTrace();

               }

       }

}

 

**Stream

=>입출력을 처리하는 중간 매개체 , 데이터를 운반하는 통로

=>파일이나 네트워크 또는 입출력 장치 들과 통신을 하기 위해서는 스트림이 필요

1.스트림 분류

1)방향에 따른 분류

=>입력 스트림 과 출력 스트림

 

2)전송되는 데이터에 따른 분류

=>byte 스트림(일반 파일)과 문자 스트림 (텍스트 파일 -텍스트 단위 전송)

=>문자 스트림 대신에 byte스트림을 사용하는 것은 가능

반대는 안됨

 

2.ByteStream

1)InputStream

=>바이트 단위로 읽어올 때 사용하는 스트림들의 최상위 클래스로 추상 클래스

=>공통으로 사용할 메소드들을 선언만 해놓은 클래스

int available(): 읽을 수  있는 바이트 수를 리턴

 

void close(): 연결을 해제하는 메소드

 

int read():한 바이트를 읽어서 리턴, 읽은 데이터가 없으면 -1을 리턴

int read(byte[] ): byte배열 만큼 읽어서 매개변수로 대입된   byte배열에 저장하고 읽은 바이트 수를 리턴 읽은 데이터가 없으면 -1을 리턴

 

int read(byte[] ,int start, int len):  start부터 len만큼 읽어서 byte배열에 저장하고 읽은 바이트 수를 리턴 읽은 데이터가 없으면 -1을 리턴

 

2)OutputStream

=>바이트 단위로 출력하기 위한 스트림의 최상위 클래스로서 추상 클래스

 

void close() : 연결 해제

 

void write(int n) : n을 기록

 

void write(byte[] b): 바이트 배열의 내용 기록

 

void write(byte[] b,int start, int len):바이트 배열에서 start부터 len만큼 기록

 

void flush():버퍼의 내용을 전부 기록

 

=>기록을 할 때는 출력 대상에게 바로 기록하는 것이 아니고 버퍼에 기록한 후 버퍼가 차면 기록을 합니다.

마지막에 버퍼의 내용이 남아있는데 기록이 안되는 현상이 발생할 수 있습니다.

기록을 한 후 flush()를 호출하게 되면 남아있는 내용을 모두 기록하게 됩니다.

 

3)FileInputStream

=>파일에서 바이트 단위로 읽어오는 메소드

FileInputStream(String path)

FileInputStream(File path)

 

 

4)FileOutputStream

=>파일에 바이트 단위로 기록하는 클래스

FileOutputStream(String path) :파일이 존재하면 지우고 생성,없으면 바로 생성

FileOutputStream(String path,boolean append): 없으면 생성하고 있으면 이어쓰기

FileOutputStream(File path) :

FileOutputStream(File path,boolean append):

 

5)close

=>File이나 Network자원은 Java의 자원이 아니고 운영체제의 자원입니다.

이러한 외부 자원을 사용할 떄는 사용이 끝나면 자원을 반납해야 합니다

자원이 사용이 끝나고 자원을 반납하지 않으면 운영체제는 그 만큼의 자원을 사용할 수 없는 상태가 됩니다.

반드시 close를 호출해 주어야 합니다.

1.7버전 부터는 try(자원 생성){자원 사용} cathch(Exception e){예외처리 내용} 으 형태로 자원을 생성하면 close를 호출하지 않아도 자동으로 반납합니다.

try - resources구문이라고 합니다.

 

 

문자열을 바이트 단위로 파일에 기록하고 읽어오기

public class ByteInputOutput {

       public static void main(String[] args) {

               //try()안에서 만든 자원은 close 호출하지 않아도 됩니다.

               try(

                      //파일에 기록하기 이한 인스턴스 생성  

                             //파일 경로만 설정하면 기록할 마다 새로 기록 FileOutputStream fos = new FileOutputStream("./src/java/file.dat");

                             //두번째 매개변수로  true 설정하면 존재하는 경우 이어쓰기를 합니다.

                      FileOutputStream fos = new FileOutputStream("./src/java/file.dat",true);

                      //파일에서 읽어오기 위한 인스턴스 생성

                             //뒤에 옵션이 없다.

                      FileInputStream fis = new FileInputStream("./src/java/file.dat");

                             ){

                      //기록할 내용 만들기

                      String msg= "Hello Stream 안녕";

                      //문자열을 바이트 단위로 만들기

                      byte [] b = msg.getBytes();

                      //기록

                      fos.write(b);

                      fos.flush();//버퍼의 내용을 전부 기록

                     

                      //한번에 읽기

                      //읽을 데이터 개수를 가져오기

                      /*int len = fis.available();

                      //읽은 데이터를 저장할 배열을 생성

                      b = new byte[len];

                      //데이터 읽기

                      fis.read(b);

                      //바이트 배열을 문자열로 생성

                      String data = new String(b);

                      System.out.println(data);*/

                     

                      //용량이 경우 한번에 읽으면 메모리 부족으로 예외가 생기거나 시간이 오래 걸릴 있습니다.

                      //나누어서 읽는 것이 효율적

                     

                      //저장할 배열을 생성 -크기는 8 배수로 생성하는 것이 일반적

                      byte []  split= new byte[8];//일반적으로 8 배수로 읽는다.

                      while(true) {

                             //split 크기만큼 읽고 읽은 개수를 리턴

                             int r = fis.read(split);

                             if(r <= 0) {

                                    break;

                             }

                             //읽은 데이터가 있으면 처리

                             //문자를 바이트로 읽어서 변환하지는 않음

                             //데이터를 사용할 배열을 바로 사용하면 안되고 0부터 읽은 개수만큼만 사용해야 합니다.

                             //전체를 사용하는 경우 읽은 개수가 부족하면 이상한 결과를 만듭니다.

                             //txt파일은 bytes 읽으면 안된다 .깨진다.

                             String str = new String(split, 0 ,r); ///한글이 깨진다.

                             System.out.println(str);

                      }

               }catch (Exception e) {

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

               }

       }

 

 

 

 

메모리 저장해놓고 하는 것이 빠르다.

 

 

우리 코드는 jvm과 밖에 지원 못한다.

os가 자기가 지언한 것을 상용하는 것을 native method

java코드가 운영체제가 관리하는 자원을 사용하는 경우

java 코드 -> jvm->운영체제의 native method 호출

 

java코드가 native method를 자주 호출하면 효율이 떨어집니다.

이런 경우는 BATCH(일괄 -모아서 처리)처리르 고려

 

 

 

자바은 모아서 처리 할 수 잇는 스트림 제공

jvm이 알아서 버퍼를 만든다.

BYTE stream =>BufferedInputStream :다른 inputstream

                       PrintStream : 다른 outputstream(print라는 메소드를 가지고 있다.)

                       system.outprintstream이다.

 

Buffer:임시기억 장치 속도 차 떄문제 존재

Double Buffering

buffer단점 메모리를 많이 사용한다.

프린트도 같은 기능이다. 복사한 내용을 buffere 저장

한장일 경우 buffer이 필요없다. 속도가 늘어진다. 상황을 판단하면서 해야 한다.

 

awtdouble buffering 안한다.

swingdouble buffering 한다.

 

체팅 과 복사 등을 여러번한다. 그래서 메모리에 연다.

통상적으로 메로리에 하는 것이 좋다.

게임은 graphic을 가속한다.

 

출력은 바로 안하고 비운다.실제르는 PRINT하는 것이 아니라고 WRITE한다.

 

os.직접 대화하는 것은 assembly  , c 이다.

cunix

unix95%c언어와 assemble로 되여있다.

 

read - > jvm-> os->native method->

 

7)Buffer이용

=>입출력 명령은 우리가 자바코드로 작성하지만 실제 동작은 운영체제의 native method를 호출해야 합니다.

너무 잦은 입출력 명령은 운영체제의 효율을 떨어뜨려서 애플맄이션의 성능을 떨어뜨릴수 있습니다.

이런 경웬느 명령을 버퍼에서 모아서 한꺼번에 처리하는 것이 효율적일 수 있습니다.

=>버퍼를 이용하는   ByteStreamBufferedInputStream,PrintStream이 있습니다.

이 스트림들은 다른 스트림을 매개변수로 해서 인스턴스를 생성하고 이전 입출력명령을 그래도 사용할 수 있고 몇개의 추가된 메소드가 존재합니다.

=>자바는 명령을 수행하는 방식이 바뀌더라도 오버라이딩을 이용해서 명령을 추가하는 구조를 이용하기 때문에호출되는 메소드 이름은 그대로 입니다.

 

 

public class BufferInputOutput {

       public static void main(String[] args) {

               try(PrintStream ps = new PrintStream(new FileOutputStream("./src/java/buf.dat"));

                             BufferedInputStream bis = new BufferedInputStream(new FileInputStream("./src/java/buf.dat"));

                             ){

                      //기록하기

                      ps.println("Hello buffered Stream");

                      ps.flush();

                     

                      //전부 읽기

                      //읽을 데이터 크기 가져오기

                      int len = bis.available();

                      //읽은 데이터를 자장할 배열 생성

                      byte[] b  = new byte[len];

                      //데이터 읽기

                      bis.read(b);

                      //읽은 데이터를 문자열로 변환해서 출력

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

                     

               }catch(Exception e) {

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

               }

       }

}

 

8)기타 스트림

=>DataiInputStream & DataOutputStream

기본형(int , double, boolean)의 데이터를 읽고 쓸 수 있는 메소드를 제공하는 클래스

 

=>sequence Stream

여러 개의 스트림을 합쳐서 읽을 수 있도록 해주는 스트림

 

2.문자 스트림-  chracter stream

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

1)Reader

=>문자 입력 스트림의 최상위 클래스로 추상 클래스

void close();

 

int read();

int read(char[] buf);

int read(char[] buf,int start, int len);

 

2)Writer

=>문자 출력 스트림의 최상위 클래스로 추상 클래스

void close();

 

int write(String str);

int write(String str,int start, int len);

void flush();

 

3)FileReader

=>파일에서 문자 단위로 읽어 오기 위한 스트림

=>생성자

FileReader(String filepath);

FileReader(File file)

 

4)FileWriter

=>파일에 문자 단위로 기록 하기 위한 스트림

=>생성자

FileWriter(String filepath)

FileWriter(File file)

FileWriter(String filepath, boolean append) : 추가 모드 설정 기능

FileWriter(File file, boolean append): 추가 모드 설정 기능

 

5)BufferedReader

=>버퍼를 이용해서 문자 단위로 읽어 올 수 있는 스트림

=>생성자

BufferedReader(Reader in )

=>파일에서 읽어오는 Reader

new BufferedReader(new FileReader(파일 경로));

 

=>다른 intputStream으로 부터 읽어오는 Reader생성

new BufferedReader(new InputStreamReader(InputStream 인스턴스));

키보드로 부터 읽어오는 Reader : new BufferedReader(new InputStreamReader(Systme.in));

소켓에서 읽어올 때는 Socket.getInputStream()System.in대신에 대입합니다.

 

=>읽어오는 메소드로 readLine()을 제공

줄 단위로 읽어서 String으로 리턴하는 메소드

 

=>네트워크 상에서 문자열을 주고받을 때나 텍스트 파일을 읽을 때 이 스트림을 이용

 

6)PrintWriter

=>문자 단위로 버퍼을 이용해서 출력하는 클래스

PrintWriter(String 파일경로)

PrintWriter(File file)

PrintWriter(OutputStream outputStream)

PrintWriter(Writer writer)

 

=>출력을 할 때 print메소드를 사용하는 것이 가능

 

7)문자 단위로 기록하고 만들기

public class CharacterStream {

       public static void main(String[] args) {

               try(//파일에 문자 단위로 기록하기 위한 스트림

                             PrintWriter pw = new PrintWriter("./src/java/data.txt");

                             BufferedReader br = new BufferedReader(new FileReader("./src/java/data.txt"));

                             ){

                      pw.println("안녕하세요 반갑습니다.");

                      pw.println("내일 모래면 설날입니다.");

                      pw.flush();

                     

                      //파일의 내용을 읽기

                      while(true) {

                             //한줄 일기

                             String line = br.readLine();

                             // 읽었으면 중지

                             if(line == null) {

                                    break;

                             }

                             System.out.println(line);

                      }

               }catch(Exception e) {

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

               }

       }

}

 

0:0:0:0:0:0:0:1 - - [30/May/2017:16:59:23 +0900] "GET /library/ HTTP/1.1" 200 12223

get ->요청방식

HTTP/1.1

200 정상

 

 

500번대는 서버오류

12223 트래픽

 

8)log.txt파일을 읽어서 기술 통계값 구하기

=>하나의 문자열을 특정 문자로 분리하는 메소드:String [] split(String 구분자)

=>문자열을 정수로 변환하는 메소드Integer.parseInt(String 문자열)

=>텍스트 파일에 변환이 안되는 문자열을 포함시켰을 가능성이 있기 때문에 예외 처리를 해야 한다.

 

예외처리 발생 하는 것 조심해야 한다.

 

public class LogRead {

       public static void main(String[] args) {

               try(//파일에 문자 단위로 기록하기 위한 스트림

                             BufferedReader br = new BufferedReader(new FileReader("./src/java/log.txt"));

                             ){

                      //파일의 내용을 줄단위로 읽기

                     

                      //트래픽의 합계를 저장할 변수

                      int total = 0;

                      //접속한 Ip 주소를 중복없이 출력

                      HashSet<String> set = new HashSet<String>();

                      //접속한 ip 트래픽 합계

                      //Map에서 없는 key 사용하면 null 리턴

                      HashMap<String, Integer> map = new HashMap<String, Integer>();

                     

                      while(true) {

                             //한줄 일기

                             String line = br.readLine();

                             // 읽었으면 중지

                             if(line == null) {

                                    break;

                             }

                             //System.out.println(line);

                            

                             //공백을 기준으로 분할

                             String [] ar =line.split(" ");

                            

                             //ip 가지고 데이터가 있느느지 확인

                             Integer traffic =map.get(ar[0]);

                             //없는 데이터만 traffic 0

                             if(traffic == null) {

                                    traffic = 0;

                             }

                            

                             try {

                                    traffic += Integer.parseInt(ar[ar.length-1]);

                             }catch(Exception e) {}

                             //map 저장: 동일한 key 저장을 하면 업데이트

                             map.put(ar[0], traffic);

                            

                             //가장 마지막 데이터 출력

                             //System.out.println(ar[ar.length-1]);

                            

                             //set 첫번째 항목을 저장

                             set.add(ar[0]);

                            

                            

                             //11 line 192.168.0.2 - - [30/May/2017:17:03:02 +0900] "GET / HTTP/1.1" 404 994

                             //192.168.0.2 - - [30/May/2017:17:03:02 +0900] "GET / HTTP/1.1" 404 -

                             //가장 마지막 데이터를 정수로 변환해서 total 추가

                             //예외가 발생해서 중단되면  try ~ catch 감싸면 예외가 발생해도 계속 수행합니다.

                             try {

                                    total += Integer.parseInt(ar[ar.length-1]);

                             }catch(Exception e) {

                                   

                             }

                            

                      }

                     

                      System.out.println("트래픽 합계: "+total);

                     

                      //set  출력

                      for(String ip : set) {

                             System.out.println(ip);

                      }

                     

                     

                      //map key value 전부 출력하기

                      Set<String> keys= map.keySet();

                      for(String key : keys) {

                             System.out.println(key +" :" +map.get(key));

                      }

               }catch(Exception e) {

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

               }

       }

}

 

 

3.RandomAccessFile

=>일반적인 스트림을 이용하면 파일을 방향으로만 읽고 있습니다.

=> 읽은 데이터는 스트림을 다시 생성하지 않으면 다시 읽가나 없습니다.

=>읽고 쓰기가 모두 가능하고 한법 읽었던 데이터도 다시 읽을 있도록 만들어주는 파일 입출력 클래스

 

1)생성자

RandomAccessFile(String file, String mode)

RandomAccessFile(File file, String mode)

=>모드는 r(읽기 전용), rw(읽고 쓰기 가능) ,rws(쓰기한 데이터가 바로 반영되고 파일 정보도 바로 갱신), rwd(쓰기 한 데이터가 바로 반영되지만 파일 정보를 나중에 갱신)

 

 

2)메소드

void seek(long pos): 파일 포인터 (읽고 쓰기 위한 위치)pos 위치로 옮겨주는 메소드

 

void write(byte[] b): b의 내용을 파일 포인터 위치에 기록

 

int read(byte[] b): 파일 포인터 위치에서 b배열의 크기만큼 읽어서 b에 저장하고 읽은 개수를 리턴

 

long getFilePointer():현재 포인터의 위치를 리턴

public class RandomFileMain {

       public static void main(String[] args) {

               try (// 파일 읽고 쓰기 객체 생성

                             RandomAccessFile f = new RandomAccessFile("./src/java/random.txt", "rw");

                      ) {

                      //기록할 내용 생성

                      String msg ="hello random access file";

                      //문자열을 바이트 배열로 변환해서 기록

                      f.write(msg.getBytes());

                      //데이터 읽기

                      //파일 포인터를 읽을 위치로 이동

                      f.seek(0);

                      //5 읽기

                      byte[] b = new byte[5];

                      f.read(b);

                      //바이트 배열음 문자열로 변환해서 출력

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

                     

                      //파일 포인터를 시작위치로 다시 옮겨서 다시 읽어냄

                      f.seek(0);

                      //5 읽기

                      b = new byte[5];

                      f.read(b);

                      //바이트 배열음 문자열로 변환해서 출력

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

               } catch (Exception e) {

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

               }

       }

}

 

4.Serializable -객체 직렬화

=>파일 입출력의 기본 단위는 bytechar입니다.

=>실제 사용하는 데이터는 bytechar도 있지만 int와 기본형 데이터나 직접 만든 class의 인스턴스인 경우도 있습니다.

이런 데이터를 파일에 저장할려면 bytechar로 변환해서 저장해야 합니다.

읽을 때는 읽어온 데이터를 다시 원래의 자료형으로 변환해서 읽어야 합니다.

=>직접 만든 클래스의 인스턴스를 파일에 저장할 수 있도록 해주는 기능을 제공하는데 이 때 저장되어야 하는 클래스에 Serializable인터페이스를 implements해야 합니다.

 

=>ObjectInputStream ObjectOutputStream클래스를 이용해서 읽기 쓰기를 합니ㅏㄷ.

이 클래스들에서는 writeObjectreadObject라는 별도의 메소드가 제공되비낟.

 

=>이 방식으로 저장한 데이터는 저장할 때 사용한 클래스가 없다면 제대로 읽어 낼 수 가 없습니다.

응용프로그램이 만든 파일을 다른 응용프로그램이 읽으면 깨지는 현상

=

 

=>응용프로그램을 만들거나 데이터 통신을 할 때 Serializable을 고려 해봐야 합니다.

Andriod같은 경우는 화면과 화면이 데이터를 주고 받을 때 Serializable인터페이스를 구현한 데이터만 가능하도록 제한을 해둠

 

=>Serializable인터페이스는 classImplements만 하면 됩니다.

메소드를 구현할 필요가 없습니다.

 

=>몇몇 클래스로부터 상속받으면 경고가 발생하는 경우가 있는데 Seriablizavle인터페이스가 구현된 클래스로부터 상속을 받으면 SereaLVersion iD를 만들라고 경고가 발생합니다.

 

=>Wrapper(기본형 ->참조형).String , date, calendar, 자료구조 클래스(List, Set, Map)들은 SerializableIMPLEMENTS되어 있습니다.

 

=>DTO(DATA tRANSFER OBJECt -여러 개의 변수를 하나로 묶어서 표현하기 위한 클래스 Variable Class또는 Domain classs라고도 합니다.) 클래스를 만들어서 파일에 기록하고 읽어오기

DTOTable 을 설계할 때 구별이 되는 속성 (Primary key)은 정수로 만드는 것이 좋습니다.

회원정보를 만들 때 idemail등이 primary key가 될 수 있지만 데이터를 빠르게 조회하고 싶으면 정수를 하나 추가시켜서 이 항목을 primary key로 만드는 것이 좋습니다.

 

 

Unit

-      정수로 유닛번호

-      문자열로 유닛이름

-      숫자로 공경력

-      숫자로 방어력

-      숫자로 레벨

 

 

dict는 이름이 있어나

list set등은 이름이 없다.

 

public class Unit implements Serializable{

       private static final long serialVersionUID = 1L;

      

       private int num;

       private String name;

       private int offence;

       private int deffence;

       private int level;

      

       //매개변수가 없는 생성자 - 기본 데이터가 제공되지 않을 사용

       public Unit() {

               super();

       }

 

       //모든 속성을 매개변수로 받아서 생성해주는 생성자

       //기본 데이터가 제공될때 사용 -테스트 좋음

       public Unit(int num, String name, int offence, int deffence, int level) {

               super();

               this.num = num;

               this.name = name;

               this.offence = offence;

               this.deffence = deffence;

               this.level = level;

       }

      

      

       //접근자 메소드

       public int getNum() {

               return num;

       }

 

       public void setNum(int num) {

               this.num = num;

       }

 

       public String getName() {

               return name;

       }

 

       public void setName(String name) {

               this.name = name;

       }

 

       public int getOffence() {

               return offence;

       }

 

       public void setOffence(int offence) {

               this.offence = offence;

       }

 

       public int getDeffence() {

               return deffence;

       }

 

       public void setDeffence(int deffence) {

               this.deffence = deffence;

       }

 

       public int getLevel() {

               return level;

       }

 

       public void setLevel(int level) {

               //레벨이 변경될 offence값이 자동으로 다시 계산됨

               this.level = level;

               offence = offence + level * 10;

       }

      

       //모든 속성의 값을 하나의 문자열로 만들어서 리턴해주느 메소드

       //출력하는 메소드에 인스턴스 이름을 대입하면 메소드가 호출됩니다.

       //모든 객체 지향언어는 방식을 이용해서 출력합니다.

       //메소드 이름이 다를 뿐입니다. (python 다르다.__str__)

       @Override

       public String toString() {

               return "Unit [num=" + num + ", name=" + name + ", offence=" + offence + ", deffence=" + deffence + ", level="

                             + level + "]";

       }

      

}

 

=>Main메소드

public class SerializableMain {

       public static void main(String[] args) {

               Unit unit = new Unit(1,"탱크" , 10 , 10 ,0);

               System.out.println(unit);

               unit.setLevel(1);

               System.out.println(unit);

              

               //byte char(String) 아닌 데이터를 읽고 때는 ObjectOutputStream.

               //ObjectInputStream 이용

              

               try(ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("./src/java/star.dat"));){

                      //오류 난다.

                      //PrintStream ps = new PrintStream(new FileOutputStream("./src/java/star.dat"))

                      //pw.write(unit)

                     

                      //이렇게 저장하면 unit.toString() 결과가 저장

                      //PrintWriter pw = new PrintWriter("./src/java/star.dat");

                      //pw.print(unit);

                     

                      //데이터 기록 : unit 클래스인 Unit Serializable인터페이슬 구현하지 않았다면

                      //ClassCastException 발생 - 변환이 안된다고 예외 발생

                      oos.writeObject(unit);

               }catch(Exception e) {

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

               }

       }

}

 

public class SerializableMain {

       public static void main(String[] args) {

               Unit unit = new Unit(1,"탱크" , 10 , 10 ,0);

               System.out.println(unit);

               unit.setLevel(1);

               System.out.println(unit);

              

               //byte char(String) 아닌 데이터를 읽고 때는 ObjectOutputStream.

               //ObjectInputStream 이용

              

               try(ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("./src/java/star.dat"));

                             ObjectInputStream ois = new ObjectInputStream(new FileInputStream("./src/java/star.dat"));){

                      //오류 난다.

                      //PrintStream ps = new PrintStream(new FileOutputStream("./src/java/star.dat"))

                      //pw.write(unit)

                     

                      //이렇게 저장하면 unit.toString() 결과가 저장

                      //PrintWriter pw = new PrintWriter("./src/java/star.dat");

                      //pw.print(unit);

                     

                      //데이터 기록 : unit 클래스인 Unit Serializable인터페이슬 구현하지 않았다면

                      //ClassCastException 발생 - 변환이 안된다고 예외 발생

                     

                      //여러번 있을 경우 os에도 안좋고 작성하기도 번거럽다.

                      /*oos.writeObject(unit);

                     

                      Unit unit1 = new Unit(2,"마린" , 5 , 5 ,0);

                      System.out.println(unit1);

                      oos.writeObject(unit1);

                     

                      System.out.println("================");

                      //데이터 읽어오기 serializable 데이터

                      Unit unit2 = (Unit)ois.readObject();

                      System.out.println(unit2);

                      Unit unit3 = (Unit)ois.readObject();

                      System.out.println(unit3);*/

                     

                      //아래 방식으로 하면 한번씩 쭐어 들었다.

                      Unit unit1 = new Unit(2,"마린" , 5 , 5 ,0);

                      ArrayList<Unit> list = new ArrayList<Unit>();

                      list.add(unit);

                      list.add(unit1);

                      oos.writeObject(list);

                     

                      //list 저장한 데이터 읽어오기

                      ArrayList<Unit> read = (ArrayList<Unit>)ois.readObject();

                      for(Unit u: read) {

                             System.out.println(u);

                      }

               }catch(Exception e) {

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

               }

       }

}

 

 

5.AutoClosable

=>try()안에서 생성한 자원을 자동으로 해제할 수 있도록 해주는 인터페이스

AutoClosable 인터페이스가 구현된 클래스는 try()안에서 생성하면 close()를 호출할 필요가 없습니다.

 

**네트워크

1. 용어

1)Protocol:통신을 하기 위한 큐칙. 규약 , 약속

=>통신을 하고자 할 때는 protocol이 같아야만 통신이 가능

 

2)IP Address(IP주소):하나의 단말기(기계)를 구분하기 위한 주소 체계

=>IPv4 :32비트 주소 -  0~255.0~255.0~255.0~255

=>IPv6 :128비트 주소 - 4비트씩 묶어서 16진수 그리고 다시 4개씩 묶어서 : 으로 구분

0000:0000:0000:0000:0000:0000:0000:0000

FFFF:FFFF:FFFF:FFFFF:FFFF:FFFF:FFFF:FFFF

=>IP주소는 국가 별로 할당

=>자신의 IP: 127.0.0.1 또는 0000:0000:0000:0000:0000:0000:0000:0000

 

 

=>사설 IP: 10.x.x.x , 192.168.x.x , 172.16.x.x ~ 172.31.x.x

 

3).port:하나의 단말기에서 서비스를 구분하기 위한 번호

0-65535

=>서비스가 애플리케이션

 

4)통신을 할 때는  ip주소  port번호가 같이 필요

5)0-1023번 까지의 포트번호는 예약

1521 : 오라클

3306: mysql

27017 :mongodb

tomcat: 8080

 

6.domain:IP주소를 문자열로 변경한 것

사람이 알아보기 쉽게 하기 위해서 만든 것

 

7)URL:인터넷 상의 자원의 위치

8)URI:특정 자원에 대한 고유한 이름

UIRURL보다 큰 개념

 

반응형

'Study > Java' 카테고리의 다른 글

java-16  (0) 2020.10.10
java-15  (1) 2020.10.05
java-13  (0) 2020.10.03
java-12  (0) 2020.10.02
java-11  (0) 2020.10.01

+ Recent posts