문자열을 더 짧게 만들기 위해 어떤 유형의 인코딩을 사용할 수 있습니까?


13

나는 가지고있는 문자열을 인코딩하는 데 관심이 있으며 알파와 숫자 만 포함하고 문자열을 나타내는 데 필요한 문자 수를 줄이는 인코딩 유형이 있는지 궁금합니다.

지금 까지이 작업을 수행하기 위해 Base64 인코딩을 사용하는 방법을 살펴 보았지만 문자열을 더 길게 만들고 때로는 ==피하고 싶은 것을 포함 시키는 것으로 보입니다. 예:

테스트 이름 | 120101

된다

dGVzdCBuYW1lfDEyMDEwMQ ==

16 ~ 24 자이며 영숫자가 아닌 문자를 포함합니다.

내가 사용할 수있는 다른 유형의 인코딩에 대해 아는 사람이 있습니까? .NET 프레임 워크에 내장되어 있거나 인코딩을 수행 할 타사 라이브러리가있는 경우 보너스 포인트.


1
허프만 코딩과 같은 손실 감소 압축을 사용할 수 없습니다! 그것들은 텍스트에 이상적으로 적합합니다 ... 그러나 최종적으로 당신은 텍스트를 되찾기 위해 한이 돌연변이에 대해 정말로 알아야합니다.

6
인코딩이 아니라 압축에 대해 설명하고 있습니다.
Andy Smith

@Andrew-좋아, 어떤 제안?
Abe Miessler

답변:


30

Base64의 마지막 '='또는 '=='는 문자 수를 4의 배수로 만 만드는 것입니다. 나중에 다시 넣을 수 있으므로 제거 할 수 있습니다. Base64는 64 개의 고유 한 문자를 사용하므로 소위 호출 됩니다. 대문자, 소문자 및 숫자는 62입니다. 따라서 Base64는 청구서에 맞거나 맞지 않을 수있는 '/'및 '+'도 사용합니다.

일반적으로 임의의 바이트 시퀀스를 영숫자 문자로 인코딩하려면 바이트에 대해 256 개의 가능한 값과 62 개의 영숫자 문자 만 있기 때문에 길이 확장이 있어야합니다. 때때로 비둘기 구멍 원리 라고도합니다 . 인코딩 체계의 평균 길이 확장은 factor log 256 / log 62 = 1.344 (모든 바이트 시퀀스의 평균) 여야합니다 . 그렇지 않으면, 일부 비둘기가 어딘가에 뭉개 져서 죽지 않고 다시 데려 가지 않을 것입니다 (즉, 동일한 것으로 인코딩 된 두 개의 다른 문자열로 인해 디코딩이 안정적으로 작동 할 수 없음).

지금, 것을 확실히 가능하다 당신의 문자열이 아닌 바로 "균일 난수 바이트의 순서"; 문자열에는 의미 가 있으므로 의미가 없기 때문에 가능한 많은 바이트 시퀀스가 ​​발생하지 않습니다. 이를 바탕으로 일반 Base64 (또는 엄격한 영숫자 문자를 사용해야하는 경우 Base62)보다 길이가 더 짧은 인코딩 체계를 고안 할 수 있습니다. 이것은 무손실 데이터 압축 입니다. 입력으로 나타날 수있는 것에 대한 명확하게 정의 된 확률 모델을 통해 작동합니다.

요약 : 길이 확장이 거의 또는 전혀 발생하지 않도록 문자열을 영숫자 시퀀스로 인코딩 하는 일반적인 체계가 존재할 수 없습니다. 수학적으로 불가능합니다. 특정의 예상 입력 문자열의 종류에 맞게 조정 방식은 아마도 존재할 수 있습니다 (하지만 당신은 발생할 수있는 문자열의 종류 무엇을 말하지 않기 때문에, 아무도 이것에 당신을 도울 수있다).


1
+1, 훌륭한 설명. 나는에 대해 알고하지 않았다 =/ ==내가 나의 필요를 위해이 문제를 해결할 수 있습니다 4의 배수 여야 할 필요 길이에 관련되는
아베 Miessler

비둘기 구멍이 없다고 가정합니다. 유니 코드에는 많은 글자가 있습니다. 우리는 실제 문제에 대해 더 잘 이해해야합니다 .
MSalters

@Tom 로그 나누기를 사용하여 평균 길이 확장 계수를 어떻게 계산 했습니까? en.wikipedia.org/wiki/Base64 의 다이어그램을 기반으로, 인코딩되지 않은 각 문자에 대해 Base64에서 4/3 문자가 표시된다는 것은 완전히 직관적입니다. 수학으로 어떻게 결론을 내릴지 궁금해 ... 감사합니다 :)
Jonathan Lin

내 멍청한 질문이야 log (256) = 8 비트, log (64) = 6 비트이므로 Base64의 비율은 8/6 = 4/3 = 1.333입니다. 건배.
Jonathan Lin

4

문자 재 인코딩은 일반적으로 수신 시스템에서 처리 할 수 ​​없을 때 수행됩니다. 예를 들어, BASE64는 더 긴 데이터 시퀀스를 나타 내기 위해 6 비트 (2 6 , 따라서 64)의 문자를 사용하여 데이터를 나타냅니다 (종종에 나타나는 "=="가 정렬을 위해 채워짐). 전자 메일의 그림 파일에 0xFE가있을 수 있고 메일 서버가 전송하는 데 불만이있을 수 있습니다 (또는 일반적으로 인쇄되지 않는 다른 문자).

"크기를 줄이는"인코딩은 없습니다. 인코딩은 비트를 나타내는 문자에 대한 매핑입니다. 즉, ASCII는 종종 8 비트 공간에 저장되는 7 비트 문자 세트 (인코딩)입니다. 허용되는 범위를 제한하면 제어 문자를 제거 할 수도 있습니다.

이 방법을 사용하면 비트 수준에서 내용을 작성해야하며 모든 최신 기계에는 8 비트의 배수 인 정렬이 있기 때문에 기계 속도 및 명령으로 약간의 지옥을 재생합니다. 예를 들어 유니 코드가 UTF-8, UTF-16 및 UTF-32 인 이유입니다.

보안을 위해이 작업을 수행하는 경우 (그렇기 때문에 Security.SE에 게시 했습니까?), 항목을 필터링하고 정상적으로 저장하십시오. 공간을 절약하기 위해이 작업을 수행하는 경우 모든 추가 코드와 느린 액세스 시간 (대부분의 항목이 주소 경계를 넘기 때문에)이 공간을 절약 할 가치가 있는지 고려하십시오.

by 다음은 ASCII를 8 비트 스토리지에서 7 비트로 변환해야하는 CS 과정의 스 니펫입니다.

    memset(dest,0x00,8);
    memcpy(dest, source, length);

    for (int i = 0; i < 8; i++) {
            if (dest[i] & 0x80) {
                    fprintf(stderr, "%s: %s\n", dest, "Illegal byte sequence");
                    exit(EILSEQ);
            }
    }

    dest[0] = 0x7F & dest[0] | 0x80 & dest[1] << 7;
    dest[1] = 0x3F & dest[1] >> 1 | 0xC0 & dest[2] << 6;
    dest[2] = 0x1F & dest[2] >> 2 | 0xE0 & dest[3] << 5;
    dest[3] = 0x0F & dest[3] >> 3 | 0xF0 & dest[4] << 4;
    dest[4] = 0x07 & dest[4] >> 4 | 0xF8 & dest[5] << 3;
    dest[5] = 0x03 & dest[5] >> 5 | 0xFC & dest[6] << 2;
    dest[6] = 0x01 & dest[6] >> 6 | 0xFE & dest[7] << 1;
    dest[7] = 0x00; //Clearing out

2

gzip, bzip2 또는 lzma를 사용하여 데이터를 압축 한 다음 base64를 실행하여 사용 된 문자 세트를 제한 할 수 있습니다. 이것은 수백 바이트 이상의 큰 문자열에서만 유용합니다.


1

왜 LZ 압축을 사용하지 않습니까? 이것은 문자열을 압축하는 적절한 방법 일 수 있지만 긴 문자열의 경우 더 효율적입니다. 인코딩하려는 대상 문자열은 얼마나 걸립니까?


LZ 압축은 attir 제안에서 언급 된 gzip 또는 bzip2와 어떻게 비교됩니까?
NoChance

gzip은 LZ 및 Huffman Coding을 기반으로합니다. LZ에 대한 자세한 내용 en.wikipedia.org/wiki/LZ77
A.Rashad
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.