Depois de ler o wiki base64 ...
Estou tentando descobrir como está funcionando a fórmula:
Dada uma string com comprimento de n
, o comprimento da base64 será
Qual é : 4*Math.Ceiling(((double)s.Length/3)))
Eu já sei que o comprimento base64 deve ser %4==0
para permitir que o decodificador saiba qual era o comprimento do texto original.
O número máximo de preenchimento para uma sequência pode ser =
ou ==
.
wiki: O número de bytes de saída por byte de entrada é aproximadamente 4/3 (33% de sobrecarga)
Questão:
Como as informações acima se ajustam ao comprimento da saída ?
4 * n / 3
fornece comprimento não acolchoado.E arredondar para o múltiplo mais próximo de 4 para preenchimento e, como 4 é uma potência de 2, pode usar operações lógicas bit a bit.
fonte
$(( ((4 * n / 3) + 3) & ~3 ))
4 * n / 3
já falhan = 1
, um byte é codificado usando dois caracteres e o resultado é claramente um caractere.Para referência, a fórmula de comprimento do codificador Base64 é a seguinte:
Como você disse, um codificador Base64 dado
n
bytes de dados produzirá uma sequência de4n/3
caracteres Base64. Em outras palavras, a cada 3 bytes de dados resultará em 4 caracteres Base64. EDIT : Um comentário indica corretamente que meu gráfico anterior não foi responsável pelo preenchimento; a fórmula correta éCeiling(4n/3)
.O artigo da Wikipedia mostra exatamente como a string ASCII
Man
codificada na string Base64TWFu
em seu exemplo. A cadeia de caracteres de entrada é de 3 bytes, ou 24 bits, em tamanho, de modo que a fórmula prevê correctamente a saída será de 4 bytes (ou 32 bits) de comprimento:TWFu
. O processo codifica a cada 6 bits de dados em um dos 64 caracteres Base64; portanto, a entrada de 24 bits dividida por 6 resulta em 4 caracteres Base64.Você pergunta em um comentário qual seria o tamanho da codificação
123456
. Tendo em mente que todo caractere dessa string tem 1 byte ou 8 bits de tamanho (assumindo a codificação ASCII / UTF8), estamos codificando 6 bytes, ou 48 bits, de dados. De acordo com a equação, esperamos que o comprimento da saída seja(6 bytes / 3 bytes) * 4 characters = 8 characters
.A inserção
123456
em um codificador Base64 criaMTIzNDU2
, com 8 caracteres, exatamente como esperávamos.fonte
floor((3 * (length - padding)) / 4)
. Confira a seguinte essência .Inteiros
Geralmente, não queremos usar duplos porque não queremos usar operações de ponto flutuante, erros de arredondamento etc. Eles simplesmente não são necessários.
Para isso, é uma boa idéia lembrar-se de como realizar a divisão do teto: o
ceil(x / y)
dobro pode ser escrito como(x + y - 1) / y
(enquanto evita números negativos, mas cuidado com o excesso).Legível
Se você busca legibilidade, é claro que também pode programá-lo desta forma (exemplo em Java, para C, você pode usar macro, é claro):
Inline
Acolchoado
Sabemos que precisamos de 4 blocos de caracteres por vez para cada 3 bytes (ou menos). Então a fórmula se torna (para x = ne y = 3):
ou combinado:
seu compilador otimizará o
3 - 1
, então deixe assim para manter a legibilidade.Sem almofada
Menos comum é a variante não-acolchoada, para isso lembramos que cada um de nós precisa de um caractere para cada 6 bits, arredondado para cima:
ou combinado:
no entanto, ainda podemos dividir por dois (se quisermos):
Ilegível
Caso você não confie no seu compilador para fazer as otimizações finais para você (ou se você quiser confundir seus colegas):
Acolchoado
Sem almofada
Portanto, existem duas formas lógicas de cálculo e não precisamos de ramificações, operações de bits ou operações de módulos - a menos que realmente desejemos.
Notas:
fonte
Eu acho que as respostas dadas não atendem ao objetivo da pergunta original, que é a quantidade de espaço que precisa ser alocada para ajustar a codificação base64 para uma determinada seqüência binária de comprimento n bytes.
A resposta é
(floor(n / 3) + 1) * 4 + 1
Isso inclui preenchimento e um caractere nulo final. Você pode não precisar da chamada de piso se estiver fazendo aritmética de número inteiro.
Incluindo preenchimento, uma string base64 requer quatro bytes para cada pedaço de três bytes da string original, incluindo todos os pedaços parciais. Um ou dois bytes extras no final da string ainda serão convertidos em quatro bytes na string base64 quando o preenchimento for adicionado. A menos que você tenha um uso muito específico, é melhor adicionar o preenchimento, geralmente um caractere igual. Eu adicionei um byte extra para um caractere nulo em C, porque as strings ASCII sem isso são um pouco perigosas e você precisa carregar o comprimento da string separadamente.
fonte
Aqui está uma função para calcular o tamanho original de um arquivo Base 64 codificado como uma String em KB:
fonte
Enquanto todo mundo está debatendo fórmulas algébricas, prefiro usar o próprio BASE64 para me dizer:
525
710
Parece que a fórmula de 3 bytes representada por 4 caracteres base64 parece correta.
fonte
(Na tentativa de fornecer uma derivação sucinta e completa.)
Cada byte de entrada possui 8 bits, portanto, para n bytes de entrada, obtemos:
A cada 6 bits é um byte de saída, portanto:
Isso é sem preenchimento.
Com o preenchimento, arredondamos esse número para vários bytes de saída:
Consulte Divisões aninhadas (Wikipedia) para obter a primeira equivalência.
Usando aritmética inteira, ceil ( n / m ) pode ser calculado como ( n + m - 1) div m , portanto, obtemos:
Para ilustração:
Finalmente, no caso da codificação MIME Base64, são necessários dois bytes adicionais (CR LF) a cada 76 bytes de saída, arredondados para cima ou para baixo, dependendo se uma nova linha final é necessária.
fonte
Parece-me que a fórmula correta deve ser:
fonte
Eu acredito que esta é uma resposta exata se n% 3 não zero, não?
Versão do Mathematica:
Diverta-se
GI
fonte
Implementação simples em javascript
fonte
Para todas as pessoas que falam C, dê uma olhada nessas duas macros:
Retirado daqui .
fonte
Não vejo a fórmula simplificada em outras respostas. A lógica é abordada, mas eu queria uma forma mais básica para o meu uso incorporado:
NOTA: Ao calcular a contagem não preenchida, arredondamos a divisão inteira, ou seja, adicionamos o Divisor-1, que é +2 neste caso
fonte
No Windows - eu queria estimar o tamanho do buffer do tamanho mime64, mas todas as fórmulas precisas de cálculo não funcionaram para mim - finalmente, acabei com uma fórmula aproximada como esta:
Tamanho da alocação de sequência do Mine64 (aproximado) = (((4 * ((tamanho do buffer binário) + 1)) / 3) + 1)
Portanto, o último +1 - é usado para ascii-zero - o último caractere precisa ser alocado para armazenar o final zero - mas por que "tamanho do buffer binário" é + 1 - suspeito que haja algum caractere de terminação mime64? Ou pode ser que isso seja algum problema de alinhamento.
fonte
Se houver alguém interessado em obter a solução @Pedro Silva em JS, eu apenas portamos a mesma solução:
fonte