java 와 C 간의 인코딩 문제...

하하의 이미지

안녕하세요..

제목과 같이 인코딩 문제로 골머리를 썩고 있습니다.

다름이 아니라.

C는 한글을 2byte 로 인식하고 있습니다

그런데 자바는 유니코드로서 1로 인식하고 있습니다.

예를 들어..

c 일 경우

char *str = "안녕하세요";

strlen(str) => 하면 정수로 10입니다.

그럼 자바일 경우

String str = "안녕하세요";

str.length() => 를 하면 5입니다.

----------------------------------------------------------------------------
아래를 볼때

다음과 같이 C 서버가 java 클라이언트에게

13 byte (주민번호) + 10byte (이름) + 11byte (전화번호)

이렇게 보낼때

java 클라이언트는

데이터를 바이트로 읽어서

String str = new String(byteBuffer)

이런식으로 서버에서 보낸 데이터를 str에 저장합니다.

문제는 여기서 서버가 보낸 각각의 데이터를 각각

String p_num = str.substring(0, 13);

String name = str.substring(13, 10);

String tel_num = str.substring(23, 11);

이렇게 입력한다고 할때..

중간에 있는 이름을 10 byte만큼 읽을려고 하지만

substring 에서의 범위 지정은 byte 단위가 아닌

한글은 1이란 숫자로 인식하기 때문에..

C 서버에서 이름 부분을 "홍길동1234" 이렇게

10자리로 채워서 보내줘도

JAVA 클라이언트는 substring(13, 10)을 통해

홍길동1234011 이런식으로 전화번호 (011) 부분

까지 읽어와 버립니다.

이럴때 바이트 단위로 매겨진 이름 10자리를

java에서도 온전히 읽을려면 어떻 방법이 있나요?

으~~~~~.. 질문이 제대로 올라 갔나 모르겠습니다

그럼 안녕히..

아.. 제가 위 문제를 해결하기 위해 허접 삽질한 코드도

올리겠습니다.

도움 부탁드립니다. 꾸벅..

import java.io.*;

public class Test {

        public static void main(String[] args) throws IOException {

                String str = "안녕하세요";

                
                
                System.out.println(str.length());
                System.out.println(str+" length:"+str.length());




                String newstr = new String(str.getBytes(), "ascii");
                System.out.println(newstr+" length:"+newstr.length());




                String substr = newstr.substring(0,4);  //  <<--- "안녕" 이란 두글자만
                                                        // substring 으로 읽을려고 시도
                                                        // 위에서 ascii로 변환 했기 때문에
                                                        // 0~4 하면 한글 2글자를 잘를거라
                                                        // 생각 했지만 결과는 한글이 깨져서 보임. ㅠㅠ;



                // println 에서 acsii로 conversion 된 문자를 찍기 위해 다시 유니코드로 변환..
                String convstr = new String(substr.getBytes(), "8859_1");
                //String convstr = new String(substr.getBytes(), "euc_kr");
                //String convstr = new String(substr.getBytes(), "KSC5601");

                System.out.println("**"+convstr);

        }
}
mykldp의 이미지

처음에 바이트 배열로 문자열을 만들때 C서버가 사용하는 인코딩과 java 클라이언트가 사용하는 인코딩을 같은 것으로 맞춰주세요. 그러면 주민번호와 이름을 잘라내는 코드가 문제 없이 돌아갈 듯 한데요. 예를 들어 서버측의 인코딩이 UTF-8 이면 new String(buffer, "UTF-8") 이 되겠죠.

하하의 이미지

Quote:

예를 들어 서버측의 인코딩이 UTF-8 이면 new String(buffer, "UTF-8") 이 되겠죠.

음.. 서버는 C로 되어있고 C는 특별히 한글이라고

인코딩 하지 않는 걸로 알고 있습니다. 단순히 바이트

로 처리를 하는 걸로.. 맞나?? 그러나 자바같은 경우

모든 한글은 어떤 인코딩 방식으로 된걸 String 객체가

제대로 인식 할수 있는거 같습니다..... 그렇다면

무엇으로 변경해야 옳은지..

String convstr = new String(substr.getBytes(), "8859_1");
String convstr = new String(substr.getBytes(), "euc_kr");
String convstr = new String(substr.getBytes(), "KSC5601");

이렇게는 해봤지만 한글 자체가 깨지는 문제가

있어 보입니다. 해결방법이 없을런지..

“바람에게도 길은 있다. 나는 비로소 나의 길을 가느니. 길은 언제나 어디에나 있다.”

mykldp의 이미지

C 프로그램에서도 당연히 문자 인코딩을 사용합니다. 인코딩은 프로그래밍 언어와는 관계 없습니다. 서버가 어떤 인코딩을 사용하는지는 서버 구현에 따라 다릅니다. 서버를 직접 구현하신게 아니라면 구현자에게 물어보시거나 서버의 문서를 살펴보시면 될겁니다. 그도 안된다면 일단 서버의 OS 를 살펴보세요. 만약에 리눅스라면 $LANG 변수의 값을 살펴보세요. 서버 OS의 기본 인코딩을 알아내실 수 있습니다. 하지만 서버 프로그램이 기본 인코딩을 사용하지 않고 자기 나름의 인코딩을 사용한다면 그 때는 정말 만든 사람에게 물어보거나 서버 문서 또는 설정 파일에서 알아내는 수 밖에 없습니다. 때로 서버가 아무런 인코딩도 사용하지 않을 수도 있습니다. 서버에 저장되어 있는 주민번호나 이름등을 클라이언트에서 데이터를 보내서 입력하는 거라면 인코딩을 변환하지 않고 그저 그 바이트를 그대로 저장했을 수도 있습니다. 그런 경우라면 클라이언트의 인코딩을 그대로 써주시면 되겠지요.

그리고 이런 코드를 쓰셨는데

String convstr = new String(substr.getBytes(), "8859_1"); 
String convstr = new String(substr.getBytes(), "euc_kr"); 
String convstr = new String(substr.getBytes(), "KSC5601"); 

제 말씀은 이런 뜻이 아니었습니다.^^;

예를 들어 서버로 부터 받은 로우 데이터가 byte[] data 에 들어있다면

String rawString = new String(data, "서버측 인코딩");

String p_num = rawString.substring(0, 13);
String name = rawString.substring(13, 10); 
String tel_num = rawString.substring(23, 11); 

이런 식으로 해보시라는 말씀이었습니다.

하하의 이미지

서버는 한글에 대해 따로 인코딩 하지 않습니다.

그럼 해당 OS의 인코딩을 따른 다는 말인데.

해당 리눅스는 LANG=ko_KR.eucKR 입니다.

따라서.

String rawString = new String(data, "euc_kr");

로 변환 후...

이름부분만 한다면.

String name = rawString.substring(13, 10);

마찬가지로 한글을 1로 생각하기 때문에 원하는 결과를

얻을 수 없었습니다.

정녕 간단한 인코딩은 안된단 말인가요?

구분자등을 입력해야 한단 ..말인가요.. ㅠㅠ

“바람에게도 길은 있다. 나는 비로소 나의 길을 가느니. 길은 언제나 어디에나 있다.”

atdda의 이미지

원하시는 답이 될런지는 모르겠습니다만,

byte 개수로 자르신 뒤에,
자른 byte array를 String으로 변환하시는게 편하지 않을까요?

질문에 보면, byte 수 기준으로 보내는 것 같은데,
byte array를 자르는 것으로 충분할법하여 말씀드립니다.

내용 추가합니다.

좀전에는 코드를 눈여겨 보지 않았었는데, 올리신 코드에 이런 부분이 보이는 군요

                String str = "안녕하세요"; 
                 .....
                String newstr = new String(str.getBytes(), "ascii"); 
                System.out.println(newstr+" length:"+newstr.length()); 
                String substr = newstr.substring(0,4);

이렇게 쓰시면 str의 byte code를 ascii로 변환하는 것이 아니라,
str의 byte를 ascii로 간주하고 String을 생성합니다.
한데, str.getbytes()로 하면 JVM 디폴트로된 charset 만 반환합니다.

그렇기 때문에 newstr에는 깨진 한글이 들어가겠네요.

위의 String 생성자는
new String(xxxx charset byte array, Name of xxxx charset)
로 사용하실 때 쓰시면 좋습니다.

May The Force Be With You.

bear의 이미지

정확한 답은 아니지만..
예전에 사용한 방법인데
길이의 문제라면..

중간 중간에 특정한 특수 문자를 넣고..

그 특수 문자로 하여 각각의 변수에 담으면 될것 같습니다.

그렇게 하면 굳이 길이의 문제를 해결 하실수 있을것 같습니다.

이름이 2자 이거나 4자일때도 생각 하신다면 특수 문자로 처리하시는 것도 괜찮다고 생각합니다.

그럼 즐삽 하세요..^^

하하의 이미지

Quote:

이렇게 쓰시면 str의 byte code를 ascii로 변환하는 것이 아니라,
str의 byte를 ascii로 간주하고 String을 생성합니다.

여기서 간주한다는 말의 의미를 잘 모르겠습니다.

간주 한단 말은 실제로는 JVM이 정한 charset만을

쓰지만 해당 String 객체는 인코딩 방식이 ascii인 것

이다...... 그렇다면... 모든 연산은 JVM 의 charset을

사용하니 실제적으로 위의 간주하는 방식은 쓸모가

없어 보입니다. 제가 식견이 짧아서 - - ;;;

그럼 위의 간주하는 방법이 어떻때 유용하게 쓰이나요?

감싸함다.

“바람에게도 길은 있다. 나는 비로소 나의 길을 가느니. 길은 언제나 어디에나 있다.”

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.