- Фантастика и фэнтези
- Ироническое фэнтези
- Стимпанк
- Детективная фантастика
- Киберпанк
- Попаданцы
- LitRPG
- Космоопера
- Технофэнтези
- Городская фантастика
- Русское фэнтези
- Юмористическая фантастика
- Космическая фантастика
- Боевое фэнтези
- Эпическая фантастика
- Зарубежная фантастика
- Книги магов
- Мистика
- Разная фантастика
- Разное фэнтези
- Любовное фэнтези
- Романтическая фантастика
- Городское фентези
- Историческая фантастика
- Историческое фэнтези
- Социально-философская фантастика
- Сказочная фантастика
- Иностранное фэнтези
- Романтическое фэнтези
- Ироническая фантастика
- Ужасы и Мистика
- Постапокалипсис
- Героическая фантастика
- Фэнтези
- Научная Фантастика
- Социально-психологическая
- Альтернативная история
- Боевая фантастика
- Разная литература
- Пословицы, поговорки
- Шахматы
- Визуальные искусства
- Фанфик
- Авто и ПДД
- Военное
- Отраслевые издания
- Гиды, путеводители
- Зарубежная образовательная литература
- Военная история
- Цитаты из афоризмов
- Современная литература
- Великолепные истории
- Начинающие авторы
- Современная зарубежная литература
- Боевые искусства
- Изобразительное искусство, фотография
- Кино
- Литература 19 века
- Недвижимость
- Музыка, музыканты
- Готические новеллы
- Истории из жизни
- Культура и искусство
- Спецслужбы
- Зарубежная прикладная литература
- Музыка, танцы
- Подростковая литература
- Прочее
- Военная техника, оружие
- Газеты и журналы
- Периодические издания
- Домоводство, Дом и семья
- Любовные романы
- Экономическая литература
- Научные и научно-популярные книги
- О животных
- Биохимия
- Культурология
- Юриспруденция
- Политика
- Психотерапия
- Языкознание
- Научпоп
- Медицина
- Психология, личное
- Радиотехника
- Филология
- Педагогика
- Образовательная литература
- Деловая литература
- Физика
- Науки: разное
- Химия
- Воспитание детей, педагогика
- Детская психология
- Зарубежная публицистика
- Биология
- Архитектура
- Зарубежная психология
- Науки о космосе
- Социология
- Математика
- География
- Беременность, ожидание детей
- Литературоведение
- Транспорт, военная техника
- Обществознание
- Зоология
- География
- Альтернативная медицина
- Иностранные языки
- Ветеринария
- Рефераты
- Астрология
- Биофизика
- Экология
- История Европы
- Учебники
- Шпаргалки
- Государство и право
- Ботаника
- Религиоведение
- История
- Техническая литература
- Прочая научная литература
- Психология
- Детективы и Триллеры
- Справочная литература
- Проза
- Новелла
- Юмор
- Проза
- Историческая проза
- Русская современная проза
- Советская классическая проза
- Повести
- Очерки
- Эссе
- Рассказы
- Зарубежная современная проза
- Сентиментальная проза
- Зарубежная классика
- Афоризмы
- Эпистолярная проза
- Феерия
- Семейный роман/Семейная сага
- Разное
- Антисоветская литература
- Магический реализм
- Русская классическая проза
- Современная проза
- О войне
- Контркультура
- Классическая проза
- Поэзия, Драматургия
- Детская литература
- Детская фантастика
- Детские остросюжетные
- Детские стихи
- Детские приключения
- Внеклассное чтение
- Учебная литература
- Зарубежные детские книги
- Бизнес
- Загадки
- Книги для подростков
- Школьные учебники
- Детский фольклор
- Книги для дошкольников
- Детские детективы
- Детская познавательная и развивающая литература
- Буквари
- Прочая детская литература
- Сказка
- Детская проза
- Детская образовательная литература
- Юмор
- Документальные книги
- Бизнес
- Внешнеэкономическая деятельность
- Тайм-менеджмент
- Кадровый менеджмент
- О бизнесе популярно
- Управление, подбор персонала
- Бизнес
- Менеджмент и кадры
- Продажи
- Экономика
- Ценные бумаги и инвестиции
- Малый бизнес
- Делопроизводство, офис
- Корпоративная культура, бизнес
- Банковское дело
- Финансы
- Зарубежная деловая литература
- Ораторское искусство / риторика
- Личные финансы
- Интернет-бизнес
- Поиск работы
- Государственное и муниципальное управление
- Бухучет и аудит
- Работа с клиентами
- Менеджмент
- Краткое содержание
- Личная эффективность
- Переговоры
- Приключения
- Старинная литература
- Религия и духовность
- Компьютеры и Интернет
- Блог
Читаем без скачивания C++17 STL Стандартная библиотека шаблонов - Яцек Галовиц
Шрифт:
Интервал:
Закладка:
for (const auto &[ext, stats] : ext_stats(dir)) {
const auto &[accum_size, count] = stats;
cout << setw(15) << left << ext << ": "
<< setw(4) << right << count
<< " items, avg size "
<< setw(4) << size_string(accum_size / count)
<< 'n';
}
}
10. Компиляция и запуск программы дадут следующий результат. Я предоставил ей в качестве аргумента командной строки каталог, содержащий офлайн-справку по С++.
$ ./file_type ~/Documents/cpp_reference/
.css : 2 items, avg size 41K
.gif : 7 items, avg size 902B
.html : 4355 items, avg size 38K
.js : 3 items, avg size 4K
.php : 1 items, avg size 739B
.png : 34 items, avg size 2K
.svg : 53 items, avg size 6K
.ttf : 2 items, avg size 421K
Инструмент для уменьшения размера папки путем замены дубликатов символьными ссылками
Существует множество инструментов, сжимающих данные разными способами. Наиболее известными примерами таких алгоритмов/форматов являются ZIP и RAR. Подобные инструменты уменьшают размер файлов, снижая их внутреннюю избыточность.
Прежде чем сжать файлы в архив, можно довольно просто снизить использование диска, просто удалив повторяющиеся файлы. В данном примере мы реализуем небольшой инструмент, который рекурсивно проходит по каталогу и в процессе ищет файлы с одинаковым содержимым. Если он найдет такие файлы, то удалит все дубликаты, кроме одного. Все удаленные файлы будут заменены символьными ссылками, которые указывают на оставшийся уникальный файл. Это позволяет сэкономить место, не выполняя сжатия и сохраняя данные.
Как это делается
В данном примере мы реализуем небольшой инструмент, который определяет, какие файлы в каталоге дублируют друг друга. Зная это, он удалит все файлы, кроме одного, и заменит их символьными ссылками, что уменьшит размер каталога.
Убедитесь, что создали резервные копии системных данных. Мы будем работать с функциями STL, которые удаляют файлы. Неверно указанный путь для такой программы может привести к тому, что программа жадно удалит нежелательным способом слишком много файлов.
1. Сначала включим все необходимые заголовочные файлы и объявим об использовании пространств имен std и filesystem по умолчанию:
#include <iostream>
#include <fstream>
#include <unordered_map>
#include <filesystem>
using namespace std;
using namespace filesystem;
2. Чтобы определить, какие файлы являются дубликатами друг друга, создадим ассоциативный массив, в котором соотносятся хеши файлов и путь к первому файлу, из которого был получен этот хеш. Для получения таких хешей следует использовать популярный алгоритм, такой как MD5 или SHA. В целях сохранения данного примера чистым и простым просто считаем весь файл в строку, а затем задействуем объект хеш-функции, уже применяемый unordered_map для подсчета хешей строк:
static size_t hash_from_path(const path &p)
{
ifstream is {p.c_str(),
ios::in | ios::binary};
if (!is) { throw errno; }
string s;
is.seekg(0, ios::end);
s.reserve(is.tellg());
is.seekg(0, ios::beg);
s.assign(istreambuf_iterator<char>{is}, {});
return hash<string>{}(s);
}
3. Затем реализуем функцию, которая создает такой ассоциативный массив, основанный на хешах, и удаляет дубликаты. Она рекурсивно итерирует по каталогу и его подкаталогам:
static size_t reduce_dupes(const path &dir)
{
unordered_map<size_t, path> m; size_t count {0};
for (const auto &entry :
recursive_directory_iterator{dir}) {
4. Для каждой записи каталога функция проверяет, является ли эта запись каталогом. Все каталоги опускаются. Для каждого файла генерируем значение хеша и пробуем вставить его в ассоциативный массив. Если последний уже содержит такой хеш, то это значит, что файл с таким хешем уже был добавлен. Соответственно, мы нашли дубликат! В случае конфликтов во время вставки второе значение в паре, которую возвращает try_emplace, равно false.
const path p {entry.path()};
if (is_directory(p)) { continue; }
const auto &[it, success] =
m.try_emplace(hash_from_path(p), p);
5. Задействуя значения, возвращаемые try_emplace, мы можем сказать пользователю, что мгновение назад вставили файл, поскольку встретили этот хеш в первый раз. Если мы нашли дубликат, то сообщаем пользователю о том, что второй файл является дубликатом, и удаляем его. После удаления создаем символьную ссылку, которая заменяет дубликат.
if (!success) {
cout << "Removed " << p.c_str()
<< " because it is a duplicate of "
<< it->second.c_str() << 'n';
remove(p);
create_symlink(absolute(it->second), p);
++count;
}
6. После перебора в файловой системе возвращаем количество файлов, которые мы удалили и заменили файловыми ссылками.
}
return count;
}
7. В функции main убеждаемся, что пользователь передал каталог в командной строке и что этот каталог существует:
int main(int argc, char *argv[])
{
if (argc != 2) {
cout << "Usage: " << argv[0] << " <path>n";
return 1;
}
path dir {argv[1]};
if (!exists(dir)) {
cout << "Path " << dir << " does not exist.n";
return 1;
}
8. Единственное, что нам осталось сделать, — вызвать функцию reduce_dupes для этого каталога и вывести на экран информацию о том, сколько файлов мы удалили:
const size_t dupes {reduce_dupes(dir)};
cout << "Removed " << dupes << " duplicates.n";
}
9. Компиляция и запуск программу, для примера каталога, содержащего дубликаты, выглядит следующим образом. Я использовал инструмент du, чтобы проверить размер каталога до и после запуска нашей программы, с целью продемонстрировать работоспособность нашего подхода:
$ du -sh dupe_dir
1.1M dupe_dir
$ ./dupe_compress dupe_dir
Removed dupe_dir/dir2/bar.jpg because it is a duplicate of
dupe_dir/dir1/bar.jpg
Removed dupe_dir/dir2/base10.png because it is a duplicate of
dupe_dir/dir1/base10.png
Removed dupe_dir/dir2/baz.jpeg because it is a