Après avoir lu le wiki base64 ...
J'essaie de comprendre comment fonctionne la formule:
Étant donné une chaîne de longueur n
, la longueur base64 sera
Lequel est : 4*Math.Ceiling(((double)s.Length/3)))
Je sais déjà que la longueur en 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% de surcharge)
Question:
Comment les informations ci-dessus s'accordent-elles avec la longueur de sortie ?
4 * n / 3
donne une longueur non rembourrée.Et arrondissez au multiple de 4 le plus proche pour le remplissage, et comme 4 est une puissance de 2, vous pouvez utiliser des opérations logiques au niveau du bit.
la source
$(( ((4 * n / 3) + 3) & ~3 ))
4 * n / 3
échoue déjà àn = 1
, un octet est codé en utilisant deux caractères, et le résultat est clairement un caractère.Pour référence, la formule de longueur du codeur Base64 est la suivante:
Comme vous l'avez dit, un encodeur Base64 doté d'
n
octets de données produira une chaîne de4n/3
caractères Base64. En d'autres termes, tous les 3 octets de données donneront 4 caractères Base64. EDIT : Un commentaire souligne correctement que mon graphique précédent ne tenait pas compte du rembourrage; la bonne formule estCeiling(4n/3)
.L'article de Wikipedia montre exactement comment la chaîne ASCII est
Man
encodée dans la chaîne Base64TWFu
dans son exemple. La chaîne d'entrée a une taille de 3 octets, ou 24 bits, de sorte que 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 donne 4 caractères Base64.Vous demandez dans un commentaire quelle
123456
serait la taille de l'encodage . En gardant à l'esprit que chaque caractère de cette chaîne a une taille de 1 octet, ou 8 bits, (en supposant un encodage ASCII / UTF8), nous encodons 6 octets, ou 48 bits, de données. Selon l'équation, nous nous attendons à ce que la longueur de sortie soit(6 bytes / 3 bytes) * 4 characters = 8 characters
.Mettre
123456
dans un encodeur Base64 créeMTIzNDU2
, qui est de 8 caractères, exactement comme prévu.la source
floor((3 * (length - padding)) / 4)
. Découvrez l' essentiel suivant .Entiers
En général, nous ne voulons pas utiliser de doubles parce que nous ne voulons pas utiliser les opérations en virgule flottante, les erreurs d'arrondi, etc. Elles ne sont tout simplement pas nécessaires.
Pour cela, il est bon de se rappeler comment effectuer la division du plafond:
ceil(x / y)
en double peut être écrit comme(x + y - 1) / y
(en évitant les nombres négatifs, mais attention aux débordements).Lisible
Si vous optez pour la lisibilité, vous pouvez bien sûr également le programmer comme ceci (exemple en Java, pour C, vous pouvez utiliser des macros, bien sûr):
Inline
Rembourré
Nous savons que nous avons besoin de 4 blocs de caractères à la fois pour chaque 3 octets (ou moins). Alors la formule devient (pour x = n et y = 3):
ou combiné:
votre compilateur optimisera le
3 - 1
, alors laissez-le comme ceci pour maintenir la lisibilité.Non rembourré
Moins commune est la variante non rembourrée, pour cela, nous nous souvenons que chacun nous avons besoin d'un caractère pour chaque 6 bits, arrondi:
ou combiné:
on peut cependant encore diviser par deux (si on veut):
Illisible
Si vous ne faites pas confiance à votre compilateur pour faire les optimisations finales à votre place (ou si vous voulez confondre vos collègues):
Rembourré
Non rembourré
Nous sommes donc là, deux méthodes logiques de calcul, et nous n'avons pas besoin de branches, d'opérations de bits ou d'opérations modulo - à moins que nous ne le voulions vraiment.
Remarques:
la source
Je pense que les réponses données manquent le point de la question originale, à 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 de fin. Vous n'aurez peut-être pas besoin de l'appel d'étage si vous faites de l'arithmétique entière.
Y compris le remplissage, une chaîne base64 nécessite quatre octets pour chaque morceau de trois octets de la chaîne d'origine, y compris les morceaux partiels. Un ou deux octets supplémentaires à la fin de la chaîne seront toujours convertis en quatre octets dans la chaîne base64 lorsque le remplissage est ajouté. Sauf si vous avez une utilisation 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 en C, car les chaînes ASCII sans cela sont un peu dangereuses et vous devrez transporter la longueur de la chaîne séparément.
la source
Voici une fonction pour calculer la taille d'origine d'un fichier Base 64 encodé sous forme de chaîne en Ko:
la source
Alors que tout le monde débat des formules algébriques, je préfère utiliser BASE64 lui-même pour me dire:
525
710
Il semble donc que la formule de 3 octets représentée par 4 caractères base64 semble correcte.
la source
(Dans une tentative de donner une dérivation succincte mais complète.)
Chaque octet d'entrée a 8 bits, donc pour n octets d'entrée, nous obtenons:
Tous les 6 bits sont un octet de sortie, donc:
Ceci est sans rembourrage.
Avec le remplissage, nous arrondissons cela à plusieurs octets de sortie sur quatre:
Voir les divisions imbriquées (Wikipedia) pour la première équivalence.
En utilisant l'arithmétique entière, ceil ( n / m ) peut être calculé comme ( n + m - 1) div m , d'où nous obtenons:
À titre d'illustration:
Enfin, dans le cas du codage MIME Base64, deux octets supplémentaires (CR LF) sont nécessaires tous les 76 octets de sortie, arrondis vers le haut ou vers le bas selon si une nouvelle ligne de fin est nécessaire.
la source
Il me semble que la bonne formule devrait être:
la source
Je crois que celui-ci est une réponse exacte si n% 3 n'est pas nul, non?
Version Mathematica:
S'amuser
GI
la source
Implémentation simple en javascript
la source
Pour toutes les personnes qui parlent C, jetez un œil à ces deux macros:
Pris d' ici .
la source
Je ne vois pas la formule simplifiée dans d'autres réponses. La logique est couverte mais je voulais une forme la plus basique pour mon utilisation intégrée:
REMARQUE: Lors du calcul du nombre non complété, nous arrondissons la division entière, c'est-à-dire ajoutons Divisor-1 qui est +2 dans ce cas
la source
Sous 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, je me suis retrouvé avec une formule approximative comme celle-ci:
Taille d'allocation de chaîne Mine64 (approximative) = (((4 * ((taille du tampon binaire) + 1)) / 3) + 1)
Donc le dernier +1 - il est utilisé pour ascii-zéro - le dernier caractère doit être alloué pour stocker la fin de zéro - mais pourquoi "la taille du tampon binaire" est + 1 - je soupçonne qu'il y a un caractère de terminaison mime64? Ou peut-être s'agit-il d'un problème d'alignement.
la source
S'il y a quelqu'un intéressé à réaliser la solution @Pedro Silva dans JS, je viens de porter cette même solution pour cela:
la source