티거의 개발 공간

이클립스는 한글폰트가 매우 이상하다. 한글폰트가 뭉개져 잘 보이지도 않는다.
그래서 필자는 컴퓨터를 포맷하거나 이클립스 프로젝트 폴더를 새로 생성하면 바로 폰트부터 바꾼다.

 


 

 

 

이클립스 상단바에서 Window  - Preferences 를 클릭하면 나타나는 창이다.
이 설정창 왼쪽 카테고리에서 General - Appearance - Colors and Fonts 를 클릭한다.

그리고 중앙의 카테고리에서 Basic을 열어 Text Font를 선택한 후 'Edit...' 버튼을 클릭한다.

 

 

필자는 네이버에서 배포하는 '나눔고딕코딩' 폰트를 주로 사용한다. 사용할 폰트를 선택한 후
'확인' 버튼을 누르고 설정창에서 OK 또는 Apply 버튼을 눌러 적용시키면 완료된다.

 

 

위의 사진은 '나눔고딕코딩' 폰트가 정상 적용된 모습이다.

 

 

p.s. 아무리 생각해도 코딩 기본 폰트는 Visual Studio가 짱이다...

아래 암호화 알고리즘은 여러가지 인코딩 방식을 제공해주고 있는 Apache Commons Codec
라이브러리를 사용한다. 이 라이브러리는 게시물 하단에 링크를 걸어두겠다.

 


 

 암호화 부분
인자값은 순서대로 (암호화할 문자열, 비밀번호 문자열) 이다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public String Encryption(String str, String pw) throws Exception{
    byte[] bytes = pw.getBytes();
    SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
    sr.setSeed(bytes);
    KeyGenerator kgen = KeyGenerator.getInstance("AES");
    kgen.init(128, sr);
    
    SecretKey skey = kgen.generateKey();
    SecretKeySpec skeySpec = new SecretKeySpec(skey.getEncoded(), "AES");
    Cipher c = Cipher.getInstance("AES");
    c.init(Cipher.ENCRYPT_MODE, skeySpec);
    
    byte[] encrypted = c.doFinal(str.getBytes());
    return Hex.encodeHexString(encrypted);
}
 
cs

 

 

복호화 부분
인자값은 순서대로 (복호화할 문자열, 비밀번호 문자열) 이다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public String Decryption(String str, String pw) throws Exception{
    byte[] bytes = pw.getBytes();
    SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
    sr.setSeed(bytes);
    KeyGenerator kgen = KeyGenerator.getInstance("AES");
    kgen.init(128, sr);
    
    SecretKey skey = kgen.generateKey();
    SecretKeySpec skeySpec = new SecretKeySpec(skey.getEncoded(), "AES");
    
    Cipher c = Cipher.getInstance("AES");
    c.init(Cipher.DECRYPT_MODE, skeySpec);
    byte[] decrypted = c.doFinal(Hex.decodeHex(str.toCharArray()));
    return new String(decrypted);
}
 
cs

 

 


 

 

실행 결과

 


 

하단은 Apache Commons Codec 라이브러리를 배포하고있는 Apache 페이지이다.

 

 

소프트웨어공학과 대학교연계 스터디그룹 과제로 모래시계 알고리즘을 분석하는
내용이 나왔다. 여러 언어로 구현할 수 있는 알고리즘이나, 내가 사용하는 주 언어는 자바이므로
자바를 이용해 구현해보겠다.
자바에서 모래시계 알고리즘을 구현하는 것은 꽤나 쉽다.

 


 

모래시계 알고리즘의 출력물은 아래와 같다

1234567
0234560
0034500
0004000
0034500
0234560
1234567

위처럼 2차원 배열에 모래시계 형태로 숫자들을 배열하는 것이 모래시계 알고리즘이다.
안타깝게도 int 배열에서는 빈공간을 출력하지는 못한다. 아무것도 채워지지 않은 공간은
null로 처리되어 출력되기 때문인데, 그런 상황을 피하고자 빈공간을 0으로 채웠다.

 


 

 아래는 모래시계 알고리즘을 구현한 소스코드이다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public static void main(String[] args) 
    {
        int row = 7;
        int line = 7;
        
        int[][] a = new int[row][line];
 
        int c = (row/2)+1;
        int t, j, q = 0;
        int small = 1;
        int large = line;
 
        for(t = 0; t < row; t ++){
            q = small;
 
            if(small>1for(int y = 0; y < small-1; y++) a[t][y] = 0
            
            for(j = small-1; j<large; j++){
                a[t][j] = q;
                q = q+1;
            } 
 
            if(large<line) for(int z = large; z < line; z ++) a[t][z] = 0;
            
            if(t+1<c){ 
                small = small + 1;
                large = large - 1;
            } else { 
                small = small - 1;
                large = large + 1;
            }
        }
 
        for(int i = 0; i < row; i ++){
            for(int k = 0; k < line; k ++){
                System.out.print(a[i][k]);
            }
            System.out.println();
        }
    }
 
cs

 

행과 열의 정보를 갖는 row 와 line은 Scanner 변수를 이용해 입력을 받아 사용할 수 있다.
다만 이 모래시계 알고리즘은 행과 열이 홀수여야만 정상적으로 출력된다.

변수가 어떻게 변하는지 출력이 어떻게 되는지 한번 직접 손으로 써보면서 하면 더욱 잘 이해가 된다.

java.util.ConcurrentModificationException

이 예외는 흔히 List나 ArrayList를 for 문에 직접 집어넣고 돌리며 remove를 호출했을 때 발생한다.

1
2
3
4
5
6
ArrayList<String> list = new ArrayList<String>();
//~ ~ ~        
for(String name : list){
    list.remove(name);
}
 
cs

 

 위의 메서드를 실행할 때 예외가 발생한다는 건데,

위의 for 문은 list에서 index를 비교하며 그에 맞는 값을 name에 넣어주고 돌리는 식이다.
그런데 돌리는 도중 remove를 호출하면 기존 index 값과 remove 호출로 인해 줄어든 size 값이 맞지 않기 때문에 예외가 발생한다. 

 


 

해결법 [1]

 

1
2
3
4
5
6
7
8
9
ArrayList<String> list = new ArrayList<String>();
~ ~ ~
            
ArrayList<String> Remove = new ArrayList<String>();
for (String name : list) 
    Remove.add(name);
for (String name : Remove) 
    list.remove(name);
 
cs

 

 위의 예외를 피하기 위해서 삭제해야 할 리스트(이하 Remove)를 따로 만들고, Remove를 for 문에 집어넣어 돌려 list를 제거하는 형식이다.

하지만 이 방법은 효율적이지 않으며 속도도 느리다고 한다.

 


 

 

해결법 [2]

 

 

1
2
3
4
5
6
7
8
9
ArrayList<String> list = new ArrayList<String>();
~ ~ ~
 
Iterator<String> iter = list.iterator();
while (iter.hasNext()) {
    String s = iter.next();
    iter.remove();
}
 
cs

 

 위의 방법은 반복자(Iterator)를 이용하는 방법이다.
.remove() 메서드보다 무조건 .next() 메서드가 먼저 호출되어야만 예외가 발생하지 않는다.
해결법 1보다는 이 방법이 더 효율적이고 쓸모없는 코드들이 없다 하니 이 방법을 많이 사용하는 것을 권장한다.

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

자바 AES 암호화, 복호화  (0) 2017.04.02
자바 모래시계 알고리즘  (0) 2017.04.02
이클립스 테마 변경하기  (0) 2017.04.02
이클립스 기본인코딩 변경하기(UTF-8)  (0) 2017.04.01
자바 소켓통신하는법  (0) 2017.04.01

이클립스를 처음 설치하면 하얀색 배경으로 개발환경이 잡히는데
하얀색 배경을 오래 보고 사용하면 눈이 아파진다.
그래서 검정색 배경으로 바꾸면 눈이 덜 아프다고 하길래 바꾸어보았다.

 


 

이클립스의 상단바를 보면 Help탭이 있다
클릭하면 Eclipse Marketplace... 라는 항목이 있는데 이를 클릭해보자.

 

 

클릭하면 아래와 같은 창이 뜨는데 인터넷에 접속하고 로딩되는데 꽤 시간이 걸린다.

 

 

위의 사진에서 왼쪽 상단에 보면 Find 라는 곳이 있다.
이곳은 검색창인데 'Color Theme' 라고 친 후 엔터를 눌러 검색을 해주자.

 

 

그럼 위와 같이 나올텐데, 맨위의 Eclipse Color Theme 1.0.0 을 install 버튼을 눌러 설치해주자.
필자는 이미 설치를 하고 사용중이기 때문에 Installed 로 나온다.

 

 

install 버튼을 누르고 Confirm 버튼을 누르면 위와 같은 창이 나타나는데
이 창은 약관동의다 동의 안하면 설치가 안되니 오른쪽 하단의
'I accept the terms of the license agreements' 에 체크 후 Finish를 눌러준다.

그러면 설치가 진행되는데 설치가 다되면 이클립스를 껐다 키라고 할 것이다.
껐다 키고 아래를 진행하면 된다.

 

 

이클립스의 상단 바에서 Window - Preferences 항목에 들어가자

 

 

그럼 위와 같은 창이 나타나는데 왼쪽 카테고리에서 General - Appearance - Color Theme 에 들어가서 Obsidian 을 클릭한 후 Ok 또는 Apply 를 눌러주면 테마 적용이 끝난다.

물론 Obsidian 이 아닌 다른 테마도 있지만 필자는 이 테마가 가장 편하고 눈에 피로감이 별로 없다.

 


 

+ 추가글

Color Theme만 적용하면 코딩 구역만 테마가 적용되는데 다른 패키지 익스플로러 같은 부분들은 아래 과정을 따르면 같이 어두운색으로 변한다.

 

 

이클립스 상단바에서 Window - Preferences 를 클릭하면 나타나는 창이다.
왼쪽의 카테고리에서 General - Appearance 를 클릭하고 Theme 부분을 Dark로 바꿔주면 같은 어두운색으로 바뀌게 된다.

이클립스를 사용하면서 다른 프로젝트를 불러오거나

맥이나 리눅스에서 코딩하던것을 윈도우로 가져올때 가끔 한글이 완전히 깨져서 나오는 경우가 있다.

 

이 때는 인코딩이 맞지 않아서 생기는데
이클립스를 처음 설치했을 때 윈도우의 기본인코딩은 'MS949' 인코딩을 사용한다.
하지만 맥이나 리눅스 계열에서 이클립스를 처음 설치하면 기본인코딩은 'UTF-8' 인코딩을 사용한다.

프로젝트에 열기에 알맞은 인코딩을 선택해 열어야한다.
하지만 대부분은 UTF-8을 사용하고 오류가 별로 없기에 UTF-8 사용을 권장한다.

아래의 작업을 진행하기 전, 코딩 중인 파일을 저장하지 않고 인코딩을 바꿀 시 저장에러가 나올 수 있다. 다 저장 후 닫고 아래의 작업을 진행하자.


 

 

이클립스 상단 바에 Window 를 클릭하면 Preferences 가 있다.

 

 

클릭하면 환경설정창이 나오게 되는데, 왼쪽 카테고리에서 General - Workspace 를 클릭해준다.
그럼 위와 같은 설정화면이 나오는데 설정창 왼쪽 하단 'Text file encoding' 에 있는 것중에
Other 체크 후 콤보박스를 내려 UTF-8로 설정해준다.

그리고 OK나 Apply 를 눌러주면 적용이 된다.

 


 

 

위의 작업을 마치면 .java 파일을 이클립스로 열 때 기본인코딩 UTF-8로 열려지는데
기존에 MS949로 코딩했던 파일이 있다면 프로젝트나 파일별로 기본인코딩을 설정할 수 있다.
 

 

프로젝트 파일 오른쪽 클릭 후 하단에 Properties 클릭

 

 

그리고 왼쪽 카테고리에 Resource 를 클릭하고 'Text file encoding' 에서 Other 체크 후에 콤보박스를 내려 UTF-8 을 선택해준 후 OK 또는 Apply 를 누르면된다.

콤보박스에 MS949 항목이 없는데 MS949로 설정하고 싶다면 콤보박스를 내리지 말고 직접 MS949를 입력해 수정하면 된다.

자바 소켓통신 하는 코드는 아래와 같다.

 


 

[ Server.java ]

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
import java.net.*;
import java.util.*;
import java.io.*;
 
class Server
{
 
    private static int port = 0;
 
    public static void main(String[] args) 
    {
        System.out.println("SERVER PROGRAM");
        Scanner scan = new Scanner(System.in);
        while(true){
            System.out.print("[SYSTEM] Type Port : ");
            String ports = scan.nextLine();
            try{
                port = Integer.parseInt(ports);
                if(port <= 0 || port > 9999){
                    System.out.println("[SYSTEM] Wrong Port!");
                    port = 0;
                } else break;
            } catch(Exception e){ System.out.println("[SYSTEM] Wrong Port!"); }
        }
        openServer();
    }
 
    private static void openServer(){
        try{
            ServerSocket server = new ServerSocket(port);
            System.out.println("[SYSTEM] Server Started ["+port+"]");
            System.out.println("[SYSTEM] Wait Client...");
            Socket socket = server.accept();
            System.out.println("[SYSTEM] Connect! ["+socket.getInetAddress()+"]");
        
            InputStream is = socket.getInputStream();
            DataInputStream dis = new DataInputStream(is);
            OutputStream os = socket.getOutputStream();
            DataOutputStream dou = new DataOutputStream(os);
 
            while(true){
                String msg = dis.readUTF();
 
                if(msg.equalsIgnoreCase("exit")){
                    dou.writeUTF("exit");
                    System.out.println("[SYSTEM] Shutdown Server");
                    socket.close();
                    server.close();
                    break;
                } else {
                    System.out.println("[CLIENT] " + msg);
                    dou.writeUTF("Data Received : " + msg);
                }
            }
        } catch(Exception e){
            System.out.println("[SYSTEM] Failed to open server");
        }
    }
 
}
 
 
cs

 

 


 

 

 

[ Client.java ]

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
import java.io.*;
import java.net.*;
import java.util.*;
 
class Client 
{
 
    private static int port  = 0;
    private static String ip = "";
 
    public static void main(String[] args) 
    {
        System.out.println("CLIENT PROGRAM");
        Scanner scan = new Scanner(System.in);
        System.out.print("[SYSTEM] Type Ip: ");
        ip = scan.nextLine();
        while(true){
            System.out.print("[SYSTEM] Type Port : ");
            String ports = scan.nextLine();
            try{
                port = Integer.parseInt(ports);
                if(port <= 0 || port > 9999){
                    System.out.println("[SYSTEM] Wrong Port!");
                    port = 0;
                } else break;
            } catch(Exception e){ System.out.println("[SYSTEM] Wrong Port!"); }
        }
        
        Connect();
    }
 
 
    private static void Connect(){
        try{
            Socket socket = new Socket(ip, port);
            System.out.println("[SYSTEM] Server Connected ["+port+"]");
            InputStream is = socket.getInputStream();
            DataInputStream dis = new DataInputStream(is);
 
            Scanner scan = new Scanner(System.in);
            while(true){
                System.out.print("[SYSTEM] Type Message : ");
                String msg = scan.nextLine();
                
                OutputStream os = socket.getOutputStream();
                DataOutputStream dos = new DataOutputStream(os);
                dos.writeUTF(msg);
 
                String remsg = dis.readUTF();
    
                if(remsg.equalsIgnoreCase("exit")){
                    System.out.println("[SYSTEM] Shutdown Client");
                    socket.close();
                    break;
                } else
                System.out.println("[SERVER] " + remsg);
            }
 
        } catch(Exception e){
            System.out.println("[SYSTEM] You can not access the server");
        }
    }
}
 
 
cs

 

 


 

서버와 클라이언트 두개의 클래스가 있으며

서버 클래스를 먼저 실행시켜준 뒤 서버를 개방할 포트 입력 후

클라이언트 클래스를 실행시켜 접속할 아이피, 포트 입력하면

접속되어 소켓통신이 가능하다.

 

그리고 접속 포트와 서버 포트는 1~9999번으로 제한했지만,

실제로는 1~65565번까지 사용가능하다는거 같다.

자신의 공인아이피를 보여줄 사이트인 http://ipip.kr 이다.

웹 구조가 가장 간단하게 잘 나와있어 파싱하기 쉽다.


------------코드


public static void main(String[] a){

                

String IP = null;


try{

                        //파싱 할 사이트를 URL로 선언한다.

URL u = new URL("http://ipip.kr");

                        InputStreamReader input = new InputStreamReader(u.openStream());

BufferedReader br = new BufferedReader(input);


String Line;


while((Line=br.readLine())!=null) System.out.println(Line);


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

    }


--------------결과



<head>

<title>Your IP is (자신의아이피)</title>

</head>

<html>


<head>

<meta http-equiv="content-type" content="text/html; charset=euc-kr">

<title>++ ipip.kr ++</title>

<meta name="generator" content="Namo WebEditor v5.0">

</head>


<body bgcolor="#BBFFFF" text="black" link="blue" vlink="purple" alink="red">

<br><br><br><br>

<table align="center" cellpadding="0" cellspacing="0">

 (===========중략============)

</table>

<p align="center"><b><font color="#3399FF"><span style="font-size:10pt;">Your 

IP is&nbsp;</span></font><font color="#0066FF"><span style="font-size:11pt;">(자신의아이피)</span></font></b></p>

<p align="center"><b><font color="#0066FF"><span style="font-size:11pt;">&nbsp;</span></font></b></p>

<p align="center"><b><font color="red" face="맑은 고딕"><span style="font-size:11pt;"></span></font></b></p>

<br>

<font color="#0066FF"><br><center><span style='font-size:9pt'>[ ipip.kr은 트래픽 부하 없이 간단하게 자신의 IP를 보여주는 사이트입니다. ]<br><br><br>Copyright @ 2000~2013 HACKERSCHOOL All right reserved.

<br>

</body>

</html>




이런식의 결과가 나오게 되는데 (자신의아이피) 라고 써저있는 곳은 파싱했을 때 파싱한 컴퓨터의 공인아이피가 나오는 자리이다

간단하게 보기 위해서는 아래 복잡한 부분이 아닌 위의 <title> 부분의 아이피를 replace 로 추려내어

쉽게 아이피 값만 얻어 올 수 있다.


부가적으로

<title>Your IP is (자신의아이피)</title>


이 구문에서 자신의 아이피만 남기고 모두 지우는 방법은

replace를 사용해 자신의 아이피만 남기고 앞 뒤를 모두 빈칸으로 치환해버리면 간단하게 끝난다.