Использование потоков InStream и OutStream
Потоки поддерживаются следующими типами данных Dynamics NAV:
- BLOB (поле в таблице)
- File (переменная)
- XMLPort (переменная, ссылающаяся на объект)
- BigText (переменная)
- Automation (переменная, ссылающаяся на COM объект)
- OCX (переменная, ссылающаяся на Custom Control)
Базовый пример использования потоков приведен в онлайновой справке C/SIDE Reference Guide, здесь же мы рассмотрим передачу информации между указанными типами данных.
| Из / В | BLOB | File | XMLPort | BigText | XMLDom |
| BLOB | := | iF | iS | iS | iS |
| File | iF | gF | iS | iS | iS |
| XMLPort | iS | iS | нет | нет | нет |
| BigText | iS | iS | нет | нет | нет |
| XMLDom | iS | iS | нет | нет | нет |
:= – используется оператор присваивания
iF – используются функции комплексного типа данных (automation) для непосредственной передачи значения другому типу данных.
iS – используются функции комплексного типа данных (automation) для передачи значения другому типу данных с помощью потоков (InStream или OutStream)
gF – системная функция для непосредственного передачи значения между типам данных.
нет – встроенных функций нет, однако передачу можно выполнить с помощью промежуточного типа данных.
Из BLOB в …
Из полей типа BLOB в BLOB
rItemFrom.GET(’70102′);
rItemFrom.CALCFIELDS(Picture);
rItemTo.GET(’1200′);
rItemTo.Picture:=rItemFrom.Picture;
rItemTo.MODIFY;
Из полей типа BLOB во внешний файл
rItem.GET(’70102′);
rItem.CALCFIELDS(Picture);
rItem.Picture.EXPORT(’C:\111\MyPic.BMP’);
Из полей типа BLOB в XMLPort
rSetup.GET;
rSetup.CALCFIELDS(XMLData);
rSetup.XMLData.CREATEINSTREAM(iStream);
XMLPORT.IMPORT(50000,iStream);
Из полей типа BLOB в переменную BigText
rSetup.GET;
rSetup.CALCFIELDS(XMLData);
rSetup.XMLData.CREATEINSTREAM(iStream);
tBigText.READ(iStream);
Из полей типа BLOB в Automation XMLDom
rSetup.GET;
rSetup.CALCFIELDS(XMLData);
rSetup.XMLData.CREATEINSTREAM(iStream);
IF ISCLEAR(OutboundXML) THEN
CREATE(OutboundXML);
OutboundXML.load(iStream);
Из File в …
Из внешнего файла в BLOB
rSetup.GET;
rSetup. XMLData.IMPORT(’C:\111\MyData.XML’);
rSetup.MODIFY;
Из файла в файл
COPY(’C:\111\imp.xml’,'C:\111\imp1.xml’);
Из внешнего файла в XMLPort
fFile.open(’C:\111\imp1.xml’);
fFile.CREATEINSTREAM(iStream);
XMLPORT.IMPORT(50000,iStream);
Из внешнего файла в BigText
fFile.open(’C:\111\imp1.xml’);
fFile.CREATEINSTREAM(iStream);
tBigText.READ(iStream);
Из внешнего файла в Automation XMLDom
fFile.open(’C:\111\imp1.xml’);
fFile.CREATEINSTREAM(iStream);
IF ISCLEAR(OutboundXML) THEN
CREATE(OutboundXML);
OutboundXML.load(iStream);
Из XMLPort в …
Из XMLPort в поле BLOB
rSetup.GET;
rSetup.XMLData.CREATEOUTSTREAM(oStream);
XMLPORT.EXPORT(50000,oStream);
Из XMLPort во внешний файл
fFile.CREATE(’C:\111\imp1.xml’);
fFile.CREATEOUTSTREAM(oStream);
XMLPORT.EXPORT(50000,oStream);
Из XMLPort в XMLPort, в BigText, в XMLDom
Выполняется с помощью промежуточного объекта, например, поля BLOB:
Выполняется передача из XMLPort в BLOB
Выполняется передача из BLOB в XMLPort, BigText или XMLDom
Из BigText в …
Из BigText в BLOB
rItem.GET(’1200′);
rItem.Picture.CREATEOUTSTREAM(oStream);
tBigText.WRITE(OStream);
Из BigText во внешний файл
fFile.CREATE(’C:\111\MyPic1.BMP’);
fFile.CREATEOUTSTREAM(oStream);
tBigText.WRITE(OStream);
Из BigText в XMLPort, BigText, XMLDom
Выполняется с помощью промежуточного объекта, например, поля BLOB:
Выполняется передача из BigText в BLOB
Выполняется передача из BLOB в XMLPort, BigText или XMLDom
Из XMLDom в …
Из XMLDom в BLOB
rSetup.GET;
rSetup.XMLData.CREATEOUTSTREAM(oStream);
OutboundXML.save(oStream);
Из XMLDom в File
fFile.CREATE(’C:\111\imp1.xml’);
fFile.CREATEOUTSTREAM(oStream);
OutboundXML.save(oStream);
Из XMLDom в XMLPort, BigText, XMLDom
Выполняется с помощью промежуточного объекта, например, поля BLOB:
Выполняется передача из BigText в BLOB
Выполняется передача из BLOB в XMLPort, BigText или XMLDom
Все отлично. Но лично меня смущает один момент.
Некоторое время назад я обнаружил функцию по преобразованию InStream в OutStream и думал, что она используется в одной из приведенных выше ситуаций. Но как вы видели это не так.
Однако с какой-то целью данная функция создавалась, чтобы выяснить это у нас есть два пути:
Использовать космическую энергию
Использовать Navision Developer Toolkit
Естественно я начал с космической энергии и перечитал собственную статью, опубликованную в одном из предыдущих выпусков.
Статья Использование Microsoft Message Queue для обмена информацией с Dynamics NAV (Navision)
Если в двух словах, то там рассказывалось как использовать Microsoft Message Queue для обмена данными. Dynamics NAV может выступать как в роли отправителя, так и в роли получателя данных. В обоих случаях используются потоки: InStream и OutStream.
Начнем с отправки данных. Для отправки используется следующий код (подробности см. по ссылке выше).
CREATE(Comcom);
CREATE(MQBus);
MQBus.OpenWriteQueue(’.\private$\MyQueue’,0,0);
Comcom.AddBusAdapter(MQBus,0);
ComOut := Comcom.CreateoutMessage(’Message queue://’);
OutStr := ComOut.GetStream;
OutStr.WRITE(’nav4u.ru’);
ComOut.Send(0);
В данном пример отправляется простая строка. Мы же попробуем передать и получить что-нибудь более сложное чем «nav4.ru».
Практически весь код в функции останется без изменений, мы лишь заменим строку OutStr.WRITE(’nav4u.ru’); на что-нибудь более подходящее
Из BLOB в MSMQ
…
//OutStr.WRITE(’nav4u.ru’);
r27.GET(’70102′);
r27.CALCFIELDS(Picture);
r27.Picture.CREATEINSTREAM(inStr);
COPYSTREAM(OutStr,InStr);
…
Из File в MSMQ…
//OutStr.WRITE(’nav4u.ru’);
fff.OPEN(’C:\111\imp1.xml’);
fff.CREATEINSTREAM(InStr);
COPYSTREAM(OutStr,InStr);
…
Из XMLPort в MSMQ…
//OutStr.WRITE(’nav4u.ru’);
XMLPORT.EXPORT(50000,OutStr);
…
Из BigText в MSMQ
…
//OutStr.WRITE(’nav4u.ru’);
BigTxt.WRITE(OutStr);
…
Из XMLDom в MSMQ…
//OutStr.WRITE(’nav4u.ru’);
Create(xmldom);
xmldom.load(’C:\111\imp1.xml’);
xmldom.save(OutStr);
…
Отлично, отправка прошла успешно, теперь можно перейти к получению данных. Для этого изменим код в событии Comcom::MessageReceived
Comcom::MessageReceived(VAR InMessage : Automation “”.IDISPATCH”)
ComIn := InMessage;
InStr := ComIn.GetStream;
InStr.READTEXT(Line);
Message(’OK’);
Заменим строку InStr.READTEXT(Line); на один из фрагментов приведенных ниже (в зависимости от того, что требуется получить).
Из MSMQ в BLOB
…
//InStr.READTEXT(Line);
r27.GET(’1000′);
r27.Picture.CreateOutStream(OutStr);
COPYSTREAM(OutStr,InStr);
r27.MODIFY;
…
Из MSMQ в File…
//InStr.READTEXT(Line);
fff.CREATE(’C:\111\imp1.xml’);
fff.CREATEOUTSTREAM(OutStr);
COPYSTREAM(OutStr,InStr);
fff.CLOSE;
…
Из MSMQ в XMLPort…
//InStr.READTEXT(Line);
XMLPORT.IMPORT(50001,InStr);
…
Из MSMQ в BigText
…
//InStr.READTEXT(Line);
BigTxt.READ(InStr);
…
Из MSMQ в XMLDom
//InStr.READTEXT(Line);
Create(xmldom);
xmldom.load(InStr);
xmldom.save(’C:\111\imp1.xml’);
| BLOB | File | XMLPort | BigText | XMLDom | |
| В MSMQ из | gS | gS | iS | iS | iS |
| Из MSMQ в | gS | gs | iS | iS | iS |
iS – используются функции комплексного типа данных (automation) для передачи значения другому типу данных с помощью потоков (InStream или OutStream)
gS – системная функция для копирования значения из потока на чтение в поток на запись.
Что касается Developer Toolkit, то с его помощью удалось найти следующие места, где используется функция COPYSTREAM:
- Сodeunit 5301 Outlook Synch. NAV Mgt.; функция GetXMLFromJQEntry
- Codeunit 5301 Outlook Synch. NAV Mgt.; функция PutXMLToJQResponse;
- Codeunit 6817 EP Format Functions; функция GetValueFromBLOB
- Codeunit 7700 ADCS NAS Startup; функция ComComIn::MessageReceived
Благодарности
Выражаю благодарность коллегам Alterant, DA_NEAL и Fordewind, собственно благодаря им эта статья и была написана.
Метки: Андрей Панько
16 Январь 2009 в 12:52
Про проблемы с функцией copystream (из MSMQ в File)
The COPYSTREAM “problem” for Sockets
http://blogs.msdn.com/microsoft_dynamics_nav_sustained_engineering/archive/2009/01/15/the-copystream-problem-for-sockets.aspx