Как найти файлы filestream
Экземпляр FileStream применяется для чтения и записи данных в любой файл. Для создания экземпляра FileStream потребуется указать следующие фрагменты информации:
Файл, к которому должен получаться доступ.
Режим открытия файла. Например, планируется создать новый файл или же открыть существующий? Если планируется открыть существующий файл, то должно ли перезаписываться имеющееся в нем содержимое, или новые данные должны добавляться к концу файла?
Вид доступа к файлу. Например, нужен ли доступ для выполнения чтения или записи либо того и другого вместе?
Общий доступ, который показывает, должен ли доступ к файлу быть эксклюзивным или же должна быть возможность доступа со стороны других потоков одновременно. Если да, то разрешено ли другим потокам чтение, запись либо то и другое.
Перечисление | Значение |
FileMode | Append, Create, CreateNew, Open, OpenOrCreate, Truncate |
FileAccess | Read, ReadWrite, Write |
FileShare | Delete, Inheritable, None, Read, ReadWrite, Write |
Обратите внимание, что в случае FileMode, если запрашивается режим, не соответствующий существующему состоянию файла, может быть сгенерировано исключение. Значения Append, Open и Truncate будут приводить к генерации исключения, если файл не существует, а значение CreateNew — наоборот, если он уже существует. Значения Create и OpenOrCreate подходят в обоих сценариях, но Create приводит к удалению любого существующего файла и замене его новым, изначально пустым.
Перечисления FileAccess и FileShare являются битовыми флагами, поэтому их значения могут комбинироваться с помощью битовой операции "ИЛИ", т.е. |. Для создания FileStream доступно большое количество конструкторов. Три наиболее простейших из них работают так, как описано ниже:
Как видно в коде, перегруженные версии данных конструкторов способны подставлять стандартные значения FileAccess.ReadWrite и FileShare.Read на месте третьего и четвертого параметров в зависимости от значения FileMode. Можно также создавать файловый поток из экземпляра FileInfo.
После окончания работы поток нужно закрыть:
Закрытие потока приводит к освобождению всех ассоциированных с ним ресурсов и позволяет другим приложениям запускать потоки для работы с тем же файлом. Кроме того, это действие приводит к очистке буфера. Между открытием и закрытием потока нужно производить собственно чтение и/или запись данных. В классе FileStream для этого предусмотрен набор методов.
Метод ReadByte() представляет собой самый простой способ для чтения данных. Он берет один байт из потока и приводит результат к типу int со значением в диапазоне от О до 255. В случае достижения конца потока он возвращает -1.
Если необходимо, чтобы за один раз читалось сразу множество байтов, можно вызывать метод Read(), который читает указанное количество байтов в массив. Метод Read() возвращает действительное количество прочитанных байтов; если возвращается значение О, значит, был достигнут конец потока. Ниже показан пример чтения данных в массив байтов по имени ByteArray:
Во втором параметре метод Read() принимает значение смещения, которое позволяет указать, что массив должен заполняться, начиная не с первого, а с какого-то другого элемента. В третьем параметре можно указать, сколько байтов должно читаться в массив.
Для выполнения записи данных доступно два метода — WriteByte() и Write(). Метод WriteByte() позволяет записывать по одному байту в поток:
Помимо этих методов в FileStream есть и множество других методов и свойств, имеющих отношение к выполнению вспомогательных операций, таких как определение количества байтов в потоке, блокирование потока и очистка буфера. Для выполнения базовых операций чтения и записи эти дополнительные методы обычно применять не требуется; всю информацию о них можно найти в документации SDK.
В данной статье применение класса FileStream иллюстрируются на примере приложения BinaryFileReader, которое может считывать и отображать любой файл. Создайте в Visual Studio 2010 новый проект типа приложения WPF. Это приложение должно иметь один элемент меню, открывающий стандартное диалоговое окно OpenFileDialog для указания файла, и затем отображать содержимое этого файла в двоичном формате.
Поскольку считываться будут двоичные файлы, необходимо чтобы приложение было способно отображать непечатаемые символы. Для этого каждый байт файла будет отображаться отдельно, с выводом по 16 байтов в каждой строке многострочного текстового поля. В случае если байт представляет собой печатаемый ASCII-символ, будет отображаться этот символ, а если нет, то содержащее в байте значение будет отображаться в шестнадцатеричном формате. И в том и в другом случае отображаемый текст должен дополняться пробелами так, чтобы отображаемый байт занимал четыре столбца.
Я работаю над этим приложением, где мне нужно загружать большие файлы данных в мою базу данных SQL Server, и я использую FileStream, чтобы сделать это более эффективно.
Я понимаю, что файлы хранятся непосредственно в моих системных папках (C:\CryptoDB).
Дело в том, что мне нужно манипулировать этими файлами (расшифровывать их), но я не смог восстановить их путь к файлу.
Сделав это, я смогу манипулировать ими напрямую, не перегружая их через SQL, что является реальной тратой.
Что мне удалось сделать до сих пор:
И когда я пытаюсь восстановить путь к файлу:
Если файл на самом деле:
Путь, который вы получаете, правильный, вы должны получить сетевой общий путь, а не локальный путь, и использовать SqlFileStream для открытия потока.
Вы также можете получить дескриптор файла с использованием метода OpenSqlFilestream, т.е. использовать его в Windows API.
ответил(а) 2015-04-13T11:47:00+03:00 6 лет, 7 месяцев назадАлександр ответ велик, спасло меня много проблем, сопоставляя номера страниц/слотов с фактическими LSN. В моем случае с использованием SQL Server 2008 R2 мне пришлось внести некоторые корректировки в его SP, чтобы заставить его работать:
Первый параметр SPs:
В моем случае это уникальный идентификатор, поэтому мне нужен более большой varchar, исходное значение - 19.
Когда запрашивает вывод DBCC PAGE:
SET @parent_object = (SELECT TOP 1 [ParentObject] FROM @DBCC_PAGE_Output WHERE [Поле] = @keyFieldName И [VALUE] = @instanceS)
В оригинале указано "[Field] = 'INSTANCE_S'" , которое, по-видимому, жестко закодировало значение, которое работало для OP, но не для меня. Он должен был соответствовать имени поля ключа таблицы FILESTREAM.
Также, чтобы немного уточнить параметры SPs:
@instanceS = Фактическое значение столбца, которое идентифицирует строку. Будет это всегда соответствует столбцу, установленному как таблица "RowGuid"?
@tableName = Довольно ясно. Имя таблицы FILESTREAM.
@keyFieldName = Имя столбца ключа таблицы. Должна быть исходный столбец, откуда был взят @instanceS.
SQL-запрос для получения физического местоположения всех данных FILESTREAM (источник)
SELECT t.name AS 'table', c.name AS 'column', fg.name AS 'filegroup_name', dbf.type_desc AS 'type_description', dbf.physical_name AS 'physical_location'
FROM sys.filegroups fg
INNER JOIN sys.database_files dbf
ON fg.data_space_id = dbf.data_space_id
INNER JOIN sys.tables t
ON fg.data_space_id = t.filestream_data_space_id
INNER JOIN sys.columns c
ON t.object_id = c.object_id
И c.is_filestream = 1
SQL-запрос для получения подпапок для данных FILESTREAM на сервере:
(Эти таблицы используются только в рамках выделенного соединения с администратором (ЦАП)).
SELECT o.name AS [Таблица], cp.name AS [Column], r.rsguid AS [Rowset GUID], rs.colguid AS [Идентификатор столбца] FROM SYS.SYSROWSETS r CROSS APPLY sys.sysrscols rs
JOIN sys.partitions p ON rs.rsid = p.partition_id
JOIN sys.objects o ON o.object_id = p.object_id
JOIN sys.syscolpars cp ON cp.colid = rs.rscolid
WHERE rs.colguid НЕ НУЛЛ И o.object_id = cp.id И r.rsguid НЕ НУЛЛ И r.rowsetid = rs.rsid И o.name = 'DOCUMENT' и cp.name = 'DIGITAL_FILE';
2,1. Результат запроса:
Таблица: ДОКУМЕНТ
Столбец: DIGITAL_FILE
GUID GUID: 0x6AA5E6045794D34D8B1FAC0F49A49B0A
GUID столбца: 0xD756E638FB2CC843AE98F489B57F6D7D
Вычисление подпункта из этих указаний:
2.2 Результат расчета полного пути для хранения FILESTREAM:
Получить исходное имя файла для значения BLOB в папке NTFS.
3,1. Сохраненная процедура запроса расширенной информации о странице SQL Server
3,2. Сохраненная процедура для исходного исходного запроса запроса для поля BLOB FILESTREAM'а таблицы
3.3. Пример запроса хранимой процедуры для получения имени файла в папке NTFS для BLOB:
3.4. Результат (исходное имя файла в папке NTFS):
3,5. Полный путь к результату:
Изучение задач, связанных с программированием баз данных на платформе MS SQL Server.
среда, 9 июля 2014 г.
Файловые потоки
Если в таблице базы данных MS SQL требуется хранить большие двоичные данные, например, файлы с большими документами, аудио или видео файлы, то обычно для этого используются столбцы типа varbinary ( max ). Такой столбец может вместить до двух гигабайт данных. Внутренне он (при большой длине) не хранится в строке из-за недостатска места. На строке есть только указатель на корневую страницу типа LOB. Сама строка с двоичным значением дробится на отдельные страницы, которые образуют структуру бинарного дерева, по которому можно спускаться, начиная с корневой страницы, через указатели.
Несмотря на несомненные достоинства у этого способа хранения есть недостатки:
- при обновлении больших файлов может увеличиться уровень фрагментации
- увеличивается объем кэша
- база данных может стать очень большой
- доступ на чтение и запись больших файлов может стать медленным
- нельзя сохранить файл, объем которого превышает 2 гигабайта
В MS SQL 2008 появились файловые потоки, которые призваны устранить эти недостатки. Файловые потоки позволяют хранить данные в виде отдельных файлов. Размер сохраняемых данных ограничен лишь доступным объмом на диске. При этом можно осуществлять доступ к данным как средствами Transact-SQL, как если бы мы хранили бинарник в столбце varbinary ( max ), так и средствами потокового доступа, используя средства Win32 Api. При потоковом доступе во многих случаях увеличивается скорость чтения и записи в файлы. Снижается нагрузка на оперативную память: буферный пул не используется при операциях через файловые потоки, используется системный кэш NT.
Операции чтения и записи происходят в контексте транзакции, логируются транзакционным логом. На время операции запись таблицы блокируется для других соединений.
Для работы с загруженными файлами средствами файловых потоков создается отдельная файловая группа, которая входит в бэкап базы. Это исключает проблемы администрирования и безопасности. Кроме того, файловые потоки интегрируются со многими другими копонентами Database Engine. Например, можно выполнять полнотекстовое индексирование данных filestream. Есть несущественные ограничения, например, нельзя использовать базу с файловой группой filestream в сеансе зеркального отображения. При работе с данными filestream в транзакции, доступен только уровень изоляции read committed.
Microsoft рекомендует использовать файловые потоки для ускорения потокового доступа, если есть файлы, размер которых превышает 1 мегабайт.
Приступим к разработке таблицы, хранящей данные filestream и изучим возможности операций с ней. Сперва требуется включить доступ к технологии filestream. На серверном компьютере нажимаем Пуск->Все программы->Microsoft SQL Server 2012->Средства настройки->Диспетчер конфигураций. В левом окне выбираем службы SQL Server, в правом окне выбираем службу нашего сервера, нажимаем правую кнопку мыши, выбираем свойства. В окне свойств выбираем вкладку FILESTREAM:
Верхняя галочка дает возможность осуществлять доступ к данным FILESTREAM средствами Transact-SQL, нажав следующую галочку, можно работать с filestream средствами потокового доступа. Последняя галочка дает возможность потокового доступа с удаленных компьютеров, при этом выбирается имя общей папки. Проставив все галочки, жмем OK. Далее необходимо выполнить код:
exec sp_configure 'filestream_access_level' , 2
reconfigure
Перезагружаем службу сервера. Создадим базу данных Files. Пусть она сразу не содержит файловую группу filestream:
create database Files
Теперь требуется добавить файловую группу filestream:
alter database Files add file ( name = FilesData , filename = 'C:\Users\edynak\Desktop\DataFiles' ) to filegroup FilesWrk
При добавлении файловой группы мы указали ключевое слово filestream . При добавлении файла к файловой группе требуется указать только логическое и физическое имена. Физическое имя это директория. В момент выполнения кода она не должна существовать. Должна существовать ее родительская папка. Файловых групп filestream может быть несколько, одну из них можно пометить как используемую по умолчанию с помощью ключевого слова default. Иначе файловой группой filestream, используемой по умолчанию, станет первая созданная файловая группа filestream.
После выполнения кода директория DataFiles появилась на рабочем столе, в ней есть пустая директория $FSLOG и файл filestream.hdr:
Папка $FSLOG очень важна, она логирует операции с файлами файловой группы filestream, играет роль транзакционного лога, и ее данные используется при бэкапировании и восстановлении базы.
Теперь создадим две таблицы:
Первая таблица хранит двоичные данные с помощью традиционного подхода, вторая имеет столбец типа varbinary ( max ), отмеченный опцией filestream. В конце определения второй таблицы указано ключевое слово filestream_on для выбора файловой группы filestream, в которой будут размещены данные. Если бы это слово не было указано, то использовалась бы файловая группа filestream, используемая по умолчанию. У таблицы есть столбец типа uniqueidentifier, помеченный свойством rowguidcol, на нем создан уникальный индекс. Это обязательно для таблицы с filestream-столбцом. Он используется на странице для того, чтобы по строке определить расположение файла. Чтобы не думать о том какие значения хранить в этом столбце я сделал для него значение по умолчанию, которое генерирует новый идентификатор-guid. Но поскольку этот столбец входит как ведущий столбец в индекс, неправильно использовать в качестве значения по умолчанию функцию newid. Вместо нее используется функция newsequentialid, которая случайным образом генерирует идентификаторы, которые все время возрастают.
После создания таблиц в папке DataFiles появилась директория с именем в стиле guid. Такая директория появляется для каждой секции каждой таблицы, имеющей данные filestream (если таблица не секционирована, то появляется одна папка для этой таблицы). Внутри новой директории есть еще одна директория с guid-именем, которая соответствует столбцу с опцией filestream:
С таблицей FilesStream теперь можно производить все привычные операции: select, insert, update, delete:
В директории, соответствующей столбцу, появился файл. Если его открыть с помощью Notepad, то мы увидим вставленные данные:
Поскольку мы смогли открыть файл, то он не блокируется сервером. Это связано с тем, что каждой строке, в которой заполнен столбец varFileCont, будет соответствовать один или несколько файлов. Открытие каждого из них севером снизило бы производительность. Поэтому надо быть осторожным, если этот файл, например, будет удален, то дальнейшая штатная работа с таблицей будет невозможна. При попытке доступа к ней, соединение будет отключено.
Если выполнить обновление столбца во вставленной строке, то увидим уже 2 файла. В одном из файлов будет храниться новое значение, а во втором - старое:
Это говорит о том, что при обновлении существующий файл не меняется, а создается новый. Старый же файл со временем будет удален сборщиком мусора, который работает как отдельный поток и периодически проверяет наличие данных для удаления. Если база данных имеют не простую модель восстановления, то сборщик мусора активируется после того как дважды произошло резервное копирование журнала транзакций базы. Технология сборщика мусора во многом была заимствована компонентом In Memory OLTP, когда происходит отображение данных из таблиц оперативной памяти на файлы данных и дельт (которые находятся в файловой группе с опцией memory_optimized_data).
Создадим хранимую процедуру для загрузки бинарных данных в обычную таблицу:
В данной статье я расскажу как включить работу с файловым типом данных - filestream - в случае, если база данных уже создана ранее. Большинство примеров в сети Интернет рассказывает только как настроить filestream при создании новой базы и приводят SQL-скрипты для этого. Есть и примеры с обновлением базы данных, но опять же с приведением SQL-скриптов. На самом деле это можно сделать и через визуальный интерфейс MS SQL Server Management Studio. Об это и пойдет речь в данной статье.
Итак, Ваша база данных уже создана и, например, работает некоторое время. Вы решили использовать filestream для каких-то новых данных в вашей базе. (О том как включить filestream на уже созданной таблице с blob (бинарными) данными читайте в следующей статье.)
Т.е. в данном примере стоит задача создать новую таблицу для хранения filestream данных на уже существующей базе данных.
Итак, инструкция:
Шаг 1. Создание файловой группы. Все созданные в дальнейшем папки для хранения записей типа filestream будут объединяться в эти группы. Вы можете создать одну группу или несколько в зависимости от потребностей.
Первоначально нам необходимо открыть свойства базы данных, для этого в окне Object Explorer выберите свою базу и в контекстном меню перейдите по пункту "Properties":
В открывшемся диалоговом окне свойств выбранной БД в блоке "Select a page" выберите пункт "Filegroups".
В правой части окна под блоком Filestream нажмите кнопку "Add". Появится новая строка, в которой в колонке "Name" введите любое произвольное название группы на англ.языке без пробелов.
Шаг 2. Создание папки для хранения данных типа filestream.
- Колонка "File Type" - выберите тип "Filestream Data"
- Колонка "Filegroup" - укажите ранее созданную файловую группу
- Колонка "Logical Name" - введите любое произвольное название на англ.языке без пробелов (в дальнейшем сервер создаст папку с таким именем)
- Колонка "Path" - укажите путь, где будут храниться все файлы типа filestream. Путь должен быть указан без последней папки, т.к. ее сервер создаст сам по имени предыдущей колонки.
Теперь можно нажать кнопку ОК, чтобы сохранить результат:
Чтобы увидеть, что сделал SQL сервер в результате наших действий, перейдите по пути, который Вы указали как путь для хранения filestream-данных.
Вы увидите, что была создана папка, по имени "Logical Name", в которой расположены некоторые служебные файлы и папки:
Изменять или удалять данную служебную информацию не рекомендуется.
Шаг 3. Создание новой таблицы для хранения данных типа filestream. Вот здесь к сожалению без SQL-скрипта не обойтись, т.к. создать подобный filestream-столбец через конструктор таблиц невозможно. Поэтому я рекомендую сначала создать таблицу с обязательными для filestream колонками с помощью скрипта, а затем уже через конструктор дополнить ее нужными Вам полями.
Итак, открываем окно для ввода скриптов (для этого выберите свою БД и нажмите кнопку "New Query").
В открывшемся окне введите следующий скрипт:
Будет создана таблица с двумя обязательными полями: поле fileGUID - обязательный идентификатор, который сервер будет использовать для обозначения фалов, и поле fileDATA, непосредственно ссылающее на нужный файл в файловой системе.
После выполнения данного скрипта в созданной ранее папке Вы увидите новую папку с именем, похожим на некий идентификатор. Эта папка будет соответствовать Вашей таблице и в ней будут храниться сохраненные файлы.
Теперь Вы можете перейти в конструктор таблицы и дополнить ее нужными полями.
Обратите внимание, что из конструктора не видно, является ли поле fileDATA полем типа filestream.
Если Вы хотите проверить, является ли колонка полем типа filestream, можно выполнить такой скрипт:
В результате выполнения этого скрипта, Вы увидите список всех колонок указанной таблицы, которые имеют атрибут filestream.
Использование ID в URL-адресах вместо UserKey
Пошаговая инструкция по переносу содержимого KooBoo с XML на SQL Server 2008 R2
Читайте также: