сжатие строки JavaScript с помощью localStorage - PullRequest
19 голосов
/ 29 июля 2011

Я использую localStorage в проекте, и ему нужно будет хранить лоты данных, в основном типа int, bool и string. Я знаю, что строки JavaScript являются Unicode, но когда они хранятся в localStorage, они остаются Unicode? Если так, есть ли способ, которым я мог бы сжать строку, чтобы использовать все данные в байте Unicode, или я должен просто использовать base64 и иметь меньшее сжатие? Все данные будут сохранены как одна большая строка.

РЕДАКТИРОВАТЬ: Теперь, когда я думаю об этом, base64 вообще не будет сильно сжимать, данные уже в base 64, a-zA-Z0-9 ;: составляет 65 символов.

Ответы [ 5 ]

25 голосов
/ 14 сентября 2011

"при хранении в localStorage они остаются в юникоде?"

Рабочий проект Web Storage определяет значения локального хранилища как DOMString. DOMStrings определены как последовательности 16-битных блоков с использованием кодировки UTF-16 . Так что да, они остаются Unicode.

есть ли способ сжать строку, чтобы использовать все данные в байте Unicode ... ?

Кодировка "Base32k" должна давать вам 15 бит на символ. Кодирование типа base32k использует преимущества полных 16 битов в символах UTF-16, но теряет бит, чтобы избежать срабатывания двухсимвольных символов. Если ваши исходные данные закодированы в base64, он использует только 6 бит на символ. Кодирование этих 6 битов в base32k должно сжать его до 6/15 = 40% от исходного размера. См http://lists.xml.org/archives/xml-dev/200307/msg00505.html и http://lists.xml.org/archives/xml-dev/200307/msg00507.html.

Для еще большего уменьшения размера вы можете декодировать строки base64 в их полный 8-разрядный двоичный файл, сжимать их с помощью известного алгоритма сжатия (например, см. реализацию JavaScript в gzip ), а затем кодировать base32k. сжатый вывод.

7 голосов
/ 12 сентября 2011

Вы можете кодировать в Base64, а затем реализовать простой алгоритм сжатия без потерь, такой как кодирование по длине прогона или кодирование Голомба. Это не должно быть слишком сложно, и может принести вам немного компрессии.

Кодировка Голомба

Я также нашел JsZip. Я думаю, вы могли бы проверить код и использовать алгоритм, только если он совместим.

Надеюсь, это поможет.

http://jszip.stuartk.co.uk/

6 голосов
/ 14 сентября 2011

Мне недавно пришлось сохранять огромные объекты JSON в localStorage.

Во-первых, да, они остаются в юникоде. Но не пытайтесь сохранить что-то вроде объекта прямо в локальном хранилище. Это должна быть строка.

Вот некоторые методы сжатия, которые я использовал (которые, казалось, хорошо работали в моем случае) перед преобразованием моего объекта в строку:

Любые числа можно преобразовать из основания 10 в основание 36, выполнив что-то вроде (+ num) .toString (36). Например, число 48346942 будет тогда «ss8qm», что на 1 символ (включая кавычки) меньше. Возможно, что добавление кавычек фактически увеличит количество символов. Таким образом, чем больше число, тем лучше. Чтобы преобразовать его обратно, вы должны сделать что-то вроде parseInt ("ss8qm", 36).

Если вы храните объект с любой клавишей, которая будет повторяться, лучше всего создать поисковый объект, в котором вы назначите сокращенную клавишу оригиналу. Итак, для примера, если у вас есть:

{
    name: 'Frank',
    age: 36,
    family: [{
        name: 'Luke',
        age: 14,
        relation: 'cousin'
    }, {
        name: 'Sarah',
        age: 22,
        relation: 'sister'
    }, {
        name: 'Trish',
        age: 31,
        relation: 'wife'
    }]
}

Тогда вы можете сделать это:

{
    // original w/ shortened keys
    o: {    
        n: 'Frank',
        a: 36,
        f: [{
            n: 'Luke',
            a: 14,
            r: 'cousin'
        }, {
            n: 'Sarah',
            a: 22,
            r: 'sister'
        }, {
            n: 'Trish',
            a: 31,
            r: 'wife'
        }]
    },

    // lookup
    l: {
        n: 'name',
        a: 'age',
        r: 'relation',
        f: 'family'
    }
}

Опять же, это окупается с размером. И повторение. В моем случае это сработало очень хорошо. Но это зависит от предмета.

Все они требуют, чтобы функция уменьшалась, а одна - расширялась обратно.

Кроме того, я бы порекомендовал создать класс, который будет использоваться для хранения и извлечения данных из локального хранилища. Я столкнулся с нехваткой места. Таким образом, запись потерпит неудачу. Другие сайты также могут записывать в локальное хранилище, которое может забрать часть этого пространства. См. этот пост для более подробной информации.

В том классе, который я создал, я сначала попытался удалить любой предмет с данным ключом. Затем попробуйте setItem. Эти две строки обернуты пробным уловом. Если происходит сбой, предполагается, что хранилище заполнено. Затем он очистит все в localStorage в попытке освободить место для него. После сброса он попытается снова установить элемент. Это тоже завернуто в попытку поймать. Так как он может потерпеть неудачу, если сама строка больше, чем то, что может обработать localStorage.

РЕДАКТИРОВАТЬ: Кроме того, вы столкнетесь со сжатием LZW многие люди упоминают. Я реализовал это, и это работало для маленьких строк. Но с большими строками он начал бы использовать недопустимые символы, что приводило к повреждению данных. Так что будьте осторожны, и если вы идете в этом направлении, тестовый тестовый тест

0 голосов
/ 11 июня 2013

Сжатие Base64 для javascript очень хорошо объяснено в этом блоге .Реализация также доступна здесь при использовании всего фреймворка .

0 голосов
/ 14 сентября 2011

Этот вопрос о переполнении стека содержит ответ, который может помочь. Есть ссылка на библиотеку сжатия JavaScript.

...