잊을만 하면 한번씩 올라오는 '나는야 버그 제조기' 시리즈 ....
이번에는 최근 진행중이던 프로젝트 중 파일 전송부분을 개선 하는 과정에서 발생했었다.
대용량 파일 전송을 하기 때문에, 파일을 지정한 용량 별로 쪼개고 클라이언트쪽으로 하나씩 보내는 로직이었는데
가뜩이나 대용량인데 그걸 용량별로 쪼개는것도 디스크의 I/O때문에 시간을 많이 소모해서, 실제로는 쪼개지않고 보내는 데이터만 종전과 같이 보내도록 리팩토링을 했다.
그런데, 가상으로 쪼갠 파일을 합쳐서 md5 체크를 하는 단위테스트에서는 성공을 했는데, 네트워크 전송을 하는 테스트는 중간에 InputStream 에서 데이터를 읽지 못해서 에러가 발생하는 현상이 있었다.
한참을 디버깅을 하다가,
혹시(?) 해서 의심해본것이 ~~~~File.setPosition(long position) (파일 이어보내기의 경우, 설정한 위치부터 보낸다)
대략 이런 코드였다 ..
[CODE type="java"]public void setPosition(long position){
...
in.skip( position) ;
...
}
[/CODE]
종전에는 파일 클래스 별로 InputStream 이 있어서 저 method 가 이런 버그를 낼 줄은 생각을 못했다. 이번에는 InputStream 공유해서 쓰기때문에, 저 method 를 여러번 호출하게 되면
읽지도 않았는데 그냥 position 만큼 건너뛰면서 읽어서, 나중에는 더이상 읽을 데이터가 없어서 나던 버그였다.
다음과 같이 고쳐줬다 -_-;;
[CODE type="java"]public void setPosition(long position){
...
in.reset();
in.skip( position) ;
...
}
[/CODE]
오늘 약간 큰 단위 테스트를 하면서 InputStream 으로 되어있던걸
아무래도 같은 부분이 두번 정도 읽히고 skip 하는경우도 종종 있어서
RandomAccessFile 로 바꾸고
randomFile.seek( position ) ; 으로 바꿨다.
'컴퓨터/Java'에 해당되는 글 28건
- 2008/11/14 나는야 버그 제조기 3
- 2008/07/06 Eclipse 개발환경에서 JDK제대로 설정하기 (3)
- 2008/05/17 Eclipse Visual Editor 플러그인 설치 (11)
- 2007/07/19 jateon 0.22b / 0.17a release (1)
- 2007/06/16 Jemote 삽질중 (5)
- 2007/05/24 나는야 버그 제조기 2 (5)
- 2007/02/19 javascrpt 의 escape 함수를 java로 구현 (8)
- 2007/02/15 JFrame 뜨면서 포커싱이 안가게 하기 (1)
- 2006/12/21 한글입력기 (3)
- 2006/09/10 java socket encoding 삽질기 (3)
이클립스를 쓰고 있는 사람들을 보다보면
BUILD_PATH를 JDK가 아닌 기본으로 잡히는 JRE를 쓰고 있는 것을 종종 보게 된다.
쓰는 사람이 별 불편함이 없게 느낀다면 상관없지만,
어쨌든 내 입장에서 보면 불편하다 -_-;;
이번 팁은 며칠 전 릴리즈 된 eclipse ganymede 를 기준으로 진행하겠다.
(이전버전도 별 차이는 없으니 신경쓰지 말자)


뒤에 인자들이 arg0, arg1, arg2.... 오잉
무언가 이상하다!!
F3 을 눌러 소스코드를 한번 보자..

패키지 탐색기쪽을 자세히 보자..
JRE 시스템 라이브러리..
JRE엔 당연히! 소스코드가 없다.
오직 실행만을 위한 Java Runtime Environment 이기 때문이다

그렇다면 해결책은?
build path 에 잡혀있는 JRE를 JDK로 바꿔주면 되는것이다....
JDK 설치가 되어있지 않다면, 우선 설치부터 ㄱ


설치된!? JRE 목록...
설치된 JRE들이 아니라 이클립스에서 인식하고 있는 JRE들이다..
Search 를 누르고


어쨌든 jdk 1.6.0_10 으로 선택하고 OK

자 그러면 방금전 그 소스코드로 다시 돌아가보자.
적절한 이름들이 들어가 있는걸 확인할수 있다.
Thread 에서 F3을 눌러서 소스코드를 살펴보자

이왕이면 JRE 보다는 JDK로 잡아놓고 개발하는 것이 편하지 않겠는가!
어쨌든, 문제 해결!
Visual Studio 같은 IDE에서는 기본으로 UI 디자인을 쉽게 할 수 있다.
Netbeans 도 있긴하지만 외부 패키지를 import 해서 써야하므로 좀 껄끄럽다.
이클립스에도 이러한 플러그인이 있으니,
알만한 사람들은 알만한 이클립스의 visual editor 플러그인
UI 디자인을 쉽게 할 수 있는 툴이다

이 플러그인이 이클립스 3.2에서는 쉽게 설치가 되었으나, 3.3으로 넘어가면서 약간 까칠해졌다 -_ -;
지금부터 설치 방법을 적어보도록 하겠다.

사실 어느 패키지를 사용해도 별 문제가 없다.
이클립스 프로젝트에 보면 VEP가 있긴한데 그 곳은 오래된 버전이라, Visual editor 위키페이지에 설치방법이 나와있다.


이클립스 실행!

메뉴의 Help > Software Updates > Find and Install...
Search for new features to install 선택
New Local Site 버튼을 눌러 Visual Editor 플러그인의 압축을 푼 폴더를 선택해준다.
업데이트 사이트는 아래에 선택되어있는 Europa Discovery Site와 방금 추가한 로컬 사이트를 선택해준다.
나머지는 스샷을 보고 따라하면 별 무리 없을것이라 생각된다.


당황하지말고 Select Required 를 눌러보자...
오류가 사라지지 않는다면 아래 화면처럼 Europa Discovery Site 를 펼친뒤에 다시 Select Required 를 눌러본다(필요한 패키지들이 자동으로 선택될 것이다).

이후에는 프로그램 설치하듯이 진행하면된다.
설치가 끝나면 이클립스를 재시작 할거냐고 묻는데 재시작을 해주자.
설치가 끝났으니 테스트 -_-)/
아래 그림들은 프로젝트 생성하는 과정이다.


그 외에도 밑에 AWT/Swing/SWT등등이 있으니 적절히 써보도록 하자.

스타일에서 Swing - Frame 를 선택, 클래스 이름과 몇가지 옵션을 선택해줬다.
Visual Editor 가 적용된 Eclipse

사실 자바 책같은곳에 보면 대부분 Layout Manager 를 사용해서 코딩을 하지만,
null 을 선택하게되면 원하는 위치에 Swing Component들을 배치 할 수있다.
하지만 웬만하면 레이아웃 매니저를 쓰는걸 권장하고 싶다.


간단한 프로그램 같은 경우는 무시해도 되겠지만,
규모가 커질듯한 프로그램이나, 여럿이서 공동작업을 한다고하면 .....
버튼을 만들었으니 이벤트를 연동 해보자!

한글로 적으면 제대로 입력이 되질 않는다 -_-;
밑의 프로퍼티에 입력을 하거나, 코드상에서 직접 써주자.
버튼에서 오른클릭 > Events 에 가보면 눈에 익은 문구가 하나 보인다
actionPerformed ! 버튼에 대한 기본 동작인데...
Add Events 를 선택해보면 AddKeyListener, MouseListener 등등 여러가지들이 나온다.
어찌되었건 기본 동작인 actionPerformed 를 선택
실행해보자!!
하지만 이 플러그인으로 디자인을 하고 소스코드를 보면 상당히 지저분해지기(컴포넌트 하나 추가할때마다 get~~~~~~ 이런 method 가 생김) 때문에, 생성된 코드를 직접 정리 해주는것이 좋다.

참 쉽죠?
자테온 0.22b 와 0.17a 를 릴리즈 합니다.
아시는분은 아시겠지만 0.2x 버전은 swt 를 이용한것이고
0.1x 버전은 swing 을 이용한것입니다.
swt 가 지원되지 않는 환경이나, swing 버전을 원하시는 분들이 간혹계셔서
swing 버전을 이렇게 릴리즈 하게 되었습니다.
간혹 로그인이 안된다고 하시는 분들이 계신데,
테스팅 해 주실수 있으신분들은 자테온 포럼에 글을 남겨주시거나 쪽지를보내주시면 감사하겠습니다.
0.17a 버전 변경사항은 README_swing.txt 파일을 보시면 되겠습니다만,
리소스 (아이콘 이미지, 사운드) 파일들을 jar 밖으로 분리했습니다.
Look and Feel 버그를 수정했고,
pure java code를 목표으로 했기때문에 JNI를 사용해서 구현했던 트레이는 뺐습니다.
0.22b
리소스 파일을 분리했습니다.
대화창 포커싱 문제 고쳤습니다 -_-
그룹관련 기능 추가했습니다.
기타 수정사항은 README.txt 파일을 읽어보세요
자테온은 포럼에서 구하실 수 있습니다.
http://jateon.kfmes.com
Jemote ?
Java Remote Desktop
보기에는 그럴싸하게 보일 수 있으나
버그가 상당히 있고,
개선해야될 점이 많은 -_-a
나는야 버즈 제조기 2탄 -_-;
몇분전까지의 자테온의 코드 일부였다.
[CODE type="java"] public ChatWindow getChatWindow(SwitchBoardSession ss, NateFriend fr) {
[tab]ChatWindow cw = chatdlgMap.get(ss);
[tab]if(cw==null){
[tab][tab]for(ChatWindow c : chatdlgMap.values()){
[tab][tab][tab]
[tab][tab][tab]NateFriend cf = c.getLastRecvUser();
[tab][tab][tab]if(cf!=null && cf.equals(fr));
[tab][tab][tab][tab]return c;
[tab][tab]}
[tab]
[tab]}
[tab]return cw;
} [/CODE]
A 와 대화중인데, 갑자기 B가 대화를 걸어왔을때,
황당하게도 같은 채팅창에 뜨는 버그가 있었다.
위의 코드때문에 생긴 버그였다
<자세히보기...>
javascript 에 있는 escape 함수가 필요해져서 삽질을 시작했다.
자바 스크립트로 테스트 html 페이지 만들어
ASCII 코드 ~127 까지 넣어보면서 -_- 삽질을 했다.
[CODE type="java"]public static String escape(String string){
[tab]StringBuffer sb = new StringBuffer();
[tab]String ncStr = "*+-./0123456789@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz";
[tab]char c;
[tab]
[tab]for(int i=0;i<string.length();i++){
[tab][tab]c = string.charAt(i);
[tab][tab]if(c>0x7f){
[tab][tab][tab]sb.append("%u");
[tab][tab][tab]sb.append(Integer.toHexString((int)c).toUpperCase());
[tab][tab]}
[tab][tab]else if(ncStr.indexOf((int)c)==-1){
[tab][tab][tab]sb.append('%');
[tab][tab][tab]if(c<=0xf)
[tab][tab][tab][tab]sb.append('0');
[tab][tab][tab]sb.append(Integer.toHexString((int)c).toUpperCase());
[tab][tab]}
[tab][tab]else
[tab][tab][tab]sb.append(c);
[tab]}
[tab]
[tab]return sb.toString();
}
[/CODE]
가끔씩 새로 뜨는 프레임이 포커싱이 되지 않아야 되는데
저절로 포커싱이 되서 약간(?) 불편한 경우가 생기곤 한다.
예를들자면 메신저에서 새 프레임이 뜨는 경우
열심히 타이핑하고있는데 불쑥 창 하나 떠서 그쪽으로 포커싱된다면??
-_-;;
이 문제를 해결하기 위해서
삽질하다가 알게된 코드 -_-;
여기서 this 는 JFrame 이다.
포커싱 되지 않게 해 놓은 다음에 보여주고~
포커싱 되게 설정을 해놓는 ..
여러번 테스트 해 봤는데 잘 작동하는것 같다.
[CODE type="java"][tab]this.setFocusableWindowState(false);
[tab]setVisible(true);
[tab]this.setFocusableWindowState(true);
[/CODE]
우분투 리눅스에서 돌려봤다.
java가 플랫홈인디팬던트언어니 문제 없이 잘 돌아갈거라 생각했었다
그런데 으응?
프로그램상에서 출력하는 부분은 한글이 잘 나오는데,
소켓으로 주고받는곳에서 이상하게 깨져나왔다 @.@
한참을 삽질했다 ..
하다하다 안되서 어떤분에게 물어봤더니
getBytes() 에 캐릭터셋을 지정 안해주면 시스템 기본으로 읽는다더라..
라는 말에
다음과 같은 소스를 작성해 리눅스와 윈도우에서 돌려보았다
[CODE type="java"]
class test
{
public static void main(String args[]){
System.out.println("file.encoding=" + System.getProperty("file.encoding"));
}
}
[/HTML][/CODE]
리눅스-_-;;;
$ java test
file.encoding=UTF-8
윈도우
java test
file.encoding=MS949
다음과같이 고쳐줬다
소켓에서 읽어오는 부분...
[CODE type="java"]
return new String(inbuf.toByteArray(),"MS949");
[/HTML][/CODE]
소켓으로 보내는 부분...
[CODE type="java"]
out.write(ws.getBytes("MS949"));
[/HTML][/CODE]
