Проблема по тегу "Файловая система" - PullRequest
5 голосов
/ 18 мая 2009

По рекреационным причинам я написал класс PHP, который классифицирует файлы с тегами, а не иерархически, теги хранятся в самом имени файла в виде + tag1 + tag2 + tagN + MD5.EXTENSION, и поэтому я застрял с пределом символов (255), установленным FS / OS. Вот этот класс:

<?php

class TagFS
{
    public $FS = null;

    function __construct($FS)
    {
        if (is_dir($FS) === true)
        {
            $this->FS = $this->Path($FS);
        }
    }

    function Add($path, $tag)
    {
        if (is_dir($path) === true)
        {
            $files = array_slice(scandir($path), 2);

            foreach ($files as $file)
            {
                $this->Add($this->Path($path) . $file, $tag);
            }

            return true;
        }

        else if (is_file($path) === true)
        {
            $file = md5_file($path);

            if (is_file($this->FS . $file) === false)
            {
                if (copy($path, $this->FS . $file) === false)
                {
                    return false;
                }
            }

            return $this->Link($this->FS . $file, $this->FS . '+' . $this->Tag($tag) . '+' . $file . '.' . strtolower(pathinfo($path, PATHINFO_EXTENSION)));
        }

        return false;
    }

    function Get($tag)
    {
        return glob($this->FS . '*+' . str_replace('+', '{+,+*+}', $this->Tag($tag)) . '+*', GLOB_BRACE);
    }

    function Link($source, $destination)
    {
        if (is_file($source) === true)
        {
            if (function_exists('link') === true)
            {
                return link($source, $destination);
            }

            if (is_file($destination) === false)
            {
                exec('fsutil hardlink create "' . $destination . '" "' . $source . '"');

                if (is_file($destination) === true)
                {
                    return true;
                }
            }
        }

        return false;
    }

    function Path($path)
    {
        if (file_exists($path) === true)
        {
            $path = str_replace('\\', '/', realpath($path));

            if ((is_dir($path) === true) && ($path[strlen($path) - 1] != '/'))
            {
                $path .= '/';
            }

            return $path;
        }

        return false;
    }

    function Tag($string)
    {
        /*
        TODO:
        Remove (on Windows):            . \ / : * ? " < > |
        Remove (on *nix):               . /
        Remove (on TagFS):              + * { }
        Remove (on TagFS - Possibly!)   -
        Max Chars (in Windows)          255
        Max Char (in *nix)              255
        */

        $result = array_filter(array_unique(explode(' ', $string)));

        if (empty($result) === false)
        {
            if (natcasesort($result) === true)
            {
                return strtolower(implode('+', $result));
            }
        }

        return false;
    }
}

?>

Я считаю, что эта система хорошо работает для пары небольших тегов, но моя проблема в том, что размер всего имени файла превышает 255 символов. Какой подход я должен использовать, чтобы обойти ограничение имени файла? Я имею в виду разделение тегов на несколько жестких ссылок одного и того же файла, но перестановки могут убить систему.

Есть ли другие способы решения этой проблемы?

EDIT - Некоторые примеры использования:

<code><?php

$images = new TagFS('S:');

$images->Add('P:/xampplite/htdocs/tag/geoaki.png', 'geoaki logo');
$images->Add('P:/xampplite/htdocs/tag/cloud.jpg', 'geoaki cloud tag');
$images->Add('P:/xampplite/htdocs/tag/cloud.jpg', 'nuvem azul branco');
$images->Add('P:/xampplite/htdocs/tag/xml-full.gif', 'geoaki auto vin api service xml');
$images->Add('P:/xampplite/htdocs/tag/dunp3d-1.jpg', 'dunp logo');
$images->Add('P:/xampplite/htdocs/tag/d-proposta-04c.jpg', 'dunp logo');

/*
[0] => S:/+api+auto+geoaki+service+vin+xml+29be189cbc98fcb36a44d77acad13e18.gif
[1] => S:/+azul+branco+nuvem+4151ae7900f33788d0bba5fc6c29bee3.jpg
[2] => S:/+cloud+geoaki+tag+4151ae7900f33788d0bba5fc6c29bee3.jpg
[3] => S:/+dunp+logo+0cedeb6f66cbfc3974c6b7ad86f4fbd3.jpg
[4] => S:/+dunp+logo+8b9fcb119246bb6dcac1906ef964d565.jpg
[5] => S:/+geoaki+logo+5f5174c498ffbfd9ae49975ddfa2f6eb.png
*/
echo '<pre>';
print_r($images->Get('*'));
echo '
'; / * [0] => S: / + azul + branco + nuvem + 4151ae7900f33788d0bba5fc6c29bee3.jpg * / echo '
';
print_r($images->Get('azul nuvem'));
echo '
'; / * [0] => S: / + dunp + logo + 0cedeb6f66cbfc3974c6b7ad86f4fbd3.jpg [1] => S: / + dunp + logo + 8b9fcb119246bb6dcac1906ef964d565.jpg [2] => S: / + geoaki + logo + 5f5174c498ffbfd9ae49975ddfa2f6eb.png * / echo '
';
print_r($images->Get('logo'));
echo '
'; / * [0] => S: / + dunp + logo + 0cedeb6f66cbfc3974c6b7ad86f4fbd3.jpg [1] => S: / + dunp + logo + 8b9fcb119246bb6dcac1906ef964d565.jpg * / echo '
';
print_r($images->Get('logo dunp'));
echo '
'; / * [0] => S: / + geoaki + logo + 5f5174c498ffbfd9ae49975ddfa2f6eb.png * / echo '
';
print_r($images->Get('geo* logo'));
echo '
'; ?>

РЕДАКТИРОВАТЬ: В связи с несколькими предложениями использовать базу данных без сервера или любой другой тип таблицы поиска (XML, плоские, пары ключ / значение и т. Д.), Я хочу уточнить следующее: хотя этот код написан на PHP, идея состоит в том, чтобы перенести его на Python и сделать из него приложение для настольного компьютера - это не имеет никакого отношения (помимо примера, конечно) к PHP. Кроме того, , если мне нужно использовать какую-то таблицу поиска, я определенно пойду с SQLite 3, но то, что я ищу, - это решение, которое не требует каких-либо других дополнительных "технологий", кроме файловая система (папки, файлы и жесткие ссылки).

Вы можете назвать меня чокнутым, но я пытаюсь достичь двух простых целей: 1) освободить систему от "мусора" (например, кому нравится Thumbs.db или DS_STORE?) И 2) сохранить файлы легко идентифицируется, если по какой-то причине справочная таблица (в данном случае SQLite) становится занятой, поврежденной, потерянной или забытой (например, в резервных копиях).

PS: предполагается, что он будет работать как в Linux, Mac, так и в Windows (под NTFS).

Ответы [ 14 ]

0 голосов
/ 22 мая 2009

Избегать использования SQLite, поскольку он «не является родным для PHP», кажется ложной дихотомией, поскольку он скомпилирован практически во все практические дистрибутивы PHP. Если вы предпочитаете решение, отличное от SQL, berkeleydb предоставляет простое хранилище значений ключей, которое можно использовать, чтобы связать список имен файлов с любыми заданными именами тегов со списками тегов.

Но воспользуйтесь решением SQL. Это будет быстро, переносимо и проще, чем вы думаете.

0 голосов
/ 22 мая 2009

весь смысл тегов заключается в возможности быстрого поиска нескольких комбинаций тегов. в идеале вы хотите иметь базу данных с таблицей тегов {tag, path-to-file}. если вы настроены на сохранение своих тегов в имени файла, вам нужно использовать какое-то сжатие. вокруг таблицы поиска (дБ или плоский файл), отображая каждый тег в двухсимвольный код (например, aa: tag1, ab: tag2, ac: tag3 ...). придерживаясь ascii, это должно дать вам ~ 10 тыс. тегов, если этого недостаточно, используйте три символа. теперь ваше имя файла будет примерно таким: aa.ag.f2.gx.ty.extension

еще один момент, на который следует обратить внимание: поскольку вы хотите искать по нескольким тегам, вы должны убедиться, что коды тегов в вашем имени файла находятся в строгом лексическом порядке. затем для одновременного поиска по тегам aa, f3 и yz выполните команду "ls .*aa.*f3.*yz.*", которая выберет имена файлов, содержащие все эти коды.

0 голосов
/ 22 мая 2009

Если вы не хотите использовать базу данных, почему бы не попробовать xml, вы можете перечислить все свои данные следующим образом:

<file>
  <md5>MD5</md5>
  <body>tag5+tag4+tag3</body>
</file>

Вы можете легко добавить больше как заголовок и описание.

0 голосов
/ 18 мая 2009

Вы должны сделать каталоги тегов вместо элементов имени файла, то есть вместо /dir/tag1+tag2+tagN+MD5.EXT, /dir/tag1/tag2/tagN/MD5.EXT. Вы стреляете себе в ногу несколькими способами, рассматривая иерархию каталогов как нечто, чего следует избегать.

Если вы избегаете этого, потому что считаете, что создать структуру каталогов по требованию сложно, вам следует обратиться к третьему аргументу, $recursive, к mkdir PHP.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...