Bir dizeyi kısaltmak için ne tür kodlama kullanabilirim?


13

Ben bir dize kodlama ilgileniyorum ve sadece alfa ve sayısal karakterler içerecek ve tercihen dizeyi temsil etmek için gereken karakter sayısını kısaltacaktır kullanılabilir kodlama türü olup olmadığını merak ediyorum.

Şimdiye kadar bunu yapmak için Base64 kodlama kullanarak baktım ama benim dize daha uzun yapmak gibi görünüyor ve bazen ==kaçınmak istiyorum içerir . Misal:

test adı | 120101

olur

dGVzdCBuYW1lfDEyMDEwMQ ==

16 ile 24 karakter arasındadır ve alfasayısal olmayan karakter içerir.

Herkes benim gereksinimlerimı elde edecek kullanabileceğim farklı bir kodlama türü biliyor mu? Bonus çerçevesi ya .NET çerçevesine yerleşikse ya da kodlamayı yapacak bir üçüncü taraf kütüphanesi varsa puan verir.


1
Huffman kodlama gibi daha az kayıp sıkıştırma kullanamazsınız !! Metinler için idealdir ... ancak sonunda, metni geri almak için yaptığınız bu mutasyonu gerçekten bilmelisiniz.

6
Kodlamayı değil, sıkıştırmayı tanımlıyorsunuz
Andy Smith

@Andrew - Tamam, öneriniz var mı?
Abe Miessler

Yanıtlar:


30

Base64'teki son '=' veya '==' sadece karakter sayısını 4'ün katları yapmak için var. Onu daha sonra tekrar koyabileceğiniz için kaldırabilirsiniz. Base64'ün 64 farklı karakter kullandığı için çağrıldığını unutmayın . Büyük harfler, küçük harfler ve rakamlar.

Genel olarak, rastgele bayt dizilerini alfasayısal karakterlere kodlamak istiyorsanız, bir yerde mutlaka bazı uzunluk uzantıları vardır, çünkü bir bayt için 256 olası değer ve sadece 62 alfasayısal karakter vardır. Buna bazen güvercin deliği prensibi denir . Bir kodlama şeması bir faktör günlüğünün ortalama uzunluk uzantısına sahip olmalıdır 256 / log 62 = 1.344 (tüm bayt dizileri boyunca ortalama); aksi takdirde, bazı güvercinlerin bir yere vurularak öldürüldüğü ve zarar görmeden onları geri alamayacağınız anlamına gelir (yani: aynı şekilde kodlanmış iki ayrı dize, bu nedenle kod çözme güvenilir bir şekilde çalışamaz).

Şimdi, oldukça mümkündür senin dize olmayan tam olarak "eşit rastgele bayt dizileri"; dizelerinizin bir anlamı vardır, bu da en olası bayt dizisinin gerçekleşmeyeceği anlamına gelir, çünkü anlamsızdırlar. Bu temelde, genel Base64'ten (veya katı alfasayısal karakterlere bağlı kalmanız gerekiyorsa Base62) daha az uzunluk genişlemesine neden olacak bir kodlama şeması tasarlayabilirsiniz. Bu kayıpsız veri sıkıştırmasıdır . Girdi olarak neyin ortaya çıkabileceğinin açıkça tanımlanmış olasılıklı bir modeli üzerinde çalışır.

Özet: Bir genel hiç veya çok az uzunluk uzantısı hiç olacak şekildedir alfanümerik diziler içine dizeleri kodlanması için şema, mevcut değildir; matematiksel bir imkansızlıktır. Bir belirli beklediğiniz giriş dizesinin tür uyarlanmış düzeni muhtemelen var olabilir (ama karşılaşabileceğiniz dize tür neyi söyleme çünkü kimse bu konuda size yardımcı olabilir).


1
+1, mükemmel açıklama. Uzunluğun 4'ün katları olmasıyla ilgili =/ ==varlık hakkında bir şey bilmiyordum, ihtiyaçlarım için bu
sorunu

Dikkat edin, bu güvercin deliği eksikliğini varsayar. Unicode'da çok sayıda harf var. Gerçek problemi daha iyi anlamamız gerekiyor .
MSalters

@Tom günlük bölümünü kullanarak ortalama uzunluk uzatma faktörünü nasıl hesapladınız? En.wikipedia.org/wiki/Base64'teki şemaya dayanarak, kodlanmamış her karakter için Base64'te 4/3 karakterlerin temsil edilmesi tamamen sezgisel bir anlam ifade eder. Sadece matematik ile aynı sonuca nasıl geldiğini merak ediyorum ... teşekkürler :)
Jonathan Lin

Kötü, aptalca sorum. log (256) = 8 bit, log (64) = 6 bit, dolayısıyla Base64 için oran 8/6 = 4/3 = 1.333'tür. Şerefe.
Jonathan Lin

4

Karakterlerin yeniden kodlanması genellikle alıcı sistem bunları işleyemediğinde yapılır. Örneğin, BASE64, daha uzun veri dizilerini temsil etmek için 6 bitlik (2 6 , dolayısıyla 64) karakter kullanan verileri temsil eder (sonunda görünen "==" hizalama için dolgudır). Bunun nedeni, e-postadaki resim dosyanızın içinde 0xFE olması ve posta sunucunuzun bunu (veya geleneksel olarak yazdırılmayan herhangi bir karakteri) iletmekten mutsuz olmasıdır.

"Boyutu küçülten" kodlama yoktur. Kodlamalar, bitlerin temsil ettikleri karakterle eşleştirilmesidir. Bununla birlikte, ASCII genellikle 8 bitlik alanda depolanan 7 bitlik bir karakter kümesidir (kodlama). Kabul ettiğiniz aralıkları sınırlarsanız, kontrol karakterlerini ayıklayabilirsiniz.

Bu yöntemi kullanmak, bit düzeyinde bir şeyler yazmanız gerektiği anlamına gelir ve ayrıca tüm modern makinelerin 8 bitin katları olan hizalamaları olduğu için makine hızı ve talimatları ile biraz cehennem oynar. Örneğin, Unicode'un UTF-8, UTF-16 ve UTF-32 olmasının nedeni budur.

Bunu güvenlik için yapıyorsanız (bu yüzden Security.SE'de yayınladınız, değil mi?), Sadece şeyleri filtreleyin ve normal şekilde saklayın. Yer kazanmak için bunu yapıyorsanız, tüm ekstra kodların ve daha yavaş erişim süresinin (çoğu giriş adres sınırlarını aşacağından) alan tasarrufuna değip değmeyeceğini düşünün.

Bununla birlikte, ASCII'yi 8 bit depolama alanından 7 bit'e dönüştürmek zorunda kaldığımız CS kursundan bir snippet:

    memset(dest,0x00,8);
    memcpy(dest, source, length);

    for (int i = 0; i < 8; i++) {
            if (dest[i] & 0x80) {
                    fprintf(stderr, "%s: %s\n", dest, "Illegal byte sequence");
                    exit(EILSEQ);
            }
    }

    dest[0] = 0x7F & dest[0] | 0x80 & dest[1] << 7;
    dest[1] = 0x3F & dest[1] >> 1 | 0xC0 & dest[2] << 6;
    dest[2] = 0x1F & dest[2] >> 2 | 0xE0 & dest[3] << 5;
    dest[3] = 0x0F & dest[3] >> 3 | 0xF0 & dest[4] << 4;
    dest[4] = 0x07 & dest[4] >> 4 | 0xF8 & dest[5] << 3;
    dest[5] = 0x03 & dest[5] >> 5 | 0xFC & dest[6] << 2;
    dest[6] = 0x01 & dest[6] >> 6 | 0xFE & dest[7] << 1;
    dest[7] = 0x00; //Clearing out

2

Verileri örneğin gzip, bzip2 veya lzma ile sıkıştırabilir ve sonra kullanılan karakter setini sınırlamak için base64 üzerinden çalıştırabilirsiniz. Bu yalnızca yüzlerce bayt veya daha büyük dizelerde faydalıdır.


1

neden LZ sıkıştırma kullanmıyorsunuz? bu, bir dizgeyi sıkıştırmanın iyi bir yolu olabilir, ancak uzun dizeler durumunda daha verimli olacaktır. Kodlamak istediğiniz hedef dize ne kadardır?


LZ sıkıştırması, attir önerisinde belirtilen gzip veya bzip2 ile nasıl karşılaştırılır?
NoChance

gzip, LZ ve Huffman Kodlaması üzerine kurulmuştur. LZ en.wikipedia.org/wiki/LZ77
A.Rashad hakkında
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.