Frage

Ich habe eine Reihe von ASCII-Textdateien in einer Mainframe kommen durch eine C # .NET-Anwendung verarbeitet werden. Ein neues Futter wird mit einem gepackte Dezimalzahl (COMP-3) Feld eingeführt, die auf einen numerischen Wert umgewandelt werden muss.

Die Dateien werden per FTP übertragen, ASCII-Übertragungsmodus. Ich bin besorgt darüber, dass das binäre Feld enthalten kann, was als sehr niedrig Codes ASCII interpretiert werden oder Steuerzeichen anstelle einem Wert -. Oder noch schlimmer, in dem FTP-Prozess verloren gehen kann,

Was mehr ist, die Felder werden als Strings lesen. Ich kann die Flexibilität haben, um dieses Teil zu arbeiten (das heißt ein Strom von irgendeiner Art), aber das Geschäft wird mir Push-Back.

Die Anforderung lesen „von HEX nach ASCII Konvertieren“, aber deutlich, dass nicht die richtigen Werte brachte. Jede mögliche Hilfe würde geschätzt; es braucht nicht sprachspezifisch zu sein, solange Sie die Logik des Umwandlungsprozesses erklären können.

War es hilfreich?

Lösung

Zunächst einmal müssen Sie die Zeilenende (EOL) Übersetzungsprobleme beseitigen, die durch ASCII-Übertragungsmodus verursacht wird. Sie haben völlig Recht über Datenkorruption betroffen zu sein, wenn die BCD-Werte zu EOL Zeichen entsprechen passieren. Der schlimmste Aspekt dieses Problems ist, dass es selten und unerwartet auftreten.

Die beste Lösung ist es, den Übertragungsmodus auf IST zu ändern. Dies ist angemessen, da die Daten, die Sie übertragen binär ist. Wenn es nicht möglich ist, den richtigen FTP-Transfer-Modus zu verwenden, können Sie den ASCII-Modus Schaden in Code rückgängig machen. Alles, was Sie tun müssen, ist \ r \ n Paare zurück zu \ n konvertieren. Wenn ich Sie wäre, würde ich sicherstellen, dass dies ist gut getestet.

Wenn Sie mit dem EOL Problem beschäftigt haben, ist die COMP-3 Umwandlung ziemlich straigtforward. Ich konnte in BASIC mit Beispielcode diesen Artikel in der MS Knowledgebase finden. Siehe unten für ein VB.NET-Port diesen Codes.

Da Sie mit COMP-3 Werten zu tun haben, das Dateiformat Sie fast sicher gerade liest hat mit festen Feldlängen Rekordgrößen festgelegt. Wenn ich Sie wäre, würde ich meine Hände eines Dateiformatspezifikation erhalten, bevor Sie weiter gehen mit diesem. Sie sollten eine Binary verwenden mit diesen Daten zu arbeiten. Wenn jemand zurück zu diesem Punkt drückt, würde ich zu Fuß entfernt. Lassen Sie sie jemand anderes finden, um ihre Torheit zu frönen.

Hier ist ein VB.NET-Port des Basic-Beispielcode. Ich habe nicht getestet, weil ich keinen Zugriff auf einen COMP-3-Datei haben. Wenn dies nicht funktioniert, würde ich wieder auf den ursprünglichen MS-Beispielcode für die Führung beziehen, oder auf Referenzen in den anderen Antworten auf diese Frage.

Imports Microsoft.VisualBasic

Module Module1

'Sample COMP-3 conversion code
'Adapted from http://support.microsoft.com/kb/65323
'This code has not been tested

Sub Main()

    Dim Digits%(15)       'Holds the digits for each number (max = 16).
    Dim Basiceqv#(1000)   'Holds the Basic equivalent of each COMP-3 number.

    'Added to make code compile
    Dim MyByte As Char, HighPower%, HighNibble%
    Dim LowNibble%, Digit%, E%, Decimal%, FileName$


    'Clear the screen, get the filename and the amount of decimal places
    'desired for each number, and open the file for sequential input:
    FileName$ = InputBox("Enter the COBOL data file name: ")
    Decimal% = InputBox("Enter the number of decimal places desired: ")

    FileOpen(1, FileName$, OpenMode.Binary)

    Do Until EOF(1)   'Loop until the end of the file is reached.
        Input(1, MyByte)
        If MyByte = Chr(0) Then     'Check if byte is 0 (ASC won't work on 0).
            Digits%(HighPower%) = 0       'Make next two digits 0. Increment
            Digits%(HighPower% + 1) = 0   'the high power to reflect the
            HighPower% = HighPower% + 2   'number of digits in the number
            'plus 1.
        Else
            HighNibble% = Asc(MyByte) \ 16      'Extract the high and low
            LowNibble% = Asc(MyByte) And &HF    'nibbles from the byte. The
            Digits%(HighPower%) = HighNibble%  'high nibble will always be a
            'digit.
            If LowNibble% <= 9 Then                   'If low nibble is a
                'digit, assign it and
                Digits%(HighPower% + 1) = LowNibble%   'increment the high
                HighPower% = HighPower% + 2            'power accordingly.
            Else
                HighPower% = HighPower% + 1 'Low nibble was not a digit but a
                Digit% = 0                  '+ or - signals end of number.

                'Start at the highest power of 10 for the number and multiply
                'each digit by the power of 10 place it occupies.
                For Power% = (HighPower% - 1) To 0 Step -1
                    Basiceqv#(E%) = Basiceqv#(E%) + (Digits%(Digit%) * (10 ^ Power%))
                    Digit% = Digit% + 1
                Next

                'If the sign read was negative, make the number negative.
                If LowNibble% = 13 Then
                    Basiceqv#(E%) = Basiceqv#(E%) - (2 * Basiceqv#(E%))
                End If

                'Give the number the desired amount of decimal places, print
                'the number, increment E% to point to the next number to be
                'converted, and reinitialize the highest power.
                Basiceqv#(E%) = Basiceqv#(E%) / (10 ^ Decimal%)
                Print(Basiceqv#(E%))
                E% = E% + 1
                HighPower% = 0
            End If
        End If
    Loop

    FileClose()   'Close the COBOL data file, and end.
End Sub

End Module

Andere Tipps

Ich habe die Beiträge auf zahlreichen Gremien gerade in Bezug auf die Umwandlung Comp-3 BCD-Daten von „Legacy“ Mainframe-Dateien auf etwas leicht zu benutzende C #. Als erstes möchte ich sagen, dass ich weniger als durch die Antworten verliebte, die einige dieser Stellen erhalten haben - vor allem denjenigen, die gesagt haben, im Wesentlichen „Warum stören Sie uns mit diesem nicht-C # / C ++ related posts“ und auch „Wenn Sie müssen eine Antwort über eine Art von COBOL-Konvention, warum Sie keine COBOL orientierte Website“gehen besuchen. Dies ist für mich, ist komplett BS als eine Notwendigkeit für wahrscheinlich viele Jahre sein wird zu kommen, (leider), für Software-Entwickler zu verstehen, wie mit einigen dieser Altlasten beschäftigen, die in der realen Welt existieren. Also, auch wenn ich auf diesen Beitrag für den folgenden Code knallte bekommen, werde ich mit Ihnen eine praktische Erfahrung teilen, die ich mit Bezug auf COMP-3 / EBCDIC-Konvertierung zu tun hatte (und ja, ich bin es, der spricht von " Disketten, Papier-Band, Disc Pack etc ... -. ich habe seit 1979" ein Software-Ingenieur gewesen)

Erste - verstehen, dass jede Datei, die Sie von einem Legacy-Hauptframe-System wie IBM gelesen wird, die Daten zu Ihnen im EBCDIC-Format zu präsentieren und um jede dieser Daten zu einem C # / C zu konvertieren ++ String Sie können behandeln mit Ihnen die richtigen Codepage-Übersetzung haben, verwenden werden die Daten in ASCII-Format zu bekommen. Ein gutes Beispiel dafür, wie das zu handhaben wäre:

Streamreadfile = new Stream (Pfad, Encoding.GetEncoding (037);. // 037 = EBCDIC zu ASCII-Übersetzung

Dadurch wird sichergestellt, dass alles, was Sie aus diesem Stream gelesen wird dann in ASCII umgewandelt werden und kann in einem String Format verwendet werden. Dazu gehören "zoned decimal" (Bild 9) und "Text" (Pic X) Felder, wie durch COBOL erklärt. Allerdings bedeuten dies nicht unbedingt COMP-3-Felder auf den richtigen „binären“ equivelant umwandeln, wenn sie in ein char [] oder byte [] Array gelesen. Um dies zu tun, ist der einzige Weg, die Sie jemals gehen werden diese richtig übersetzt bekommen (auch mit UTF-8, UTF-16, Standard oder was auch immer) Code-Seiten, Sie gehen zu wollen, die Datei wie folgt zu öffnen:

Filestream filestream = new Filestream (Pfad, FIleMode.Open, FIleAccess.Read, FileShare.Read);

Natürlich ist die "FileShare.Read" Option ist "optional".

Wenn Sie das Feld isoliert haben, die Sie in einen Dezimalwert konvertiert werden sollen (und dann anschließend in einem ASCII-String, wenn es sein muss), können Sie den folgenden Code verwenden - und das von dem Microsoft „UnpackDecimal“ im Grunde gestohlen wurde Posting, dass man bei bekommen:

http: // www. microsoft.com/downloads/details.aspx?familyid=0e4bba52-cc52-4d89-8590-cda297ff7fbd&displaylang=en

Ich habe isoliert (glaube ich), was die wichtigsten Teile dieser Logik sind und konsolidiert sie in zwei eine Methode, die Sie mit tun, was Sie wollen. Für meine Zwecke, wählte ich diese zu verlassen, wie ein Dezimal-Wert zurück, die ich dann tun konnte, was ich wollte. Grundsätzlich wird das Verfahren als „entpackt“ und man sich ein byte [] array (nicht länger als 12 Bytes) und die Skala als int, die die Anzahl von Dezimalstellen ist man in der Dezimalwert zurückgegeben werden soll. Ich hoffe, dass dies für Sie arbeitet ebenso wie es für mich getan hat.

    private Decimal Unpack(byte[] inp, int scale)
    {
        long lo = 0;
        long mid = 0;
        long hi = 0;
        bool isNegative;

        // this nybble stores only the sign, not a digit.  
        // "C" hex is positive, "D" hex is negative, and "F" hex is unsigned. 
        switch (nibble(inp, 0))
        {
            case 0x0D:
                isNegative = true;
                break;
            case 0x0F:
            case 0x0C:
                isNegative = false;
                break;
            default:
                throw new Exception("Bad sign nibble");
        }
        long intermediate;
        long carry;
        long digit;
        for (int j = inp.Length * 2 - 1; j > 0; j--)
        {
            // multiply by 10
            intermediate = lo * 10;
            lo = intermediate & 0xffffffff;
            carry = intermediate >> 32;
            intermediate = mid * 10 + carry;
            mid = intermediate & 0xffffffff;
            carry = intermediate >> 32;
            intermediate = hi * 10 + carry;
            hi = intermediate & 0xffffffff;
            carry = intermediate >> 32;
            // By limiting input length to 14, we ensure overflow will never occur

            digit = nibble(inp, j);
            if (digit > 9)
            {
                throw new Exception("Bad digit");
            }
            intermediate = lo + digit;
            lo = intermediate & 0xffffffff;
            carry = intermediate >> 32;
            if (carry > 0)
            {
                intermediate = mid + carry;
                mid = intermediate & 0xffffffff;
                carry = intermediate >> 32;
                if (carry > 0)
                {
                    intermediate = hi + carry;
                    hi = intermediate & 0xffffffff;
                    carry = intermediate >> 32;
                    // carry should never be non-zero. Back up with validation
                }
            }
        }
        return new Decimal((int)lo, (int)mid, (int)hi, isNegative, (byte)scale);
    }

    private int nibble(byte[] inp, int nibbleNo)
    {
        int b = inp[inp.Length - 1 - nibbleNo / 2];
        return (nibbleNo % 2 == 0) ? (b & 0x0000000F) : (b >> 4);
    }

Wenn Sie Fragen haben, schreiben sie hier - weil ich vermute, dass ich bekommen werde „geflammt“ wie alle anderen, die entschieden hat, Fragen zu stellen, die zum heutigen Probleme relevant sind ...

Danke, John -. The Elder

Wenn die ursprünglichen Daten in EBCDIC war Ihr COMP-3-Feld verstümmelt wurde. Der FTP-Prozess hat eine EBCDIC zu ASCII-Übersetzung der Byte-Werte in dem COMP-3-Feld durchgeführt, die nicht ist, was Sie wollen. Um dies zu korrigieren können Sie:

1) Verwenden Sie Binär-Modus für die Übertragung, so dass Sie die rohen EBCDIC Daten. Dann sind Sie das COMP-3-Feld in eine Zahl umwandeln und anderen EBCDIC Text auf der Platte in ASCII übersetzen. Ein gepacktes Feld speichert jede Ziffer in einem Halbbyte mit dem unteren Halbbyte als Zeichen (F positiv ist, und andere Werte, in der Regel D oder E, sind negativ). Speicher von 123,4 in einem PIC 999,99 USAGE COMP-3 wäre X'01234F '(drei Byte) und -123 im gleichen Feld ist X'01230D'.

2) Lassen Sie den Absender, das Feld in eine USAGE konvertieren IS DISPLAY SIGN führt (oder nachgestellte) numerisches Feld. Diese speichert die Nummer als eine Kette von EBCDIC Ziffern mit dem Zeichen als separates negativen (-) oder Leerzeichen. Alle Ziffern und das Zeichen übersetzen richtig in ihrem ASCII-äquivalent auf der FTP-Übertragung.

Ich entschuldige mich, wenn ich weg Basis hier bin, aber vielleicht ist dieses Codebeispiel könnte ich Ihnen hier einfügen werde dir helfen. Das kam von VBRocks ...

Imports System
Imports System.IO
Imports System.Text
Imports System.Text.Encoding



'4/20/07 submission includes a line spacing addition when a control character is used:
'   The line spacing is calculated off of the 3rd control character.
'
'   Also includes the 4/18 modification of determining end of file.

'4/26/07 submission inclues an addition of 6 to the record length when the 4th control
'   character is an 8.  This is because these records were being truncated.


'Authored by Gary A. Lima, aka. VBRocks



''' <summary>
''' Translates an EBCDIC file to an ASCII file.
''' </summary>
''' <remarks></remarks>
Public Class EBCDIC_to_ASCII_Translator

#Region " Example"

    Private Sub Example()
        'Set your source file and destination file paths
        Dim sSourcePath As String = "c:\Temp\MyEBCDICFile"
        Dim sDestinationPath As String = "c:\Temp\TranslatedFile.txt"

        Dim trans As New EBCDIC_to_ASCII_Translator()

        'If your EBCDIC file uses Control records to determine the length of a record, then this to True
        trans.UseControlRecord = True

        'If the first record of your EBCDIC file is filler (junk), then set this to True
        trans.IgnoreFirstRecord = True

        'EBCDIC files are written in block lengths, set your block length (Example:  134, 900, Etc.)
        trans.BlockLength = 900

        'This method will actually translate your source file and output it to the specified destination file path
        trans.TranslateFile(sSourcePath, sDestinationPath)


        'Here is a alternate example:
        'No Control record is used
        'trans.UseControlRecord = False

        'Translate the whole file, including the first record
        'trans.IgnoreFirstRecord = False

        'Set the block length
        'trans.BlockLength = 134

        'Translate...
        'trans.TranslateFile(sSourcePath, sDestinationPath)



        '*** Some additional methods that you can use are:

        'Trim off leading characters from left side of string (position 0 to...)
        'trans.LTrim = 15

        'Translate 1 EBCDIC character to an ASCII character
        'Dim strASCIIChar as String = trans.TranslateCharacter("S")

        'Translate an EBCDIC character array to an ASCII string
        'trans.TranslateCharacters(chrEBCDICArray)

        'Translates an EBCDIC string to an ASCII string
        'Dim strASCII As String = trans.TranslateString("EBCDIC String")


    End Sub

#End Region    'Example

    'Translate characters from EBCDIC to ASCII

    Private ASCIIEncoding As Encoding = Encoding.ASCII
    Private EBCDICEncoding As Encoding = Encoding.GetEncoding(37)  'EBCDIC

    'Block Length:  Can be fixed (Ex:  134). 
    Private miBlockLength As Integer = 0
    Private mbUseControlRec As Boolean = True        'If set to False, will return exact block length
    Private mbIgnoreFirstRecord As Boolean = True    'Will Ignore first record if set to true  (First record may be filler)
    Private miLTrim As Integer = 0

    ''' <summary>
    ''' Translates SourceFile from EBCDIC to ASCII.  Writes output to file path specified by DestinationFile parameter.
    ''' Set the BlockLength Property to designate block size to read.
    ''' </summary>
    ''' <param name="SourceFile">Enter the path of the Source File.</param>
    ''' <param name="DestinationFile">Enter the path of the Destination File.</param>
    ''' <remarks></remarks>
    Public Sub TranslateFile(ByVal SourceFile As String, ByVal DestinationFile As String)

        Dim iRecordLength As Integer     'Stores length of a record, not including the length of the Control Record (if used)
        Dim sRecord As String = ""         'Stores the actual record
        Dim iLineSpace As Integer = 1    'LineSpace:  1 for Single Space, 2 for Double Space, 3 for Triple Space...

        Dim iControlPosSix As Byte()      'Stores the 6th character of a Control Record (used to calculate record length)
        Dim iControlRec As Byte()          'Stores the EBCDIC Control Record (First 6 characters of record)
        Dim bEOR As Boolean                'End of Record Flag
        Dim bBOF As Boolean = True      'Beginning of file
        Dim iConsumedChars As Integer = 0     'Stores the number of consumed characters in the current block
        Dim bIgnoreRecord As Boolean = mbIgnoreFirstRecord   'Ignores the first record if set.

        Dim ControlArray(5) As Char         'Stores Control Record (first 6 bytes)
        Dim chrArray As Char()              'Stores characters just after read from file

        Dim sr As New StreamReader(SourceFile, EBCDICEncoding)
        Dim sw As New StreamWriter(DestinationFile)

        'Set the RecordLength to the RecordLength Property (below)
        iRecordLength = miBlockLength

        'Loop through entire file
        Do Until sr.EndOfStream = True

            'If using a Control Record, then check record for valid data.
            If mbUseControlRec = True Then
                'Read the Control Record (first 6 characters of the record)
                sr.ReadBlock(ControlArray, 0, 6)

                'Update the value of consumed (read) characters
                iConsumedChars += ControlArray.Length

                'Get the bytes of the Control Record Array
                iControlRec = EBCDICEncoding.GetBytes(ControlArray)

                'Set the line spacing  (position 3 divided by 64)
                '   (64 decimal = Single Spacing; 128 decimal = Double Spacing)
                iLineSpace = iControlRec(2) / 64


                'Check the Control record for End of File
                'If the Control record has a 8 or 10 in position 1, and a 1 in postion 2, then it is the end of the file
                If (iControlRec(0) = 8 OrElse iControlRec(0) = 10) AndAlso _
                    iControlRec(1) = 1 Then

                    If bBOF = False Then
                        Exit Do

                    Else
                        'The Beginning of file flag is set to true by default, so when the first
                        '   record is encountered, it is bypassed and the bBOF flag is set to False
                        bBOF = False

                    End If    'If bBOF = Fals

                End If    'If (iControlRec(0) = 8 OrElse



                'Set the default value for the End of Record flag to True
                '   If the Control Record has all zeros, then it's True, else False
                bEOR = True

                'If the Control record contains all zeros, bEOR will stay True, else it will be set to False
                For i As Integer = 0 To 5
                    If iControlRec(i) > 0 Then
                        bEOR = False

                        Exit For

                    End If    'If iControlRec(i) > 0

                Next    'For i As Integer = 0 To 5

                If bEOR = False Then
                    'Convert EBCDIC character to ASCII
                    'Multiply the 6th byte by 6 to get record length
                    '   Why multiply by 6?  Because it works.
                    iControlPosSix = EBCDICEncoding.GetBytes(ControlArray(5))

                    'If the 4th position of the control record is an 8, then add 6
                    '    to the record length to pick up remaining characters.
                    If iControlRec(3) = 8 Then
                        iRecordLength = CInt(iControlPosSix(0)) * 6 + 6

                    Else
                        iRecordLength = CInt(iControlPosSix(0)) * 6

                    End If

                    'Add the length of the record to the Consumed Characters counter
                    iConsumedChars += iRecordLength

                Else
                    'If the Control Record had all zeros in it, then it is the end of the Block.

                    'Consume the remainder of the block so we can continue at the beginning of the next block.
                    ReDim chrArray(miBlockLength - iConsumedChars - 1)
                    'ReDim chrArray(iRecordLength - iConsumedChars - 1)

                    'Consume (read) the remaining characters in the block.  
                    '   We are not doing anything with them because they are not actual records.
                    'sr.ReadBlock(chrArray, 0, iRecordLength - iConsumedChars)
                    sr.ReadBlock(chrArray, 0, miBlockLength - iConsumedChars)

                    'Reset the Consumed Characters counter
                    iConsumedChars = 0

                    'Set the Record Length to 0 so it will not be processed below.
                    iRecordLength = 0

                End If    ' If bEOR = False

            End If    'If mbUseControlRec = True



            If iRecordLength > 0 Then
                'Resize our array, dumping previous data.  Because Arrays are Zero (0) based, subtract 1 from the Record length.
                ReDim chrArray(iRecordLength - 1)

                'Read the specfied record length, without the Control Record, because we already consumed (read) it.
                sr.ReadBlock(chrArray, 0, iRecordLength)

                'Copy Character Array to String Array, Converting in the process, then Join the Array to a string
                sRecord = Join(Array.ConvertAll(chrArray, New Converter(Of Char, String)(AddressOf ChrToStr)), "")

                'If the record length was 0, then the Join method may return Nothing
                If IsNothing(sRecord) = False Then

                    If bIgnoreRecord = True Then
                        'Do nothing - bypass record

                        'Reset flag
                        bIgnoreRecord = False

                    Else
                        'Write the line out, LTrimming the specified number of characters.
                        If sRecord.Length >= miLTrim Then
                            sw.WriteLine(sRecord.Remove(0, miLTrim))

                        Else
                            sw.WriteLine(sRecord.Remove(0, sRecord.Length))

                        End If    ' If sRecord.Length >= miLTrim

                        'Write out the number of blank lines specified by the 3rd control character.
                        For i As Integer = 1 To iLineSpace - 1
                            sw.WriteLine("")

                        Next    'For i As Integer = 1 To iLineSpace

                    End If    'If bIgnoreRecord = True


                    'Obviously, if we have read more characters from the file than the designated size of the block,
                    '   then subtract the number of characters we have read into the next block from the block size.
                    If iConsumedChars > miBlockLength Then
                        'If iConsumedChars > iRecordLength Then
                        iConsumedChars = iConsumedChars - miBlockLength
                        'iConsumedChars = iConsumedChars - iRecordLength

                    End If

                End If    'If IsNothing(sRecord) = False

            End If    'If iRecordLength > 0

            'Allow computer to process  (works in a class module, not in a dll)
            'Application.DoEvents()

        Loop

        'Destroy StreamReader (sr)
        sr.Close()
        sr.Dispose()

        'Destroy StreamWriter (sw)
        sw.Close()
        sw.Dispose()

    End Sub



    ''' <summary>
    ''' Translates 1 EBCDIC Character (Char) to an ASCII String
    ''' </summary>
    ''' <param name="chr"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function ChrToStr(ByVal chr As Char) As String
        Dim sReturn As String = ""

        'Convert character into byte
        Dim EBCDICbyte As Byte() = EBCDICEncoding.GetBytes(chr)

        'Convert EBCDIC byte to ASCII byte
        Dim ASCIIByte As Byte() = Encoding.Convert(EBCDICEncoding, ASCIIEncoding, EBCDICbyte)

        sReturn = Encoding.ASCII.GetString(ASCIIByte)

        Return sReturn

    End Function



    ''' <summary>
    ''' Translates an EBCDIC String to an ASCII String
    ''' </summary>
    ''' <param name="sStringToTranslate"></param>
    ''' <returns>String</returns>
    ''' <remarks></remarks>
    Public Function TranslateString(ByVal sStringToTranslate As String) As String
        Dim i As Integer = 0
        Dim sReturn As New System.Text.StringBuilder()

        'Loop through the string and translate each character
        For i = 0 To sStringToTranslate.Length - 1
            sReturn.Append(ChrToStr(sStringToTranslate.Substring(i, 1)))

        Next

        Return sReturn.ToString()


    End Function



    ''' <summary>
    ''' Translates 1 EBCDIC Character (Char) to an ASCII String
    ''' </summary>
    ''' <param name="sCharacterToTranslate"></param>
    ''' <returns>String</returns>
    ''' <remarks></remarks>
    Public Function TranslateCharacter(ByVal sCharacterToTranslate As Char) As String

        Return ChrToStr(sCharacterToTranslate)

    End Function



    ''' <summary>
    ''' Translates an EBCDIC Character (Char) Array to an ASCII String
    ''' </summary>
    ''' <param name="sCharacterArrayToTranslate"></param>
    ''' <returns>String</returns>
    ''' <remarks>Remarks</remarks>
    Public Function TranslateCharacters(ByVal sCharacterArrayToTranslate As Char()) As String
        Dim sReturn As String = ""

        'Copy Character Array to String Array, Converting in the process, then Join the Array to a string
        sReturn = Join(Array.ConvertAll(sCharacterArrayToTranslate, _
                            New Converter(Of Char, String)(AddressOf ChrToStr)), "")

        Return sReturn

    End Function


    ''' <summary>
    ''' Block Length must be set.  You can set the BlockLength for specific block sizes (Ex:  134).
    ''' Set UseControlRecord = False for files with specific block sizes (Default is True)
    ''' </summary>
    ''' <value>0</value>
    ''' <returns>Integer</returns>
    ''' <remarks></remarks>
    Public Property BlockLength() As Integer
        Get
            Return miBlockLength

        End Get
        Set(ByVal value As Integer)
            miBlockLength = value

        End Set
    End Property



    ''' <summary>
    ''' Determines whether a ControlKey is used to calculate RecordLength of valid data
    ''' </summary>
    ''' <value>Default value is True</value>
    ''' <returns>Boolean</returns>
    ''' <remarks></remarks>
    Public Property UseControlRecord() As Boolean
        Get
            Return mbUseControlRec

        End Get
        Set(ByVal value As Boolean)
            mbUseControlRec = value

        End Set
    End Property



    ''' <summary>
    ''' Ignores first record if set (Default is True)
    ''' </summary>
    ''' <value>Default is True</value>
    ''' <returns>Boolean</returns>
    ''' <remarks></remarks>
    Public Property IgnoreFirstRecord() As Boolean
        Get
            Return mbIgnoreFirstRecord

        End Get

        Set(ByVal value As Boolean)
            mbIgnoreFirstRecord = value

        End Set
    End Property



    ''' <summary>
    ''' Trims the left side of every string the specfied number of characters.  Default is 0.
    ''' </summary>
    ''' <value>Default is 0.</value>
    ''' <returns>Integer</returns>
    ''' <remarks></remarks>
    Public Property LTrim() As Integer
        Get
            Return miLTrim

        End Get

        Set(ByVal value As Integer)
            miLTrim = value

        End Set
    End Property


End Class

Einige nützliche Links für EBCDIC Übersetzung:

Übersetzungstabelle - nützlich einige der Werte in den gepackten Dezimalfeldern zu tun überprüfen: http://www.simotime.com/asc2ebc1.htm

Liste der Codepages in Msdn:
http://msdn.microsoft.com/en-us /library/dd317756(VS.85).aspx

Und ein Stück Code, um die Byte-Array-Felder in C # zu konvertieren:

// 500 is the code page for IBM EBCDIC International 
System.Text.Encoding enc = new System.Text.Encoding(500);
string value = enc.GetString(byteArrayField);

Die gepackten Felder sind die gleichen in EBCDIC oder ASCII. Sie nicht die EBCDIC zu ASCII-Konvertierung auf ihnen laufen. In .Net steckt sie in ein byte [].

Sie verwenden bitweise Masken und verschiebt zu packen / entpacken. - Aber bitweise ops gelten nur Typen in .NET auf Integer, so dass Sie durch einige Reifen springen müssen

Ein guter COBOL oder C Künstler können Sie in die richtige Richtung zeigen.

einer der alten Jungs finden und Ihre Gebühren (etwa drei Bier sollte es tun) zahlen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top