Question Calcul de la longueur de base64?


Après avoir lu la base64 wiki ...

J'essaie de comprendre comment la formule de travail:

Étant donné une chaîne de longueur n , la longueur de base64 sera enter image description here

Lequel est : 4*Math.Ceiling(((double)s.Length/3)))

Je sais déjà que la longueur de base64 doit être %4==0 pour permettre au décodeur de savoir quelle était la longueur du texte d'origine.

Le nombre maximum de remplissage pour une séquence peut être = ou ==.

wiki: Le nombre d'octets de sortie par octet d'entrée est d'environ 4/3 (33%   aérien)

Question:

Comment les informations ci-dessus correspondent-elles à la longueur de sortie enter image description here ?


102
2017-11-14 12:27


origine


Réponses:


Chaque caractère représente 6 bits (log2(64) = 6).

Par conséquent, 4 caractères sont utilisés pour représenter 4 * 6 = 24 bits = 3 bytes.

Donc vous avez besoin 4*(n/3) caractères à représenter n octets, et cela doit être arrondi à un multiple de 4.

Le nombre de caractères de remplissage inutilisés résultant de l'arrondi à un multiple de 4 sera évidemment 0, 1, 2 ou 3.


138
2017-11-14 12:29



4 * n / 3 donne une longueur non rembourrée.

Et arrondissez au multiple de 4 le plus proche pour le remplissage, et 4 étant une puissance de 2, vous pouvez utiliser des opérations logiques au niveau du bit.

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

31
2017-08-21 12:19



Pour référence, la formule de longueur de l'encodeur Base64 est la suivante:

Base64 encoder's length formula

Comme vous l'avez dit, un encodeur Base64 donné n octets de données produiront une chaîne de 4n/3 Caractères Base64. En d'autres termes, tous les 3 octets de données donneront 4 caractères Base64. MODIFIER: Un commentaire souligne correctement que mon graphique précédent ne tenait pas compte du remplissage; la formule correcte est  Ceiling(4n/3).

L'article de Wikipedia montre exactement comment la chaîne ASCII Man  encodé dans la chaîne Base64 TWFu dans son exemple. La chaîne d'entrée a une taille de 3 octets ou 24 bits, donc la formule prédit correctement que la sortie aura une longueur de 4 octets (ou 32 bits): TWFu. Le processus encode tous les 6 bits de données dans l'un des 64 caractères Base64, de sorte que l'entrée 24 bits divisée par 6 génère 4 caractères Base64.

Vous demandez dans un commentaire quelle est la taille de l'encodage 123456 serait. En gardant à l'esprit que chaque caractère de cette chaîne a une taille de 1 octet ou 8 bits (en supposant un codage ASCII / UTF8), nous encodons 6 octets ou 48 bits de données. Selon l'équation, on s'attend à ce que la longueur de sortie soit (6 bytes / 3 bytes) * 4 characters = 8 characters.

En mettant 123456 dans un encodeur Base64 crée MTIzNDU2, qui a 8 caractères, comme prévu.


21
2017-07-25 17:26



Je pense que les réponses données manquent le point de la question initiale, à savoir combien d'espace doit être alloué pour s'adapter au codage base64 pour une chaîne binaire donnée de longueur n octets.

La réponse est (floor(n / 3) + 1) * 4 + 1

Cela inclut le remplissage et un caractère nul final. Vous n'avez peut-être pas besoin de l'appel sol si vous faites de l'arithmétique entière.

En incluant le remplissage, une chaîne base64 nécessite quatre octets pour chaque bloc de trois octets de la chaîne d'origine, y compris les blocs partiels. Un ou deux octets supplémentaires à la fin de la chaîne seront toujours convertis en quatre octets dans la chaîne base64 lors de l'ajout du remplissage. Sauf si vous avez un usage très spécifique, il est préférable d'ajouter le remplissage, généralement un caractère égal. J'ai ajouté un octet supplémentaire pour un caractère nul dans C, car les chaînes ASCII sans cela sont un peu dangereuses et vous devez porter la longueur de la chaîne séparément.


6
2018-03-23 15:38



Entiers

En général, nous ne voulons pas utiliser les doubles car nous ne voulons pas utiliser les opérations en virgule flottante, les erreurs d'arrondi, etc. Ils ne sont tout simplement pas nécessaires.

Pour cela, il convient de se rappeler comment effectuer la division du plafond: ceil(x / y) en double peut être écrit comme (x + y - 1) / y (tout en évitant les nombres négatifs, mais méfiez-vous des débordements).

Lisible

Si vous optez pour la lisibilité, vous pouvez bien sûr également le programmer comme ceci (par exemple en Java, pour C vous pourriez bien sûr utiliser des macros):

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));
    }
}

En ligne

Rembourré

Nous savons que nous avons besoin de 4 blocs de caractères pour chaque 3 octets (ou moins). Alors la formule devient (pour x = n et y = 3):

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

ou combiné:

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

votre compilateur optimisera le 3 - 1, laissez-le comme ça pour maintenir la lisibilité.

Non rembourré

Moins fréquente est la variante non rembourrée, pour cela nous rappelons que chacun a besoin d'un caractère pour chaque 6 bits, arrondi à:

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

ou combiné:

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

on peut cependant encore diviser par deux (si on veut):

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

Illisible

Si vous ne faites pas confiance à votre compilateur pour effectuer les optimisations finales pour vous (ou si vous voulez confondre vos collègues):

Rembourré

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

Non rembourré

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

Nous sommes donc là, deux méthodes de calcul logiques, et nous n’avons pas besoin de branches, d’opérations binaires ou d’opérations modulo - à moins que nous ne le souhaitions vraiment.

Remarques:

  • De toute évidence, vous devrez peut-être ajouter 1 aux calculs pour inclure un octet de terminaison nul.
  • Pour Mime, vous devrez peut-être vous occuper des éventuels caractères de terminaison de ligne (recherchez d'autres réponses).

4
2017-07-30 15:19



Voici une fonction pour calculer la taille d'origine d'un fichier Base 64 codé en tant que chaîne en Ko:

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;
}

3
2017-08-17 09:58



Il me semble que la bonne formule devrait être:

n64 = 4 * (n / 3) + (n % 3 != 0 ? 4 : 0)

2
2018-03-07 00:12



Alors que tout le monde débat des formules algébriques, je préfère utiliser BASE64 lui-même pour me dire:

$ 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

Il semble donc que la formule de 3 octets représentée par 4 caractères base64 semble correcte.


1
2018-05-29 01:12



Dans Windows - je voulais estimer la taille du tampon de taille mime64, mais toutes les formules de calcul précises ne fonctionnaient pas pour moi - enfin, j'ai fini avec une formule approximative comme celle-ci:

Mine64 taille d'allocation de chaîne (approximative) = (((4 * (taille du tampon binaire) + 1)) / 3) + 1)

Donc le dernier +1 - il est utilisé pour ascii-zero - le dernier caractère doit être alloué pour stocker la fin du zéro - mais pourquoi "la taille du tampon binaire" est de + 1 - Je pense qu'il y a un caractère de terminaison mime64? Ou peut-être est-ce un problème d'alignement.


0
2018-02-27 07:48