C++ Builder
| Главная | Уроки | Статьи | FAQ | Форум | Downloads | Литература | Ссылки | RXLib | Диски |

 
Как сохранить BLOB в файл?, Как сохранить BLOB в файл?
gendalf
Отправлено: 06.12.2005, 13:06


Не зарегистрирован







БД Oracle
На форме TQuery, TDatabase, TDataSource, TDBGrid.
select-м забираю данные, состоящие из нескольких строчных полей и одного поля типа Blob. Далее нужно анализировать строчные поля и, при необходимости, сохранять Blob в файл. Вот тут и не получается.
Код примерно такой:

Q1->Next();
if (Q1->Fields->Fields[x]->AsString == "..." && Q1->Fields->Fields[x1]->IsBlob()) {
// сохранить blob в файл
}

В if пытался использовать TMemoryStream, TBlobStream, TBlobField, TBlobByteData — или ошибки в runtime, или пусто (для TBlobByteData).
Перерыл Examples в Buildere — ничего.
Сам на Buildere пишу не первый год, вроде, но с базами раньше дела не имел совсем. Неделю бьюсь уже, помогите, пож-та.
AVC
Отправлено: 06.12.2005, 13:46


Ветеран

Группа: Модератор
Сообщений: 1583



TBlobField->SaveToFile() должно работать
Вот рабочий код (правда связка не BDE а DOA)
CODE

//---------------------------------------------------------------------------
//                                                         From Table to Disk
//---------------------------------------------------------------------------

void __fastcall TForm1::Bt_ToDiskClick(TObject *Sender)
{
TOracleDataSet  *qry = QryMain;
AnsiString       str;

if (!qry || !qry->Active || qry->IsEmpty()) return;

TField *fldfname = qry->FindField("FileName");
if (!fldfname) return;

if (!qry->FindField("Content")) return;
TBlobField *fldcontent = dynamic_cast<TBlobField*>(qry->FieldByName("Content"));
if (!fldcontent) return;

str = AnsiString("")    +
     "Содержимое всех записей будет сохранено в каталоге <" + FLocalDir + ">" +
     "\n\nВыполнить ?"
    ;

if (Application->MessageBox(str.c_str(), "", MB_YESNO) != IDYES) return;


AnsiString fname;
for (qry->First(); !qry->Eof; qry->Next())
{  fname = FLocalDir + fldfname->AsString;

   if (FileExists(fname))
    {  try         { DeleteFile(fname); }
       catch (...) {;                  }
    }

   try         { fldcontent->SaveToFile(fname); }
   catch (...)
    {  ShowMessage("Ошибка при создании файла <" + fname + ">\n");
    }

}      // !qry->Eof

}
gendalf
Отправлено: 06.12.2005, 14:31


Не зарегистрирован







Компилятор на TOracleDataSet выдал "Undefined symbol", в Include объявление такого класса нет: или из-за того, что у меня Builder 5, или при при установке что-то не выбрал. Поменял на TDataSet — в runtime ошибка на строку:

fldcontent->SaveToFile(fname);

"Invalid BLOB handle in record buffer"
avc*
Отправлено: 06.12.2005, 14:52


Не зарегистрирован







> TOracleDataSet выдал
Это закономерно, я ведь написал — код для DOA.

>"Invalid BLOB handle in record buffer"
Странно, сейчас попробую набросать для BDE.
AVC
Отправлено: 06.12.2005, 15:35


Ветеран

Группа: Модератор
Сообщений: 1583



Попробовал.
Все получилось с первого раза.
Форма, на форме Session, Database, Query, DataSet, сетка (просто для глаз). Все связано. Кнопка с уже приведенным кодом.
Жму. Из каталога приложения забираю файлы.
Для справки: в таблице хранятся файлы в формате MSWord (doc), поле имеет тип BLOB.

На всякий случай цепляю действующий (у меня) пример.


User Attached Image Скачать файл
p14_orabde.rar


gendalf
Отправлено: 07.12.2005, 10:36


Не зарегистрирован







Спасибо, посмотрел Ваш пример, но не помогло. Я попробовал изменить пример под мои нужды. Я изменил:
- SQL в Query1
- в Database: Params, DriverName — "Oracle" (при AliasName "HHCDev (Oracle BDE)" была ошибка "неизвестный алиас" + его нет в списке во время дизайна)
Да, база не на моей машине находится, сразу нужно было сказать наверное.
Вопросы:
- AliasName "HHCDev (Oracle BDE)" у меня нет, коннект к базе с таким алиасом не получается. Может в этом проблема?
- не ясна роль TSession в примере. В свой проект добавил, изменений нет.
- как можно узнать, действительно ли приложение получило blob поле, я пробовал смотреть fldcontent->Size, он равен 1 — это неправильно, по моему.
avc*
Отправлено: 07.12.2005, 11:42


Не зарегистрирован







> AliasName "HHCDev (Oracle BDE)" у меня нет, коннект к базе с таким алиасом не получается.
И не получится, это же моя база. smile.gif
Alias и все прочее с ним конечно же у вас не такие как у меня. Предпологалось что связь с базой у вас настроена. Если это не так то попробуйте в SQLExplorer'е создать алиас (я использовал BDE'ешный драйвер для Oracle) и поработать со своей таблицей.

> не ясна роль TSession
TSession удобен для централизации связи с сервером (BDE все равно его использует, так пусть это будет явно).

> Да, база не на моей машине находится, сразу нужно было сказать наверное.
Это и не требется. У меня, конечно, тоже и даже под управлением другой ОС. Я воспользовался первой встреченой таблицей с полем BLOB на сервере разработки.
А вот Oracle у нас стоит 8i, хотя думаю что это не должно играть особой роли.

> как можно узнать, действительно ли приложение получило blob поле
Я для этого использую иногда dynamic_cast а иногда анализ Field->DataType, по обстановке.

Можете сообщить скрипт таблицы и примерные данные для Blob, буде время — попробую смоделировать.

PS. Если вы пишете приложениедля Oracle переходите на DOA или ODAC
gendalf
Отправлено: 07.12.2005, 12:00


Не зарегистрирован







> Предпологалось что связь с базой у вас настроена.
Настоена. Из SQLNavigator-а все получается — и достать blob и сохранить. Если бы не бинарные данные и писать ничего не пришлось бы, хватало и sqlplus-а + скрипты.

> Я для этого использую иногда dynamic_cast а иногда анализ Field->DataType, по обстановке.
Я не про это. Имел в виду следующее: параллельно делал такие же select-ы ручками и смотрел содержимое blob, размер был явно не 1

> PS. Если вы пишете приложениедля Oracle переходите на DOA или ODAC
Спасибо, попробую.

И еще, что же все-таки имеется в виду "Invalid BLOB handle in record buffer"?

Вернуться в Работа с базами данных в C++Builder