2018년 9월 23일 일요일

Java 문자를 ASCII코드로 표현하기

이번시간에는 Java에서 아스키코드를 사용하는 방법에 대해서 살펴보겠다.

그전에 한가지 스트림이라는 지식에 대해 살펴보고 진행하자.

우리가 작성하는 문자들은 데이터들은 컴퓨터가 문자하나하나를 인식할 수 있을까?
다음의 예를 살펴보자.

 - Stream과정

① 'h'라는 문자를 키보드 클릭 → ②운영체제(OS)에 전달(동작 : 사용자가 키보드 'h' 클릭) → ③메모장에 'h'라는 문자를 보여줌

이 과정에서 컴퓨터가 h라는 데이터를 입력받은것을 어떻게 인식할 수 있을까?
바로 이 문자 h라는 것을 컴퓨터가 이해할 수 있도록 바이트단위로 변환시킨뒤 데이터가 전달되는 것이다. (Input Stream)
그리고 컴퓨터는 이것을 다시 사용자들이 인식할 수 있도록 바이트 단위로 표현된 문자를  원래의 값으로 변환시킨뒤 메모장 'h'라는 문자를 보이도록 하는 것이다.

즉, 입력/출력하는(InputStream / OutputStream) 동안에 컴퓨터들에게는 바이트 단위로 문자를 인식시키는것이다. 컴퓨터는 0과 1밖에 모르기 때문이다.
그리고 바이트 단위 → 문자형, 문자형 → 바이트 단위로 바꿔주는 것을 인코딩이라고 하며, 이 인코딩하는 다양한 방식들이 존재한다.
- 대표적으로 ASCII, Unicode, UTF-8 등이 있다.

- java에서 문자를 바이트 단위로 표현하기

예제 1) 문자와 숫자를 바이트 단위로 저장한 뒤 출력하기.
  1. package org.java.project;
  2.  
  3. public class Onebyte{
  4.     public static void main(String[] args) {
  5.  
  6.         byte byte_a = 'a';
  7.         byte byte_b = 'b';
  8.        
  9.         byte byte_A = 'A';
  10.         byte byte_B = 'B';
  11.        
  12.         byte byte_0 = '0';
  13.         byte byte_9 = '9';
  14.         System.out.println("문자 a를 바이트 단위로 표현 : " + byte_a);
  15.         System.out.println("문자 b를 바이트 단위로 표현 : " + byte_b);
  16.         System.out.print("\n");
  17.         System.out.println("문자 A를 바이트 단위로 표현 : " + byte_A);
  18.         System.out.println("문자 B를 바이트 단위로 표현 : " + byte_B);
  19.         System.out.print("\n");
  20.         System.out.println("숫자 0을 바이트 단위로 표현 : " + byte_0);
  21.         System.out.println("숫자 9를 바이트 단위로 표현 : " + byte_9);
  22.     }
  23. }
▶실행결과











: 실행결과 인코딩방식은 ASCII이며, 문자와 숫자가 해당하는 ASCII코드표에 있는 값의 데이터를 출력한다. 그래서 숫자로 입력받은 값 byte_0과 byte_9는 사실 숫자가 아닌 문자 '0', 문자 '9'로 인식하여 아스키 코드표에 해당하는 값 0~9는 아스키코드표에서 48~57에 으로 저장한다.
0을 아스키코드값 : 48( 48 : 2진수 0011 0000으로 컴퓨터가 인식)
9를 아스키코드값 : 57( 57 : 2진수 0011 1001으로 컴퓨터가 인식)

예제 2) 한문자씩 바이트코드 데이터형의 배열에 저장한 뒤 출력방법 - 1
  1. package org.java.project3.hanbat;
  2.  
  3. public class Onebyte{
  4.     public static void main(String[] args) {
  5.        
  6.         String str = "Hello world";
  7.         int j = 0;
  8.        
  9.         byte[] byte_str = new byte[str.length()]; // 문자열 갯수만큼 바이트코드로 인식함.
  10.        
  11.         // 문자열의 한문자씩 byte단위로 byte배열 byte_str에 저장하기.
  12.         for(int i = 0; i < str.length(); i++)
  13.             byte_str[i] = (byte)str.charAt(i); //바이트의 단위로 인식할 수 있게 형변환.
  14.        
  15.         // 자료형 문자, byte단위의 문자 비교하기  
  16.         for(byte value : byte_str)
  17.             System.out.println(str.charAt(j++) + " : " + value);       
  18.     }
  19. }
▶실행결과




















예제 3) 문자열을 바이트코드로 인코딩한뒤 바이트코드를 문자열로 디코딩하기
  1. package org.java.project;
  2. public class Onebyte{
  3.     public static void main(String[] args) {
  4.         String Text = "Hello World";
  5.         byte[] byteText = Text.getBytes(); // 문자열을 바이트코드로 변환시켜서 배열 하나하나에 저장시킴.
  6.        
  7.         System.out.println("---문자열과, 바이트코드로 인코딩한 결과---");
  8.         System.out.println("Text : " + Text);
  9.         System.out.println("byte_Text : " + byteText); // 바이트코드로 인코딩한 배열의 주소를 출력하고있음.
  10.         System.out.println("byte_Text.toString() : " + byteText.toString());
  11.        
  12.         System.out.println("\r---문자를 바이트코드로 표현한 결과---");
  13.         for(int i=0; i<Text.length(); i++)
  14.             System.out.println("Character [" + Text.charAt(i) + "] To ASCII Code : " + byteText[i]);
  15.        
  16.         String byteToText = new String(byteText);
  17.         System.out.println("\r---바이트코드에서 문자열로 디코딩한 결과---");
  18.         System.out.println(byteToText);
  19.     }  
  20. }
▶실행결과




















이로써 자바에서는 문자에서 바이트코드로 인코딩할때 8bit로 2의 7승까지 표현 할 수 있는 ASCII방식을 사용한다는 것을 살펴보았다.

2018년 9월 20일 목요일

java 문자열 안에 문자2개이상 존재 할 경우 출력하기

이번시간에는 자바로 문자열안에 문자의 갯수가 2개이상인것에 대해서 살펴보자.

`문자열안에 문자가 2개 이상 존재하는 문자의 갯수를 출력하기` 이 문장을보면,
우리는 이에맞는 알고리즘이 어떤것들이 있는지 떠올릴 수 있는가?

나는 이러한 알고리즘이 생각났다.

1) 문자열의 갯수만큼 문자열의 맨앞 문자 하나를 문자열 전체를 순환하며 비교
2) 비교하여 갯수들이 몇개있는지 확인하고 이 과정을 반복함

물론 위의 방법이 좋긴하지만, 우리는 더 효율적인 방법이 어떠한 것들이 있는지 잘 생각해보면, 다음과 같다.

1) 문자열의 갯수만큼 문자열안에 존재하는 문자하나를 기준으로 삼는다.
2) 기준이되는 문자를 문자열안에서 전부 제거한다. 그리고 그 제거한 갯수를 센다.
3) 문자열의 갯수만큼 문자열안에 존재하는 문자를 제거했으면, 비교할 데이터들이 줄어들었다. 즉, 문자열안에 문자들끼리 비교가 끝난 것은 제거하여 더 빠르고 복잡하지 않게 계산을 해주어야한다.

다음의 코드들을 살펴보자


예제) 문자열에 문자가 2개이상있는 문자들의 갯수를 출력하시오.
  1. package org.java.project.subproject1;
  2.  
  3. import java.util.Scanner;
  4.  
  5. class StrOverlap{
  6.     public static void StrCounting(String s) {
  7.         System.out.println("\n\"" + s+"\"");
  8.         char str;  // 기준점이 되는 문자
  9.         int i = 0;
  10.         int strExist = 0; // 중복되는 문자가 있는경우 0, 없는경우 -1
  11.         int currentLen;  // 중복된 문자가 있는경우 제거하기 전 길이
  12.         int duplicateCount = 0; // 중복된 문자의 갯수
  13.         String delStr = null;
  14.         while(s.length() != 0)
  15.         {
  16.             str = s.charAt(0);
  17.             System.out.println("\n"+ +++") Search : " + str);
  18.             s = s.substring(1, s.length());
  19.             strExist = s.indexOf(str); // 존재한다면 배열 인덱스값, 존재하지 않는다면 -1
  20.  
  21.             if(strExist != -1)
  22.             {
  23.                 currentLen = s.length();
  24.                 delStr = ""+str;
  25.                 s = s.replaceAll(delStr, ""); // 탐색할 문자가 존재하는 위치를 빈공간 즉 제거함.
  26.                 duplicateCount = currentLen - s.length() + 1; // 중복제거된 name.length()값이 몇개인지 세줌.
  27.                 System.out.println("\""+str + "\" is a duplicate of : " + duplicateCount);
  28.             }
  29.             else {
  30.                 System.out.println("Only one exists");
  31.             }
  32.         }
  33.     }
  34. }
  35. public class Exam {
  36.     public static void main(String[] args) {
  37.  
  38.         Scanner sc = new Scanner(System.in);
  39.         System.out.print("Input String  :   ");
  40.         String s = sc.next();
  41.  
  42.         StrOverlap.StrCounting(s);
  43.     }
  44. }
 
▶실행결과

Input String  :   Bananajoke

"Bananajoke"

1) Search : B
Only one exists

2) Search : a
"a" is a duplicate of : 3

3) Search : n
"n" is a duplicate of : 2

4) Search : j
Only one exists

5) Search : o
Only one exists

6) Search : k
Only one exists

7) Search : e
Only one exists

위 처럼 문자열 Bananajoke를 입력받으면 다음과 같이 결과가 나온다.

그래서 문자열들을 출력하고 계산시간까지 효율적으로 하기위해서는
하나의 문자를 전부다 탐색하고 이에 겹치는 문자들은 전부 제거하고 그다음 값을 비교하면서 찾아갈 수 있다.

2018년 9월 10일 월요일

네트워크 OSI 7계층과 프로토콜

이전시간에는 네트워크에 대해서 살펴보았다면, 이번시간에는 네트워크상에서 통신할때 알아야 할 필수적인 OSI7계층과 이 표준적인 통신규약에 해당하는 프로토콜에 대해서 살펴보겠다.

OSI7계층이란 무엇인가?
국제표준기구(ISO)에서 규정한 컴퓨터의 사이의 통신을 위한 약속이다.
그리고 이 약속에 해당하는 것을 프로토콜이라고 한다. 

수 많은 컴퓨터들간의 데이터를 주고 받기(송, 수신)위해서 표준 프로토콜을 따르며, 각 데이터는 OSI7계층에서 각 계층별로 데이터를 송, 수신하기 위한 형태로 맞게 변환해준다.

OSI7계층을 살펴보자,

















 위의 OSI7계층과 TCP/IP 프로토콜들의 모습을 보면, 계층간 서로 연관되어있는 형태를 띄고있다. "OSI7계층을 통해서 데이터를 송, 수신할때 TCP/IP계층 각 프로토콜들에 규격에 맞게 전송을 해야하며 이것들은 계층별로 서로 다른 규칙을 갖고있다" 라고 이해하면 된다.

그렇다면, 왜 이러한 표준화된 프로토콜을 사용해야 하는가?
이는 개발자들을 위해서이다. 만약에 프로토콜이 표준화 되어있지 않다면, 개발자들은 네트워크 상에서 데이터를 주고받을때, 통신프로토콜과 발생하는 모든 일들을 생각하여 프로그램에 포함시켜야한다. 하지만 표준화가 되어있는 통신프로토콜을 사용하게 되면 우리는 발생하는 모든 일들을 포함시킬 필요없이 각 계층별에 맞게 데이터를 쪼개거나 캡슐화시켜서 전송하면 된다. 그러면 개발자들은 편리하게 표준화된 프로토콜 규격을 따르면 된다.

각 OSI-7 계층별로 하는 역할은 다음과 같다.
 - 7계층 Application : 사용자 인터페이스 / 응용프로그램
 - 6계층 Presentation : 데이터 포멧 / 암호화
 - 5계층 Session : 연결유지
 - 4계층 Transport : 패킷생성 / 패킷 오류 관리
 - 3계층 Network : 논리적 주소(IP)관리 / 경로설정
 - 2계층 Data Link : 물리적 주소(MAC)관리
 - 1계층 Physical : 네트워크의 물리적 주소(케이블, 신호방식)

 각 TCP/IP 계층별 프로토콜은 다음과 같다.
 1. Physical : 실제로 데이터 전송방식을 정의함(네트워크가 무선인지 유선인지, 속도, 코딩방식 등)
 2. Data Link : 네트워크가 유선이든 무선이든, 1대 1 혹은 1대 N, AP(Wifi)에 연결된 단말기등을 구별하기 위한 규칙이 필요함. 그래서 다음과 같이 2가지로 나뉨
 - Data Link에서의 상위 : LLC (거의하는 역할이 없다.)
 - Data Link에서의 하위 : MAC (단말기 간의 고유 식별 번호도 포함되어 있어서 이를통해 제조업체를 알 수 있으며, 이는 이더넷이나 와이파이를 포함한 네트워크상에서의 주소로 사용된다.)
 3. Network : 1, 2계층에서 받은 패킷들을 올바른 주소로 잘 전달될 수 있도록 한다. (라우팅 되기 위한 목적)라우팅이란? 패킷들을 목적지로 전송하기 위해 경로를 설정하는 걸 의미한다.
또한 1~3계층까지는 Source IP라는 보내는 측의 IP가 이용되는데, 이후 4계층에서는 Destination IP 전송받는 측의 IP주소만 있으면 된다.
 4. Transport : TCP와 UDP로 나뉘며, 패킷의 손실 여부를 파악하며, 패킷을 순서대로 전송을 하는 역할을 한다.
 - TCP역할 : 깨진패킷 확인여부 및 시퀸스 넘버를 통해서 전송할 데이터를 순서대로 정렬하여 전송 가능하게 해준다. 데이터를 올바르게 전송하지 못했을경우, (response 측)재전송을 요청한다.
 - UDP역할 : 깨진패킷만 확인가능. 올바른 순서인지는 보장하지 않는다. 즉 올바르게 전송하지 못했다면, 재전송을 하지 않고 받고 끝낸다.


 패킷들의 데이터 송 수신방법
데이터를 전송하는 송신측(request)에서는 각 계층별로 패킷들을 쪼개어 필요한 데이터를 덧붙이거나 데이터 전송 형식에 맞게 송신한다. 
데이터를 받는 수신측(response)에서는 해당 쪼개어진 패킷들을 캡슐화 하여(원래대로 재정렬) 원상태로 복구 하여 데이터를 읽는다.































네트워크 - 네트워크에 대하여.

이번에는 네트워크 통신에 대하여 살펴보자.


 네트워크란 무엇인가?
: 다른 컴퓨터들과 데이터를 주고받기(송, 수신) 혹은 다른 장치들과의 데이터를 주고받는 행위 등 어떠한 연결을 통해서 정보들을 서로 공유하고 상호정보 교환을 수행하는 형태를 일컫는다. 다음 그림은 일반적인 네트워크 형태를 보여준다.


거대한 망을 이루어서 작업을 하는 모습처럼 보인다.
하지만 모든 네트워크는 위의 형태가 아니다. 여러 형태 중 하나를 표현한 것이며, 어떠한 통신을 하느냐에 따라서 다양한 형태를 갖으며, 그에 효율적인 통신방법에 맞게 설정해주면 된다.

그렇다면, 이 거대한 네트워크라는 망은 어떻게 통신을하느냐?
데이터를 어떠한 형태로 교환하느냐에 따라 통신방법이 달라지는데, 대표적으로 아래와 같다.
1) 회선교환망 (전화기)
2) 패킷교환망
3) 메시지 교환망


우리는 이 3가지 중에서 패킷교환망에 대해서 살펴보겠다.
그전에 네트워크와 인터넷의 차이를 알고있는가?
인터넷 : 데이터를 패킷교환망을 통해서 데이터를 주고받는 방법의 형태이다. 조건이 있다면, 이는 네트워크라는 거대한 망안에 통신하는 형태이다.















즉, 인터넷을 사용하는것은 네트워크안에서 다른 단말기간의 데이터를 송, 수신을 통해 상호작용하는것 같은 말이다.

다음시간에는 이러한 네트워크 통신을 할때 필요한 OSI7계층과 각 계층의 프로토콜들에 대해서 살펴보겠다.



[Java] N-I/O(Non-Blocking) 파일 읽기 쓰기 - GatheringByteChannel, ScatteringByteChannel, ByteBuffer 사용.

우리는 지금까지 다음과 같이 살펴보았다. 1.  InputStream / OutputStream : 입, 출력 스트림을 바이트로 처리하여 읽기, 쓰기. 2.  FileInputStream / FileOutputStream : 입, 출력 스트림을 ...