Конвертировать данные COBOL в SQL Сервер - PullRequest
1 голос
/ 25 апреля 2020

Мы получили данные из COBOL, как показано ниже, и получили возможность конвертировать в SQL Сервер. Я перешел по этой ссылке

и создал пакет служб SSIS. Однако я сталкиваюсь с проблемой при преобразовании некоторых данных из COBOL в SQL.

. Я пометил входные столбцы как байты, а выходные данные как данные Numeri c как 10 и точность 2

1. . Попытался создать столбцы в виде десятичного числа (10,2) в SQL
2. Попытался с SQL типом данных даты для даты COBOL

пакет работает успешно, но данные не заполняются. макет данных

CONTRACT-SIZE         pic S9(9)V99 COMP-3         
DIV-REC-DATE-LOBO     PIC  9(0007) COMP-3  
PAR-DATE              PIC S9(0007) COMP-3  
BID-PRICE             PIC S9(0005)V9(2)  COMP-3

Опробованная ниже функция для распаковки, Translate, COBOLZonedPicToDecimal

Public Function Translate(ByVal str As String, sConversionTable As String) As String

    Dim Temp As String, I As Int32
    Temp = Space(Len(str))
    For I = 1 To Len(str)
        Mid(Temp, I, 1) = Mid(sConversionTable, Asc(Mid(str, I, 1)) + 1, 1)
    Next
    Translate = Temp
End Function

Private Function Unpack(ByVal bPacked As Byte(), ByVal iDecimalPlaces As Integer) As Decimal
    Dim i As Integer
    Dim HiNibble As Byte
    Dim LoNibble As Byte
    Dim dResult As Decimal = 0


    For i = 0 To bPacked.Length - 2
        UnpackNibblesToBytes(bPacked(i), LoNibble, HiNibble)
        dResult = Convert.ToDecimal(dResult * 10 ^ 2I + HiNibble * 10 + LoNibble)

    Next
    UnpackNibblesToBytes(bPacked(bPacked.Length - 1), LoNibble, HiNibble)

    dResult = dResult * 10 + HiNibble

    If LoNibble = &HD& Then
        dResult = -dResult
    End If

    Unpack = Convert.ToDecimal(dResult * 10 ^ (-iDecimalPlaces))

End Function

Private Sub UnpackNibblesToBytes(ByVal InputNibbles As Byte, ByRef LoNibble As Byte, ByRef HiNibble As Byte)

    LoNibble = (Me.F And InputNibbles)
    HiNibble = ((Me.F0 And InputNibbles) >> 4)

End Sub

Public Function DecimalToCOBOLZonedPic(ByVal dNumber As Decimal, ByVal iPadLength As Integer, ByVal iDecimalPlaces As Integer, ByVal bModifiedZoned As Boolean) As String
    Dim isNegative As Boolean = False
    Dim strNumber As String
    Dim sPositive As String = "{ABCDEFGHI"
    Dim sNegativeMod As String = "}JKLMNOPQR"
    Dim sNegativeStrict As String = "pqrstuvwxy"

    ' Determine the sign
    If dNumber < 0 Then
        isNegative = True
        dNumber = -dNumber
    End If

    dNumber = Convert.ToDecimal(dNumber * (10 ^ iDecimalPlaces))

    strNumber = dNumber.ToString

    If strNumber.IndexOf(".") > -1 Then
        ' Truncate remaining decimal places
        strNumber = strNumber.Substring(0, strNumber.IndexOf("."))
    End If

    ' Pad with leading zeros
    If strNumber.Length < iPadLength Then
        strNumber = strNumber.PadLeft(iPadLength, "0"c)
    End If

    Dim lastDigit As Integer = Convert.ToInt32(strNumber.Substring(strNumber.Length - 1, 1))

    If bModifiedZoned Then
        If isNegative Then
            strNumber = strNumber.Substring(0, strNumber.Length - 1) & sNegativeMod.Substring(lastDigit, 1).ToString
        Else
            strNumber = strNumber.Substring(0, strNumber.Length - 1) & sPositive.Substring(lastDigit, 1).ToString
        End If
    Else
        If isNegative Then
            strNumber = strNumber.Substring(0, strNumber.Length - 1) & sNegativeStrict.Substring(lastDigit, 1).ToString
        End If
    End If

    Return strNumber
End Function

Public Function COBOLZonedPicToDecimal(ByVal strNumber As String, ByVal decimalPlaces As Integer) As Decimal
    Dim sZoneChar As String
    Dim convertedNumber As Decimal
    Dim sPositive As String = "{ABCDEFGHI"
    Dim sNegativeMod As String = "}JKLMNOPQR"
    Dim sNegativeStrict As String = "pqrstuvwxy"

    strNumber = strNumber.Trim

    If strNumber = "" Then
        Return 0
    End If

    sZoneChar = strNumber.Substring(strNumber.Length - 1)

    Select Case True
        Case sPositive.IndexOf(sZoneChar) > -1
            strNumber = strNumber.Substring(0, strNumber.Length - 1) & sPositive.IndexOf(sZoneChar)
            convertedNumber = Convert.ToDecimal(strNumber)

        Case sNegativeMod.IndexOf(sZoneChar) > -1
            strNumber = strNumber.Substring(0, strNumber.Length - 1) & sNegativeMod.IndexOf(sZoneChar)
            convertedNumber = -Convert.ToDecimal(strNumber)

        Case sNegativeStrict.IndexOf(sZoneChar) > -1
            strNumber = strNumber.Substring(0, strNumber.Length - 1) & sNegativeStrict.IndexOf(sZoneChar)
            convertedNumber = -Convert.ToDecimal(strNumber)
        Case Else
            convertedNumber = Convert.ToDecimal(strNumber)
    End Select

    Return Convert.ToDecimal(convertedNumber / (10 ^ decimalPlaces))
End Function

1 Ответ

2 голосов
/ 27 апреля 2020

Текущий файл

0x0200EAA4, преобразованный в EBCDI C - это x0200529F, которое является допустимым значением comp-3 (2020-May-29).

Выполнение преобразования ascii для двоичного EBCDI C файл (как этот файл) повредит Файл Не не пытайтесь обработать текущий файл.

Решения

  • Преобразование файла в текст при исходном вычислении (мэйнфрейм ??) и передача / перевод файла

  • При обработке файла мэйнфрейм Cobol посмотрите в cb2 xml. Он преобразует Cobol Copybook в файл Xml (и вычисляет позицию / длину). Xml может обрабатываться на многих языках.

  • Конвертировать в фиксированную длину при исходных вычислениях (вероятно, это уже фиксированная длина) и передавать как EBCDI C файл. В файле не будет никаких символов перевода строки. Вам нужно будет обработать его как файл EBCDI C.

Если вы можете

  • выполнить java
  • Получить Тетрадь Cobol
  • В тетради Cobol нет переопределений

Что-то вроде CobolToCsv может конвертировать файл из Cobol-Ebcdi c в файл Ascii-Csv


EBCDI C

Существует несколько наборов символов EBCDI C Cp037 / IBM037 - US EBCDIC; CP273 / IBM273 - немецкий EBCDI C, вам необходимо выяснить, какой диалект EBCDI C используется

Примечание: CP037 означает кодированный Page 037

Фиксированная ширина мэйнфрейма

При фиксированной ширине мэйнфрейма все записи имеют одинаковую длину 1061 * и отсутствуют символы возврата каретки / перевода строки. Для файла с 26-байтовыми записями это

<-- 26 bytes --><-- 26 bytes --> ... <-- 26 bytes -->

cb2 xml

cb2 xml преобразует Cobol Copybook в xml. Это позволяет в общем c обрабатывать данные Cobol на большинстве современных языков

cb2 xml преобразует

 01 Location-Record.
     03 Record-Type            pic xx.
     03 location occurs 10.
        05 DC-Number           pic 9(4).
        05 Pack-Quantity       pic 9(8).         

в

<item display-length="122" level="01" name="Location-Record" position="1" storage-length="122">
    <item display-length="2" level="03" name="Record-Type" picture="xx" position="1" storage-length="2"/>
    <item display-length="12" level="03" name="location" occurs="10" position="3" storage-length="12">
        <item display-length="4" level="05" name="DC-Number" numeric="true" picture="9(4)" position="3" storage-length="4"/>
        <item display-length="8" level="05" name="Pack-Quantity" numeric="true" picture="9(8)" position="7" storage-length="8"/>
    </item>
</item>
...