Р?спользование потоков 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

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