Отменить произвольные строки заголовка при обработке BizTalk Flat File?
Я нашел эти связанные темы, но они не отвечают на мой вопрос напрямую:
BizTalk - плоский файл с несколькими записями заголовка и нижнего колонтитула - проблема с разборкой
Удаление заголовка из плоского файла в BizTalk
Я имею дело со старой системой, которая доставляет плоские файлы с очень свободной схемой. В частности, заголовок состоит из двух строк: первая строка является заголовком, а вторая строка - заголовками столбцов. Все последующие строки являются действительными записями.
Проблема заключается в том, что когда нет записей за этот день, заголовки столбцов опускаются; в этом случае у нас есть заголовок документа, а затем итоговая строка (для потребления человеком), которая уведомляет читателя об отсутствии записей за этот день.
Поскольку один и тот же файл может иметь такие разные форматы, мне трудно создать схему заголовка, которую я могу использовать в моем конвейере приема плоских файлов, который позволит мне удалить информацию заголовка. Кроме того, поскольку заголовок состоит из нескольких строк, кажется, что я не могу просто использовать разделитель возврата каретки.
Я попробовал два подхода к этому:
- Схема заголовка, которая содержит два элемента поля с разделителем-кареткой, каждый из которых является непрозрачной строкой
- Схема заголовка, содержащая две записи с разделителем-кареткой, каждая из которых определяет фиктивный разделитель инфиксов, который никогда не будет существовать ни в одной строке (в результате по одной непрозрачной строке на запись)
Однако, когда я их развертываю, BizTalk подберет файлы и обработает их, однако на самом деле это не приводит к каким-либо сообщениям. Это заставляет меня поверить, что BizTalk обрабатывает мои плоские файлы так, как будто весь файл является заголовком, так что он не находит записей.
Решение, которое я пытаюсь найти, состоит в том, как создать схему заголовка, которая заставляет BizTalk обрабатывать первые две строки файла как заголовок, независимо от их содержимого, и отбрасывать их. Это возможно?
РЕДАКТИРОВАТЬ: Примеры разных файлов:
Записи существуют:
2017-02-27 19:27:03
CustomerName, OrderNumber, Expedite, ItemNumber, Count
CustomerA, O196801, 0, I232, 2
CustomerA, O196801, 0, I255, 1
CustomerB, O196802, 0, I237, 1
CustomerC, O196803, 0, I214, 1
CustomerC, O196803, 0, I232, 2
В этом файле нет записей:
2017-02-27 19:30:22
***EOF***
- Первая строка всегда одинакова и может быть описана позиционно-разделенной записью.
- Вторая строка - это либо список имен столбцов, разделенных запятыми, либо эта строка EOF.
- EOF появляется только тогда, когда нет записей.
В настоящее время я могу обрабатывать файлы с записями только путем определения разделителя между схемами заголовка и документа как всей строки заголовка столбца, т.е. CustomerName, OrderNumber, Expedite, ItemNumber, Count{CR}{LF}
Тем не менее, эта схема заголовка не удается для пустого файла, когда он находит ***EOF***
вместо строки заголовка столбца.
1 ответ
Может быть какой-то умный способ справиться с этим с помощью схемы плоских файлов, но я не могу об этом думать.
Я бы наверное посмотрел написать кастом Decode
компонент для конвейера, который будет проверять первые несколько байтов сообщения для этого ***EOF***
- если это так, просто обнулите поток (или, возможно, перепишите его с ожидаемыми заголовками) - если нет, сбросьте позицию потока обратно в 0 и передайте его.
например (примечание: непроверенный, возможно, работает код):
public IBaseMessage Execute(IPipelineContext pContext, IBaseMessage pInMsg)
{
if (pInMsg == null || pInMsg.BodyPart == null) return pInMsg;
var stream = pInMsg.BodyPart.GetOriginalDataStream();
if (stream == null || stream.Length == 0) return pInMsg;
if (!stream.CanSeek)
{
stream = new ReadOnlySeekableStream(stream);
pContext.ResourceTracker.AddResource(stream);
}
StreamReader reader = new StreamReader(stream);
pContext.ResourceTracker.AddResource(reader);
reader.ReadLine(); // date line
if (reader.ReadLine() == "***EOF***")
{
pInMsg.BodyPart.Data = null;
}
else
{
stream.Position = 0;
pInMsg.BodyPart.Data = stream;
}
return pInMsg;
}