상세 컨텐츠

본문 제목

자바, 안드로이드 문자열을 바이트 길이구하기, 또는 길이로 제한, 인코딩에 따른 바이트 복사

본문

반응형

 

 

 

 

 

=================================

=================================

=================================

 

 

 

 

 

 

 

 

인코딩에 따른 문자열의 바이트 크기 구하는 방법

 

 

//기본 인코딩 설정이 UTF-8 로 되어 있다는 가정하에.

 

String str = "가나다"; 

 

int byteCnt = 0;

 

byteCnt = str.getBytes().length;

 

byteCnt 의 값은 유니코드[utf-8] 크기에 따라 한글 한글자당 3바이트씩 나온다.

 

그런데 자신이 서버나 다른 정보 저장 매체의 인코딩에 따라 문자열을 보내야하고 그 인코딩된 문자열의 사이즈 크기를 알고 싶다 그러면.

[예 "euc-kr"]

 

String str = "가나다"; 

 

int byteCnt = 0;

 

byteCnt = str.getBytes("euc-kr").length;

 

byteCnt 의 값은 "euc-kr" 크기에 따라 한글 한글자당 2바이트씩 나온다.

 

 

=================================

=================================

=================================

 

 

 

인코딩에 따른 문자열의 바이트 복사

 

 

 

String en = "euc-kr"; //utf-8, "MS949" 등등 넣어준다

 

String str = "가나다";

 

int siz = str.getBytes(en).length;

 

byte[] buff = new byte[siz];

 

System.arraycopy( str.getBytes(en) ,0 ,buff ,0 ,siz);

 

 

 

 

=================================

=================================

=================================

 

 

 

출처: http://photoress.tistory.com/56

 

 

2008/11/07 16:09 Programming/# java

 저는 프로그래밍 초보입니다. 저와 비슷한 레벨의 개발자들은 저와 같은 실수를 범하고 있을 것입니다.
오늘 제가 해결했던 문제점을 다른 개발자들은 어떻게 해결했는지 궁금하네요.


 

오늘 회사에서 코딩을 하던중 String형의 length를 구하는 부분이있었다.

가볍게 String.lengh() 사용해 주었다. 


 

예제1)

public class  Test
{
        public static void main(String[] args) 
       {
                String test = "안녕하세요";
                System.out.println("length = " +

 test.length()

);
       }
}

결과)   length = 

5

 

예상대로 5가 나왔다. 하지만 문제점이 하나 있다. 한글로 다섯글자는 10byte가 된다. 바이트로 네트워크 전송한다면, '안녕ㅎ', '하'는 1byte가 잘려나가게 된다. 결과는 '안녕하세요'라는 문자열이 전체 다 전송 되는 것이 아니라 절반만 전송되는 것이다. 이부분을 해결하기 위해서 여러가지 방법을 찾아보았다.

1) test.getByte().length();
   -> 1byte만 읽히고, length()에서 오류.

2) test.getBytes()

.length();


   -> 전체가 byte로 바뀌지만, 마찬가지로 length()에서 오류.

3) test.getBytes().length;
   
-> 올바른 사이즈 계산

마지막 괄호가 문제 였다. 평소 사용하는 length()가 익숙한 까닭에 습관적으로 괄호를 붙이게 되는데, 인터넷 이곳저곳을 뒤져서 괄호가 문제임을 찾아내었다. 사소한 것이지만 모른다면 length라는 것은 절대 찾을 수 었을 것같다. 다음은 마지막 테스트 결과이다.


 

예제2)

public class  Test
{
        public static void main(String[] args) 
       {
                String test = "안녕하세요";
                System.out.println("length = " + test.getBytes().length);
       }
}

결과)   length = 

10

 

 

 

 

 

반응형

 

 

728x90

 

 

=================================

=================================

=================================

 

 

 

출처: http://ecogeo.tistory.com/295

 

android.text.InputFilter를 이용해서 사용자의 텍스트입력을 다양한 방식으로 필터링할 수 있습니다. 
입력문자를 모두 대문자로 바꾸거나(InputFilter.AllCaps 이용), 문자열의 길이를 제한(InputFilter.LengthFilter 이용)할 수 있죠. 그밖에 다양한 필터를 만들 수 있을 겁니다. (정규식을 적용한 필터 예제 : http://flysky.thoth.kr/blog/4208673)
 
그런데 안드로이드가 기본으로 제공하는 InputFilter.LengthFilter는, 글자수(캐릭터 수)로 문자열의 길이를 계산하기 때문에 바이트 수로 길이를 제한하고 싶은 경우에는 사용할 수 없습니다. (한글처럼 문자열에 non-ascii 글자가 포함되면 글자 수 < 바이트 수).
 
아래 ByteLengthFilter는 바이트 길이로 입력을 제한해주는 필터입니다.
 
 
import android.text.InputFilter;
import android.text.Spanned;
 
/**
 * EditText 등의 필드에 텍스트 입력/수정시 
 * 입력문자열의 바이트 길이를 체크하여 입력을 제한하는 필터.
 *
 */
public class ByteLengthFilter implements InputFilter {

    private String mCharset; //인코딩 문자셋
 
    protected int mMaxByte; // 입력가능한 최대 바이트 길이
 
    public ByteLengthFilter(int maxbyte, String charset) {
        this.mMaxByte = maxbyte;
        this.mCharset = charset;
    }
 
    /**
     * 이 메소드는 입력/삭제 및 붙여넣기/잘라내기할 때마다 실행된다.
     *
     * - source : 새로 입력/붙여넣기 되는 문자열(삭제/잘라내기 시에는 "")
     * - dest : 변경 전 원래 문자열
     */
    public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart,
            int dend) {
 
        // 변경 후 예상되는 문자열
        String expected = new String();
        expected += dest.subSequence(0, dstart);
        expected += source.subSequence(start, end);
        expected += dest.subSequence(dend, dest.length());
 
        int keep = calculateMaxLength(expected) - (dest.length() - (dend - dstart));
 
        if (keep <= 0) {
            return ""; // source 입력 불가(원래 문자열 변경 없음)
        } else if (keep >= end - start) {
            return null; // keep original. source 그대로 허용
        } else {
            return source.subSequence(start, start + keep); // source중 일부만 입력 허용
        }
    }
 
    /**
     * 입력가능한 최대 문자 길이(최대 바이트 길이와 다름!).
     */
    protected int calculateMaxLength(String expected) {
        return mMaxByte - (getByteLength(expected) - expected.length());
    }    
    
    /**
     * 문자열의 바이트 길이.
     * 인코딩 문자셋에 따라 바이트 길이 달라짐.
     * @param str
     * @return
     */
    private int getByteLength(String str) {
        try {
            return str.getBytes(mCharset).length;
        } catch (UnsupportedEncodingException e) {
            //e.printStackTrace();
        }
        return 0;
    }
}    
 
 
EditText에는 이렇게 적용하면 됩니다.
 
 
int maxByte = ...;
EditText editText = ...;
 
InputFilter[] filters = new InputFilter[] {new ByteLengthFilter(maxByte, "KSC5601")};
editText.setFilters(filters);

 

 

=================================

=================================

=================================

 

 

 

 

 

반응형


관련글 더보기

댓글 영역