De quelle taille sont les chiffres? En plus des autres réponses, vous pourriez envisager de base-128 variante de codage par longueur, qui vous permet de stocker des nombres plus petits dans les octets tout en permettant à un plus grand nombre. Le MSB signifie "il y a un autre octet" - ce qui est décrit ici.
Combinez cela avec les autres techniques de sorte que vous stockez à ignorer "taille", "prendre la taille", "sauter" taille", "prendre la taille" mais de noter que ni le "skip", ni de "prendre" ne sera jamais nulle, donc nous allons soustraire un de chaque (qui permet d'enregistrer un octet supplémentaire pour une poignée de valeurs)
Donc:
1-100, 110-160
est "skip 1" (à supposer commencer à zéro, car il rend les choses plus faciles), "prendre 100", "skip 9", "prendre 51"; soustrait 1 de chacun, de donner (comme les décimales)
0,99,8,50
qui encode (hex):
00 63 08 32
Si nous voulions passer/prendre un plus grand nombre de 300, par exemple; nous soustrayons 1 donnant 299 - mais qui remonte à plus de 7 bits; en commençant par le petit bout, nous coder les blocs de 7 bits et une ESM pour indiquer la suite:
299 = 100101100 = (in blocks of 7): 0000010 0101100
donc, en commençant par le petit bout:
1 0101100 (leading one since continuation)
0 0000010 (leading zero as no more)
donner:
AC 02
On peut donc coder un grand nombre facilement, mais un petit nombre (dont le son est typique pour passer/prendre) prennent moins d'espace.
Vous pourriez essayer d'exécuter ce par le biais de "dégonfler", mais il pourrait ne pas aider beaucoup plus...
Si vous ne voulez pas faire face à tout cela en désordre encodage cruff vous-même... si vous pouvez créer l'entier-le tableau des valeurs (0,99,8,60) - vous pouvez utiliser le protocole de tampons avec des paniers répété uint32/uint64 - et il va faire tout le travail pour vous ;-p
Je n'ai pas "faire" de Java, mais il y en a plein le C# de mise en œuvre (pour emprunter de l'encodage des bits à partir de mon protobuf-net du projet):
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
static class Program
{
static void Main()
{
var data = new List<int>();
data.AddRange(Enumerable.Range(1, 100));
data.AddRange(Enumerable.Range(110, 51));
int[] arr = data.ToArray(), arr2;
using (MemoryStream ms = new MemoryStream())
{
Encode(ms, arr);
ShowRaw(ms.GetBuffer(), (int)ms.Length);
ms.Position = 0; // rewind to read it...
arr2 = Decode(ms);
}
}
static void ShowRaw(byte[] buffer, int len)
{
for (int i = 0; i < len; i++)
{
Console.Write(buffer[i].ToString("X2"));
}
Console.WriteLine();
}
static int[] Decode(Stream stream)
{
var list = new List<int>();
uint skip, take;
int last = 0;
while (TryDecodeUInt32(stream, out skip)
&& TryDecodeUInt32(stream, out take))
{
last += (int)skip+1;
for(uint i = 0 ; i <= take ; i++) {
list.Add(last++);
}
}
return list.ToArray();
}
static int Encode(Stream stream, int[] data)
{
if (data.Length == 0) return 0;
byte[] buffer = new byte[10];
int last = -1, len = 0;
for (int i = 0; i < data.Length; )
{
int gap = data[i] - 2 - last, size = 0;
while (++i < data.Length && data[i] == data[i - 1] + 1) size++;
last = data[i - 1];
len += EncodeUInt32((uint)gap, buffer, stream)
+ EncodeUInt32((uint)size, buffer, stream);
}
return len;
}
public static int EncodeUInt32(uint value, byte[] buffer, Stream stream)
{
int count = 0, index = 0;
do
{
buffer[index++] = (byte)((value & 0x7F) | 0x80);
value >>= 7;
count++;
} while (value != 0);
buffer[index - 1] &= 0x7F;
stream.Write(buffer, 0, count);
return count;
}
public static bool TryDecodeUInt32(Stream source, out uint value)
{
int b = source.ReadByte();
if (b < 0)
{
value = 0;
return false;
}
if ((b & 0x80) == 0)
{
// single-byte
value = (uint)b;
return true;
}
int shift = 7;
value = (uint)(b & 0x7F);
bool keepGoing;
int i = 0;
do
{
b = source.ReadByte();
if (b < 0) throw new EndOfStreamException();
i++;
keepGoing = (b & 0x80) != 0;
value |= ((uint)(b & 0x7F)) << shift;
shift += 7;
} while (keepGoing && i < 4);
if (keepGoing && i == 4)
{
throw new OverflowException();
}
return true;
}
}