FileAttributes и проблемы с битовой маской

По какой-то причине, когда я пытаюсь проверить файл с помощью FileAttributes.Normal, мне кажется, что почти ни один из моих файлов не отображается в моем поиске. Согласно API, это потому, что установлены некоторые другие атрибуты. Ничего страшного, мне просто нужно искать то, что мне не нужно. Вот где возникает проблема.

Я невероятно устарел в математике с побитовыми операторами, особенно когда дело касается одновременной проверки нескольких вещей. Я пытаюсь выяснить, как получить оператор if для возврата false, если присутствует какой-либо из определенного количества атрибутов файла (т.е. НИКТО из указанных атрибутов не может быть найден, если он хочет пройти через мой поиск). Вот что я написал до сих пор:

if ((File.GetAttributes(stringFileName) &
   (FileAttributes.System | FileAttributes.Hidden | FileAttributes.Archive |
    FileAttributes.Encrypted | FileAttributes.Temporary)) == 0)

Я думаю, что нужно взять совокупность всех различных атрибутов и сравнить их с исходными атрибутами файла. Если найдено какое-либо совпадение, все отображается нулевым. Однако, похоже, это работает не так, как задумано. Должен ли я использовать другой оператор, кроме побитового и (&)?

Спасибо!

Обновление:

Похоже, проблема заключалась не в логике битовой маски, а в FileAttributes.Archive. По какой-то причине почти все мои файлы были отмечены этим флагом (возможно, это означает, что они предназначены для резервного копирования?). По крайней мере, теперь я знаю, а знание - половина дела. :)


person Mac Sigler    schedule 19.06.2012    source источник
comment
В качестве пояснения, цель дизайна состоит в том, чтобы оператор if завершился ошибкой, если присутствует какой-либо из атрибутов.   -  person Mac Sigler    schedule 21.06.2012
comment
Если я закомментирую оператор if, он вернет все файлы (включая те, которые я хочу скрыть). Но по какой-то причине, когда я добавляю этот оператор if, файлы почти не отображаются. Я думаю, что файлы помечаются чем-то, что их не должно помечать.   -  person Mac Sigler    schedule 21.06.2012
comment
«Если будет найдено какое-либо совпадение, все будет равно нулю». Это не тот случай. Если у файла есть какой-либо атрибут, который соответствует указанным вами, он будет НЕ-нулевым.   -  person docmanhattan    schedule 21.06.2012


Ответы (3)


Если вам нужны файлы только с установленным атрибутом Normal, тогда

if (File.GetAttributes(stringFileName) == FileAttributes.Normal)
    // True, file with only Normal attribute
else
    // False, file with some attributes but not the Normal one

Согласно MSDN FileAttributes.Normal означает The file is normal and has no other attributes set. This attribute is valid only if used alone.

После некоторого исследования я думаю, что проблема заключается в атрибуте Archive. Хотите протестировать этот простой код?

using System;
using System.IO;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            if (args.Length != 1)
            {
                Console.WriteLine("Usage: CheckAllAtt <directoryName>");
                return;
            }
            var files = Directory.GetFiles(args[0]);
            foreach (string fileName in files)
            {
                FileAttributes att = File.GetAttributes(fileName);
                DumpAttr(fileName, att);
            }
        }
        private static void DumpAttr(string fileName, FileAttributes att)
        {
            StringBuilder sb = new StringBuilder("File: " + fileName);
            if ((att & FileAttributes.Archive) == FileAttributes.Archive)
                sb.Append(" Archive,");
            if ((att & FileAttributes.Compressed) == FileAttributes.Compressed)
                sb.Append(" Compressed,");
            if ((att & FileAttributes.Device) == FileAttributes.Device)
                sb.Append(" Device,");
            if ((att & FileAttributes.Directory) == FileAttributes.Directory)
                sb.Append(" Directory,");
            if ((att & FileAttributes.Encrypted) == FileAttributes.Encrypted)
                sb.Append(" Encrypted,");
            if ((att & FileAttributes.Hidden) == FileAttributes.Hidden)
                sb.Append(" Hidden,");
            if ((att & FileAttributes.Normal) == FileAttributes.Normal)
                sb.Append(" Normal,");
            if ((att & FileAttributes.NotContentIndexed) == FileAttributes.NotContentIndexed)
                sb.Append(" Normal,");
            if ((att & FileAttributes.Offline) == FileAttributes.Offline)
                sb.Append(" Offline,");
            if ((att & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
                sb.Append(" ReadOnly,");
            if ((att & FileAttributes.ReparsePoint) == FileAttributes.ReparsePoint)
                sb.Append(" ReparsePoint,");
            if ((att & FileAttributes.SparseFile) == FileAttributes.SparseFile)
                sb.Append(" SparseFile,");
            if ((att & FileAttributes.System) == FileAttributes.System)
                sb.Append(" System,");
            if ((att & FileAttributes.Temporary) == FileAttributes.Temporary)
                sb.Append(" Temporary,");

            sb.Length -= 1;
            Console.WriteLine(sb.ToString());
        }
    }
}
person Steve    schedule 19.06.2012
comment
Кажется, что это должно сработать, но, как я отмечал в своем объяснении выше, похоже, что он отфильтровывает все мои файлы. Должен быть установлен какой-то непонятный атрибут, из-за которого он не является Нормальным. Вот почему я решил явно указать, какие атрибуты я не хочу показывать. - person Mac Sigler; 21.06.2012
comment
Тестирование с образцом каталога на моем компьютере сработало, как ожидалось, затем переключение на другой каталог, где я выполняю регулярное резервное копирование, оказалось, что атрибут Archive испортил простой тест на FileAttributes.Normal. Добавлен код, используемый для тестирования папки. - person Steve; 21.06.2012
comment
Я тоже просто самостоятельно понял, что это атрибут Архив. Но спасибо, что подтвердили мои подозрения. - person Mac Sigler; 21.06.2012
comment
Точно. Пытался сбросить атрибут архива (attrib -a filename в окне dos) восстановил работу FileAttributes.Normal - person Steve; 21.06.2012

Это дает вам только те атрибуты, которые вы выбрали.

if ((File.GetAttributes(stringFileName) &
    (FileAttributes.System | FileAttributes.Hidden | FileAttributes.Archive |
    FileAttributes.Encrypted | FileAttributes.Temporary)) != 0)

Просто замените равенство неравенством. Таким образом, если любой из этих атрибутов присутствует, конечный результат будет отличным от нуля.

person TheZ    schedule 19.06.2012
comment
Да, но разве я не хотел бы, чтобы результат был равен нулю, если бы эти атрибуты присутствовали? Т.е. оператор if завершается ошибкой, если эти атрибуты присутствуют. - person Mac Sigler; 21.06.2012
comment
Вы сказали: «Я пытаюсь понять, как заставить оператор if возвращать истину, если присутствует какой-либо из определенного количества атрибутов файла». Вот что это делает. Если какой-либо из флагов установлен, он оценивается как истина, и выполняется оператор if. В вашем комментарии говорится, что вы хотите обратного. Итак, что это такое? - person TheZ; 21.06.2012
comment
Определенно хочу, чтобы он возвращал false, если атрибуты присутствуют. Отредактирую свой исходный пост, чтобы прояснить это. Значит, значит, мой код уже должен работать? Тогда я думаю, у меня проблемы посерьезнее, чем с битовыми масками. :( - person Mac Sigler; 21.06.2012
comment
В конце концов, это был флаг архива. Но спасибо, что побудили меня проверить это. - person Mac Sigler; 21.06.2012
comment
Хорошо, я рада, что ты в этом разобрался :) - person TheZ; 22.06.2012

Ваша логика обратная. Если найдено какое-либо совпадение, то побитовый результат и (&) не равен нулю.

Примеры:

Соответствие: 0101000 & 0100000 = 0100000! = 0

Нет совпадений: 0101000 & 0010000 = 0000000

person zdan    schedule 19.06.2012