[string] Base64 길이 계산?

base64 위키를 읽은 후 …

수식이 어떻게 작동 하는지 알아 내려고합니다 .

길이가 n인 문자열이 주어지면 base64 길이는여기에 이미지 설명을 입력하십시오

어느 것 : 4*Math.Ceiling(((double)s.Length/3)))

나는 base64 길이가 %4==0디코더가 원래 텍스트 길이를 알 수 있도록 해야한다는 것을 이미 알고 있습니다 .

시퀀스의 최대 패딩 수는 =또는 ==입니다.

wiki : 입력 바이트 당 출력 바이트 수는 약 4/3 (33 % 오버 헤드)입니다.

질문:

위의 정보는 출력 길이와 어떻게 일치 여기에 이미지 설명을 입력하십시오합니까?



답변

각 문자는 6 비트 ( log2(64) = 6) 를 나타내는 데 사용됩니다 .

따라서을 나타내는 데 4 개의 문자가 사용됩니다 4 * 6 = 24 bits = 3 bytes.

따라서 바이트 4*(n/3)를 나타내려면 문자가 필요 n하며 이는 4의 배수로 반올림되어야합니다.

4의 배수로 올림하여 사용되지 않은 패딩 문자의 수는 분명히 0, 1, 2 또는 3입니다.


답변

4 * n / 3 패딩되지 않은 길이를 제공합니다.

패딩을 위해 가장 가까운 4의 배수로 반올림하고 4는 2의 거듭 제곱으로 비트 논리 연산을 사용할 수 있습니다.

((4 * n / 3) + 3) & ~3


답변

참고로 Base64 인코더의 길이 공식은 다음과 같습니다.

Base64 엔코더 길이 공식

말했듯이, n바이트 단위의 데이터가 주어진 Base64 인코더 는 4n/3Base64 문자 의 문자열을 생성합니다 . 다시 말해, 3 바이트의 데이터마다 4 개의 Base64 문자가 생성됩니다. 편집 : 주석은 이전 그래픽이 패딩을 설명하지 않았다고 올바르게 지적합니다. 올바른 공식은 Ceiling(4n/3) 입니다.

Wikipedia 기사는 ASCII 문자열 이 예제에서 Man Base64 문자열로 인코딩되는 방식을 정확하게 보여줍니다 TWFu. 입력 문자열의 크기는 3 바이트 (24 비트)이므로 수식의 출력 길이는 4 바이트 (또는 32 비트)입니다 TWFu. 이 프로세스는 6 비트의 모든 데이터를 64 Base64 문자 중 하나로 인코딩하므로 24 비트 입력을 6으로 나눈 값은 4 Base64 문자가됩니다.

인코딩의 크기가 무엇인지 의견에 묻습니다 123456. 해당 문자열의 모든 문자는 크기가 1 바이트 또는 8 비트 (ASCII / UTF8 인코딩이라고 가정)이므로 6 바이트 또는 48 비트의 데이터를 인코딩합니다. 방정식에 따르면 출력 길이는이라고 예상합니다 (6 bytes / 3 bytes) * 4 characters = 8 characters.

123456Base64 인코더에 넣으면 MTIzNDU2예상대로 8 자 길이가됩니다.


답변

정수

일반적으로 우리는 부동 소수점 연산, 반올림 오류 등을 사용하지 않기 때문에 복식을 사용하고 싶지 않습니다. 그것들은 필요하지 않습니다.

이를 위해 상한 나눗셈을 수행하는 방법을 기억하는 것이 좋습니다. 복수 ceil(x / y)(x + y - 1) / y(음수를 피하면서 오버플로를 조심하면서) 쓸 수 있습니다 .

읽을 수있는

가독성을 원한다면 물론 다음과 같이 프로그래밍 할 수도 있습니다 (예 : Java의 경우 C의 경우 매크로를 사용할 수 있음).

public static int ceilDiv(int x, int y) {
    return (x + y - 1) / y;
}

public static int paddedBase64(int n) {
    int blocks = ceilDiv(n, 3);
    return blocks * 4;
}

public static int unpaddedBase64(int n) {
    int bits = 8 * n;
    return ceilDiv(bits, 6);
}

// test only
public static void main(String[] args) {
    for (int n = 0; n < 21; n++) {
        System.out.println("Base 64 padded: " + paddedBase64(n));
        System.out.println("Base 64 unpadded: " + unpaddedBase64(n));
    }
}

인라인

패딩

우리는 각 3 바이트 (또는 그 이하)마다 4 문자 블록이 필요하다는 것을 알고 있습니다. 따라서 공식은 (x = n 및 y = 3)이됩니다.

blocks = (bytes + 3 - 1) / 3
chars = blocks * 4

또는 결합 :

chars = ((bytes + 3 - 1) / 3) * 4

컴파일러는를 최적화 3 - 1하므로 가독성을 유지하려면 그대로 두십시오.

패딩되지 않은

패딩되지 않은 변형은 덜 일반적입니다.이를 위해 각 6 비트마다 문자가 필요하다는 것을 기억합니다.

bits = bytes * 8
chars = (bits + 6 - 1) / 6

또는 결합 :

chars = (bytes * 8 + 6 - 1) / 6

그러나 여전히 원하는 경우 두 개로 나눌 수 있습니다.

chars = (bytes * 4 + 3 - 1) / 3

읽을 수 없음

컴파일러가 자신을 위해 최종 최적화를 수행한다고 신뢰하지 않는 경우 (또는 동료를 혼동시키려는 경우) :

패딩

((n + 2) / 3) << 2

패딩되지 않은

((n << 2) | 2) / 3

따라서 우리는 두 가지 논리적 계산 방법이 있으며, 실제로 원하지 않는 한 분기, 비트 연산 또는 모듈로 연산이 필요하지 않습니다.

노트:

  • 분명히 널 종료 바이트를 포함하기 위해 계산에 1을 추가해야 할 수도 있습니다.
  • Mime의 경우 가능한 줄 종결 문자 등을 관리해야 할 수도 있습니다 (다른 답변 찾기).

답변

주어진 답변이 원래 질문의 요점을 놓친 것 같습니다. 이는 길이 n 바이트의 주어진 이진 문자열에 대해 base64 인코딩에 맞게 얼마나 많은 공간을 할당해야하는지입니다.

정답은 (floor(n / 3) + 1) * 4 + 1

여백 및 종료 널 문자가 포함됩니다. 정수 산술을 수행하는 경우 플로어 호출이 필요하지 않을 수 있습니다.

패딩을 포함하여 base64 문자열에는 부분 청크를 포함하여 원래 문자열의 3 바이트 청크마다 4 바이트가 필요합니다. 패딩이 추가 될 때 문자열 끝에 추가 된 1 바이트 또는 2 바이트는 여전히 base64 문자열에서 4 바이트로 변환됩니다. 매우 구체적으로 사용하지 않는 한 일반적으로 등호 인 패딩을 추가하는 것이 가장 좋습니다. 이것을 사용하지 않는 ASCII 문자열은 약간 위험하므로 문자열 길이를 별도로 운반해야하기 때문에 C에서 null 문자에 여분의 바이트를 추가했습니다.


답변

다음은 인코딩 된 Base 64 파일의 원래 크기를 문자열 (KB)로 계산하는 함수입니다.

private Double calcBase64SizeInKBytes(String base64String) {
    Double result = -1.0;
    if(StringUtils.isNotEmpty(base64String)) {
        Integer padding = 0;
        if(base64String.endsWith("==")) {
            padding = 2;
        }
        else {
            if (base64String.endsWith("=")) padding = 1;
        }
        result = (Math.ceil(base64String.length() / 4) * 3 ) - padding;
    }
    return result / 1000;
}


답변

다른 모든 사람들이 대수 공식에 대해 토론하고 있지만, 나는 BASE64 자체를 사용하여 나에게 이야기하고 싶습니다.

$ echo "Including padding, a base64 string requires four bytes for every three-byte chunk of the original string, including any partial chunks. One or two bytes extra at the end of the string will still get converted to four bytes in the base64 string when padding is added. Unless you have a very specific use, it is best to add the padding, usually an equals character. I added an extra byte for a null character in C, because ASCII strings without this are a little dangerous and you'd need to carry the string length separately."| wc -c

525

$ echo "Including padding, a base64 string requires four bytes for every three-byte chunk of the original string, including any partial chunks. One or two bytes extra at the end of the string will still get converted to four bytes in the base64 string when padding is added. Unless you have a very specific use, it is best to add the padding, usually an equals character. I added an extra byte for a null character in C, because ASCII strings without this are a little dangerous and you'd need to carry the string length separately." | base64 | wc -c

710

따라서 4 base64 문자로 표현되는 3 바이트 수식이 올바른 것 같습니다.