Использование потоков 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, собственно благодаря им эта статья и была написана.

Метки:



Комментариев: 1

  1. apanko пишет:

    Про проблемы с функцией 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

Оставьте свой отзыв!