Чтение сгенерированного файла Cobol

В настоящее время я занимаюсь написанием приложения на С#, которое будет располагаться между двумя существующими приложениями. Все, что я знаю о втором приложении, это то, что оно обрабатывает файлы, созданные первым. Первое приложение написано на Коболе.

Шаги: 1) Приложение Cobol записывает несколько файлов и копирует их в каталог. 2) Второе приложение подхватывает эти файлы и обрабатывает их.

Мое приложение С# будет находиться между 1) и 2). Он должен будет взять файл, сгенерированный 1), прочитать его, изменить и сохранить, чтобы приложение 2) не узнало, что я там был.

У меня несколько проблем.

  • Прежде всего, если я открою файл, созданный 1) в блокноте, большая часть его будет нечитаема, в то время как другие части будут.
  • Если я прочитаю файл, изменю его и сохраню, я должен сохранить файл с той же нотацией, которая используется приложением cobol, чтобы приложение 2) не знало, что я был там.

Я пытался прочитать файл таким образом, но он все еще не читается:

Код:

        string ss = @"filename";

        using (FileStream fs = new FileStream(ss, FileMode.Open))
        {
            StreamReader sr = new StreamReader(fs);
            string gg = sr.ReadToEnd();
        }

Кроме того, если я найду способ сделать его читаемым (используя какую-то технику кодирования), я боюсь, что при повторном сохранении файла я могу изменить его исходный формат.

Есть предположения? Предложения?


person Rauland    schedule 02.02.2011    source источник
comment
Вам нужно узнать производителя COBOL, а затем выяснить формат файла. Единого формата COBOL не существует.   -  person John Saunders    schedule 02.02.2011
comment
Было бы интересно узнать, какой формат должен быть предполагается, это CSV? Можете ли вы поговорить с парнем, который создает файл, чтобы спросить его, что файл должен содержать?   -  person Felice Pollano    schedule 02.02.2011
comment
В зависимости от платформы это также может быть EBCDIC.   -  person Dr. belisarius    schedule 02.02.2011
comment
Привет, спасибо за ответы. Я узнаю версию Cobol и тип файла (файлы создаются без расширения). Я знаю, что платформа Windows, и я думаю, что это не файл CSV (файл, разделенный запятыми).   -  person Rauland    schedule 02.02.2011
comment
Можете ли вы загрузить образец файла куда-нибудь и дать ссылку на него.   -  person Tim Lloyd    schedule 02.02.2011
comment
@rauland: не только версия COBOL, но и поставщик. Microfocus — один поставщик, но я считаю, что их больше одного (Fujitsu?)   -  person John Saunders    schedule 02.02.2011
comment
@chibacity Файлы содержат данные клиента,..   -  person Rauland    schedule 02.02.2011
comment
@rauland Надеюсь, пароли и данные кредитной карты. :)   -  person Tim Lloyd    schedule 02.02.2011
comment
@ Джон Сондерс, я также узнаю продавца.   -  person Rauland    schedule 02.02.2011
comment
@Всем спасибо за интерес и помощь. Это начинает казаться очень сложной задачей. Это мой первый пост в stackoverflow, и я ошеломлен ответами, которые я получил до сих пор, несколько далеко за пределами моей лиги (например, ответ Николаса Кэриса! Дорогой, какой ответ .. давайте посмотрим, все ли я понял).   -  person Rauland    schedule 02.02.2011
comment
@rauland Вы обнаружите, что если будете публиковать хорошие вопросы, вы, как правило, получите хорошие ответы на SO. Попробуйте решить проблему и постарайтесь разбить свои проблемы на маленькие кусочки — не пытайтесь съесть всю корову сразу. Придерживайтесь этого и удачи. :)   -  person Tim Lloyd    schedule 02.02.2011
comment
Я не уверен, может ли это помочь. Но у меня есть знания о системе, которая генерирует файлы: 1) Оператор начинает с создания пакетного файла. К файлу добавляется заголовок, в котором подробно описывается несколько вещей, таких как тип партии, дата и формат записи. 2)Оператор продолжает работу над пакетом и записи добавляются в файл. (Я понимаю, что каждая запись представляет собой не более чем одну строку текста.) 3) Затем оператор решает завершить пакет, который добавляет нижний колонтитул в конец файла с некоторыми деталями, такими как количество записей, добавленных в пакет.   -  person Rauland    schedule 02.02.2011
comment
..Если это процесс, можем ли мы сказать, какой это тип файла?   -  person Rauland    schedule 02.02.2011
comment
Теперь идея состоит в том, что мое приложение С# будет отвечать за выполнение шага 3), добавить нижний колонтитул, закрыть пакет и передать файл в следующую систему. Я думал, что это будет так же просто, как открыть несколько закрытых командных файлов, чтобы увидеть содержимое нижнего колонтитула и информацию, которая в нем содержится. Затем из С# сгенерируйте эту информацию и добавьте ее в файл. Кажется, это далеко не так прямолинейно, как я думал.   -  person Rauland    schedule 02.02.2011
comment
@chibacity Я договорился о том, чтобы получить несколько образцов файлов, которые я могу загрузить. Я займусь последним этим вечером из дома, так как я за прокси-сервером и не могу получить доступ к своему скайдрайву... было бы здорово, если бы кто-нибудь мог взглянуть на них, если это нормально? Я изучил все отличные комментарии, которые я получил до сих пор, большинство из них я нахожу очень сложными, но делаю все возможное, чтобы справиться с ними. Любые советы о том, как ускориться (с основами !?)? Я пытался пометить все ответы как полезные, но это не разрешено, так как я новичок в stackoverflow. :) Ваше здоровье!   -  person Rauland    schedule 03.02.2011
comment
Пожалуйста, не публикуйте ничего, если вы и ваш работодатель не хотите, чтобы это было общедоступным для всех / любого. Не публикуйте ничего, что могло бы идентифицировать человека, номер кредитной карты, банковский счет, номер социального страхования или любую другую идентифицирующую информацию. Оно будет преследовать вас!   -  person NealB    schedule 03.02.2011
comment
Привет спасибо за совет. Оба файла имеют фиктивные данные, и я также попросил разрешения на публикацию файлов, поэтому я не вижу никакого вреда в их публикации, и все будет хорошо, если кто-нибудь сможет помочь и определить, к каким типам файлов они относятся. Файлы имеют заголовок с именем: CDL, записи в этом случае типа этикетки и отсутствие раздела трейлера. (это то, что я должен выполнить из С#.) В данный момент мне нужен способ подсчета количества записей в файле, поэтому я должен определить какой-то разделитель в файле. Большое спасибо!   -  person Rauland    schedule 03.02.2011
comment
Вот Файл 1. и здесь: Файл 2   -  person Rauland    schedule 03.02.2011
comment
Можете ли вы изменить программу Cobol, чтобы она создавала данные, которые просто отображают данные? И никаких подразумеваемых десятичных точек в данных. Кроме того, формат записи может быть подсказкой. У вас может быть более 1 типа записей, записываемых в файл. Это плохая практика.   -  person Cathy Sullivan    schedule 05.02.2011
comment
Я посмотрел предоставленные вами файлы. Я даже посмотрел на это в двоичном виде (вариант в TextPad). Вам нужен макет файла из исходной программы, независимо от того, какой язык вы использовали. У вас нет никого, кто мог бы модифицировать программу на Коболе? Это был бы лучший способ сделать это.   -  person Cathy Sullivan    schedule 05.02.2011
comment
@Cathy Sullivan Привет, Кэти, большое спасибо за ваше время. Я не уверен, что таким длинным ответом нарушаю какое-то правило stackoverflow, поэтому, пожалуйста, дайте мне знать, если это так. Также мне пришлось разнести его по многим комментариям, так как в один он не влез. Существует существующая программа COBOL, которая добавляет трейлер или закрытие файла, но в настоящее время находится на машине UNIX. Я полагаю, что они хотят заменить эту программу COBOL, работающую в UNIX, приложением winforms, работающим на Windows Server. Я объясню, что я сделал до сих пор. Ничего не понимая, я начал проверять файлы с помощью HEX-редактора.   -  person Rauland    schedule 06.02.2011
comment
(Просто напомню, что структура файла начинается с заголовка, затем записей данных и концевика.) Изучив файл в редакторе, я пришел к выводу, что каждый файл COBOL структурирован таким образом, что для каждой записи существует определение структуры или типа. а затем фактические данные. Кажется, это происходит для каждой записи в файле. Итак, возвращаясь к C#, если мне нужно подсчитать эти записи данных, мне потребуется: - Открыть файл. - Определите, где заголовок начинается и заканчивается.   -  person Rauland    schedule 06.02.2011
comment
- Там, где заканчивается заголовок, начинаются записи данных, поэтому отсюда и далее обнаруживайте разделитель. - Узнайте, сколько существует разделителей, и подсчитайте записи данных. - Напишите трейлер. Кстати, я еще не видел файла с трейлером! (Я знаю, что это безумие). Все, что мне сказали о трейлере, это то, что мне нужно написать количество записей.   -  person Rauland    schedule 06.02.2011
comment
Итак, в своем уме и будучи действительно уверенным, я начинаю выполнять небольшую миссию: - Из C # я загрузил бы HEX-представление файла в виде строки. - Определение структуры заголовка кажется одинаковым для каждого файла. Таким образом, я мог бы найти это определение структуры и определить, где заголовок начинается и заканчивается. - Там, где это заканчивается, начинаются записи данных. Каждая запись данных должна начинаться с определения структуры, я мог каким-то образом извлечь это определение, и это может быть мой разделитель записей.   -  person Rauland    schedule 06.02.2011
comment
- Я бы посмотрел, сколько раз повторяется этот разделитель, и посчитал записи. - Если закрытие или трейлер достаточно просты, я мог бы прямо в HEX подсчитать и добавить в файл. Затем я начинаю спускаться на землю, верю и понимаю, что это может быть слишком сложным и ненадежным способом сделать это.   -  person Rauland    schedule 06.02.2011
comment
Менеджер моей проектной группы никогда не осознавал, что это будет такой проблемой, он думал, что эти файлы COBOL будут похожи на обычные текстовые файлы. Итак, вот мой вопрос: может ли COBOL создавать вместо этих сложных для обработки файлов обычные файлы .txt? В любом случае, я все еще пытаюсь объяснить ему, что обработка этих файлов из C# совсем не проста. И, вероятно, мне может потребоваться много времени, чтобы понять, как их обрабатывать, если я когда-нибудь это сделаю.   -  person Rauland    schedule 06.02.2011
comment
@rauland, что должно быть в записи трейлера? Просто подсчет количества подробных записей? Вы знаете, какой формат должен быть? В конце каждой записи, написанной программой Cobol, должен быть CRLF. Вы знаете, какой длины должна быть каждая запись? Наверное, все они одного размера.   -  person Cathy Sullivan    schedule 06.02.2011
comment
@ Кэти Салливан, я не получаю особой помощи. Все, что мне сказали о трейлере, это то, что мне нужно посчитать записи и добавить это количество в трейлер. Также я узнал, что программа COBOL, которая в настоящее время добавляет трейлеры, заставляет вас выбирать определенную длину. У вас есть следующие варианты: 80, 160, 240 и 360. Насколько я понимаю, если вы выберете, например, 80, все записи будут обрезаны до этой длины. Формат варьируется в зависимости от типа партии. Каждый тип пакета будет иметь свой формат.   -  person Rauland    schedule 06.02.2011
comment
@Everybody Поскольку я не получаю особой помощи (с моей стороны :)), я начал рассматривать возможность создания более простых версий этих файлов COBOL, а затем попытки доступа к ним из C #. Таким образом, я могу начать знакомиться с этими файлами. Мне удалось установить «Microsoft COBOL Compiler Version 2.20 Microsoft Corp. 1982-87». Я начал с нескольких приветственных миров, но теперь хочу создать похожие файлы COBOL. Я посмотрел и не могу найти никаких руководств или руководств, которые могли бы мне помочь.   -  person Rauland    schedule 06.02.2011
comment
Это сложно, потому что я действительно не знаю, какие типы файлов мне нужны. (Я уже спросил производителя, тип файла и версию COBOL). Как только я получу более простые версии этих файлов, я смогу начать обращаться к ним из C# и работать напрямую с HEX-представлением. Я знаю, что, вероятно, основным приложением является другой поставщик COBOL, вероятно, IBM, но компилятор IBM COBOL не является бесплатным.   -  person Rauland    schedule 06.02.2011
comment
См. дополнительную информацию [здесь][1] [1]: stackoverflow.com/questions/5109302/   -  person GilShalit    schedule 17.07.2011


Ответы (3)


Чтобы прочитать файл, созданный на языке COBOL, вам необходимо знать:

Во-первых, вам понадобится макет записи (тетрадь) для файла. Макет записи COBOL будет выглядеть примерно так:

01  PATIENT-TREATMENTS.
    05  PATIENT-NAME                PIC X(30).
    05  PATIENT-SS-NUMBER           PIC 9(9).
    05  NUMBER-OF-TREATMENTS        PIC 99 COMP-3.
    05  TREATMENT-HISTORY OCCURS 0 TO 50 TIMES
           DEPENDING ON NUMBER-OF-TREATMENTS
           INDEXED BY TREATMENT-POINTER.
        10  TREATMENT-DATE.
            15  TREATMENT-DAY        PIC 99.
            15  TREATMENT-MONTH      PIC 99.
            15  TREATMENT-YEAR       PIC 9(4).
        10  TREATING-PHYSICIAN       PIC X(30).
        10  TREATMENT-CODE           PIC 99.

Вам также понадобится копия Principles of Operation IBM (S/360, S370, z/OS, для наших целей это не имеет особого значения). Последняя версия доступна в IBM по адресу

Главы 8 (Десятичные инструкции) и 9 (Обзор операций с плавающей запятой и инструкции по поддержке) представляют интерес для наших целей.

Без этого вы в значительной степени потеряны.

Затем вам нужно понять типы данных COBOL. Например:

  • PIC определяет поле в буквенно-цифровом формате (PIC 9(4), например, состоит из 4 десятичных цифр, которые могут быть заполнены пробелами, если они отсутствуют). Pic 999V99 состоит из 5 десятичных цифр с подразумеваемой десятичной точкой. Так далее и тому подобное.
  • BINARY — это [обычно] двоичное целое число с фиксированной точкой со знаком. Обычные размеры составляют половину слова (2 октета) и полное слово (4 октета).
  • COMP-1 — это число с плавающей запятой одинарной точности.
  • COMP-2 — это число с плавающей запятой двойной точности.

Если источником данных является мэйнфрейм IBM, COMP-1 и COMP-2, скорее всего, не будут использовать IEE с плавающей запятой: это будет формат base-16 избыток 64 с плавающей запятой. Вам понадобится что-то вроде Принципов работы S/370, чтобы понять это.

  • COMP-3 представляет собой «упакованное десятичное число» разной длины. Упакованное десятичное число — это компактный способ представления десятичного числа. Объявление будет выглядеть примерно так: PIC S9999V99 COMP-3. Это говорит о том, что оно подписано, состоит из 6 десятичных цифр с подразумеваемой десятичной точкой. Packed decimal представляет каждую десятичную цифру как полубайт октета (шестнадцатеричные значения 0–9). Старшая цифра — это старший полубайт самого левого октета. Младший полубайт самого правого октета представляет собой шестнадцатеричное значение A-F, представляющее знак. Таким образом, приведенное выше предложение PIC потребует ceil( (6+1)/2 ) или 4 октетов. значение -345,67, представленное приведенным выше предложением PIC, будет выглядеть как 0x0034567D. Фактическое значение знака может варьироваться (по умолчанию C/положительное, D/отрицательное, но A, C, E и F считаются положительными, а только B и D считаются отрицательными). Подробнее о представлении см. в разделе Принципы работы S\370.

Относящийся к КОМП-3 является районированным десятичным числом. Это может быть объявлено как `PIC S9999V99' (со знаком, 5 десятичных цифр, с подразумеваемой десятичной точкой). Десятичные цифры в EBCDIC представляют собой шестнадцатеричные значения 0xFO - 0xF9. «Распаковать» (машинная инструкция мэйнфрейма) принимает упакованное десятичное поле и преобразует его в символьное поле. Процесс:

  • начать с самого правого октета. Инвертируйте его так, чтобы фрагмент знака был сверху, и поместите его в крайний правый октет поля назначения.
  • Работая справа налево (и источник, и цель), удалите каждый оставшийся полубайт упакованного десятичного поля и поместите его в младший полубайт следующего доступного октета в месте назначения. Заполните высокий кусок шестигранником F.

  • Операция завершается, когда исчерпаны поля источника или назначения.

  • Если поле назначения не исчерпано, если оно дополняется нулями слева, заполняя оставшиеся октеты десятичным '0' (oxF0).

Таким образом, значение нашего примера -345,67, если оно сохранено со значением знака по умолчанию (шестнадцатеричный D), будет распаковано как 0xF0F0F0F3F4F5F6D7 ("0003456P" в EBDIC).

[Ну вот. Позже будет викторина]

  1. Если приложение COBOL работает на мейнфрейме IBM, был ли файл преобразован из исходного EBCDIC в ASCII? Если нет, вам придется выполнить сопоставление самостоятельно (подсказка: это не обязательно так просто, как может показаться, поскольку это может быть выборочный процесс — преобразуются только символьные поля (COMP-1, COMP-2, COMP -3 и BINARY исключаются, так как они представляют собой последовательность двоичных октетов.) Хуже того, существует множество вариантов представления EBCDIC из-за различных национальных реализаций и различных цепочек печати, используемых на разных принтерах.

О... последнее. Аппаратное обеспечение мэйнфрейма, как правило, предпочитает, чтобы разные вещи были выровнены по границам полуслов, слов или двойных слов, поэтому макет записи может не отображаться непосредственно на октеты в файле, поскольку между полями могут быть вставлены заполняющие октеты для поддержания необходимого выравнивания слов.

Удачи.

person Nicholas Carey    schedule 02.02.2011
comment
Я вернусь завтра и проголосую - на сегодня закончились. Отличный ответ. Выглядит довольно сложной задачей! :) - person Tim Lloyd; 02.02.2011
comment
В целом все не так плохо, как кажется. Большинство приложений COBOL записывают записи в прямом символьном формате. Вы редко видите числа с плавающей запятой в дикой природе, но вы можете увидеть упакованные десятичные числа или двоичные числа с фиксированной точкой. Двоичный файл с фиксированной точкой представляет собой прямое отображение 1:1 на short или int (за исключением проблем с обратным порядком байтов/обратным порядком байтов). С упакованным десятичным числом немного хлопотно, но не так уж плохо написать процедуру преобразования для преобразования в decimal. - person Nicholas Carey; 02.02.2011
comment
не моя тетрадь B^). Я был вне мира мэйнфреймов в течение очень долгого времени, хотя недавно мне пришлось пройти через процесс создания процесса для периодического импорта дампа файла COBOL, содержащего смесь текстового, двоичного и упакованного десятичного числа. данные и перенести их в мир .Net/SQL Server. Преобразование из EBCDIC [в основном] довольно просто, поскольку .Net TextInfo поддерживает несколько кодовых страниц EBCDIC (037 и 500, для начала). Пришлось написать процедуру преобразования упакованного десятичного числа в decimal и преобразовать фиксированную точку с прямого порядка байтов в прямой. Легкий! - person Nicholas Carey; 03.02.2011
comment
Если вы не укажете SYNCHRONIZED, мейнфрейм ничего не сделает для выравнивания. - person Bill Woodger; 26.01.2013

Из комментариев, прикрепленных к вашему вопросу, я вижу, что вы имеете дело с «классической» структурой пакетного файла COBOL: запись заголовка, подробные записи и запись трейлера.

Это, вероятно, плохие новости, если вы несете ответственность за создание записи трейлера! Типичная «завершающая» запись используется для определения конца файла и предоставляет управляющую информацию, такую ​​как количество записей, предшествующих ей, а также различные контрольные суммы и/или общие итоги для «подробных» записей. Другими словами, вам может понадобиться прочитать и обобщить весь файл, чтобы создать трейлер. Добавьте к этому возможность того, что большая часть данных в файле находится в формате Packed Decimal, Zoned Decimal или других числовых типах данных COBOLish, и вы можете столкнуться с трудностями.

Вы можете задаться вопросом, почему вы добавляете записи трейлеров в эти файлы. Обычно «трейлер» создается той же программой или приложением, которое создало записи «деталей». Предполагается, что трейлер служит подтверждением того, что отправляющее приложение/программа записало все данные, которые оно должно было записать. Сводные итоги, подсчеты и т. д. используются принимающим приложением для проверки того, что подробные записи совпадают с предыдущими подробностями. Предполагается, что это служит еще одной проверкой того, что отправляющее приложение не испортило данные или что они не были повреждены в пути (нет, это не было шуткой — но, возможно, так и должно быть). Когда «человек посередине» создает трейлеры, это как бы сводит на нет всю цель упражнения (независимо от того, насколько ошибочным оно могло быть с самого начала).

person Community    schedule 03.02.2011
comment
+1, чтобы напомнить мне, как все стало плохо, когда поля Total в трейлере переполнились :) - person Dr. belisarius; 03.02.2011

  • Было бы полезно знать, с каким диалектом кобола вы имеете дело, потому что единого формата кобола не существует. Некоторые компиляторы Cobol (Micro Focus) помещают «Описание файла» в начале файлов (для файлов Micro Focus VB/индексированных).

  • Взгляните на RecordEditor (http://record-editor.sourceforge.net/). В нем есть Мастер создания файлов, который может быть вам очень полезен.

    • In the File Wizard set the file as Fixed-Width File (most common in Cobol). The program lets you try out different Record Lengths. When you get the correct record length, the Text fields should line up.
    • Позже в Мастере есть поиск по полям, который может искать Binary, Comp-3, Text Fields.
    • Здесь есть некоторые примечания по использованию мастера RecordEditor с неизвестным файлом http://record-editor.sourceforge.net/Unkown.htm
  • Если файл не исходит от мэйнфрейма / AS400, он вряд ли будет использовать EBCDIC (cp037 - Кодированная страница 37 - это US EBCDIC), любой текст, скорее всего, будет в Ascii.

  • Файл, вероятно, содержит данные в формате Packed-Decimal (Comp3) и Binary-Integer. Большинство коболов используют Big-Endian (для целых чисел Comp) даже на Intel (оборудование с прямым порядком байтов).

  • Следует помнить одну вещь: Cobol PIC s9(6)V99 comp хранится в виде двоичного целого числа, где x'0001' соответствует 0,01. Поэтому, если у вас нет определения Cobol, вы не можете сказать, является ли двоичная 1 1 0,1, 0,01 и т. д.

person Bruce Martin    schedule 03.02.2011