Question

J'ai une série de fichiers plats ASCII provenant d'un ordinateur central qui doivent être traités par une application C #. Un nouveau flux a été introduit avec un champ Décimal empaqueté (COMP-3), qui doit être converti en une valeur numérique.

Les fichiers sont en cours de transfert via FTP, en utilisant le mode de transfert ASCII. Je crains que le champ binaire ne contienne ce qui sera interprété comme un code ASCII très faible ou des caractères de contrôle au lieu d’une valeur - ou pire, risque d’être perdu dans le processus FTP.

De plus, les champs sont lus sous forme de chaînes. J'aurai peut-être la possibilité de contourner cette partie (c'est-à-dire un flux), mais l'entreprise me donnera du recul.

L'exigence indiquait "Convertir de HEX à ASCII", mais cela ne donnait manifestement pas les valeurs correctes. Toute aide serait appréciée; il n'est pas nécessaire que ce soit spécifique à la langue, tant que vous pouvez expliquer la logique du processus de conversion.

Était-ce utile?

La solution

Tout d’abord, vous devez éliminer les problèmes de traduction de fin de ligne (EOL) dus au mode de transfert ASCII. Vous avez absolument raison de vous inquiéter de la corruption des données lorsque les valeurs BCD correspondent à des caractères EOL. Le pire aspect de ce problème est qu’il se produira rarement et de manière inattendue.

La meilleure solution consiste à changer le mode de transfert en BIN. Ceci est approprié car les données que vous transférez sont binaires. S'il n'est pas possible d'utiliser le mode de transfert FTP correct, vous pouvez annuler les dommages liés au mode ASCII dans le code. Tout ce que vous avez à faire est de reconvertir les \ r \ n paires en \ n. Si j'étais vous, je m'assurerais que cela soit bien testé.

Une fois que vous avez résolu le problème de la fin de vie, la conversion COMP-3 est plutôt simple. J'ai pu trouver cet article dans la base de connaissances MS avec un exemple de code en BASIC. Voir ci-dessous pour un port VB.NET de ce code.

Etant donné que vous utilisez des valeurs COMP-3, le format de fichier que vous lisez a probablement des tailles d’enregistrement fixes avec des longueurs de champs fixes. Si j'étais vous, je disposerais d'une spécification de format de fichier avant d'aller plus loin avec ceci. Vous devriez utiliser un BinaryReader pour travailler avec ces données. Si quelqu'un repousse sur ce point, je partirais. Laissez-les trouver quelqu'un d'autre pour se livrer à leur folie.

Voici un port VB.NET du code exemple BASIC. Je n'ai pas testé cela parce que je n'ai pas accès à un fichier COMP-3. Si cela ne fonctionne pas, je renvoie au code exemple MS d'origine ou aux références fournies dans les autres réponses à cette question.

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

Autres conseils

J'ai consulté les messages de nombreux forums concernant la conversion des données Comp-3 BCD à partir de "legacy". fichiers mainframe à quelque chose utilisable en C #. Premièrement, je voudrais dire que je suis moins séduit par les réponses que certains de ces messages ont reçues - en particulier celles qui ont dit essentiellement "pourquoi nous dérangez-vous avec ces messages non liés à C # / C ++" et aussi "Si vous avez besoin d'une réponse à propos d'une sorte de convention COBOL, pourquoi ne pas aller visiter un site orienté COBOL". Pour moi, il s’agit d’une BS complète, car les développeurs de logiciels auront probablement besoin (bien entendu) de nombreuses années à venir pour comprendre comment traiter certains de ces problèmes hérités qui existent dans THE REAL WORLD. Donc, même si on me reproche ce code pour le code suivant, je vais partager avec vous une expérience REAL WORLD à laquelle je devais faire face en ce qui concerne la conversion COMP-3 / EBCDIC (et oui, je suis lui qui parle de " ; disquettes, bandes de papier, kits de disques, etc. - Je suis ingénieur en logiciel depuis 1979 ").

Premièrement, comprenez que tout fichier lu depuis un système principal tel qu'IBM va vous présenter les données au format EBCDIC et que vous pouvez convertir ces données en chaîne C # / C ++. avec vous allez devoir utiliser la traduction de page de code appropriée pour obtenir les données au format ASCII. Un bon exemple de la façon de gérer cela serait:

StreamReader readFile = new StreamReader (chemin, Encoding.GetEncoding (037); // 037 = traduction EBCDIC vers ASCII.

Cela garantira que tout ce que vous lisez dans ce flux sera ensuite converti en ASCII et pourra être utilisé dans un format de chaîne. Ceci inclut & déc; Zoned Decimal " (Photo 9) et "Texte" (Pic X) les champs tels que déclarés par COBOL. Toutefois, cela ne convertit pas nécessairement les champs COMP-3 en champs "binaires" corrects. équivelant lorsqu'il est lu dans un tableau char [] ou byte []. Pour ce faire, la seule façon dont vous obtiendrez cette traduction correctement (même en utilisant des pages de code UTF-8, UTF-16, Default ou autre), vous allez vouloir ouvrir le fichier comme ceci:

FileStream fileStream = new FileStream (chemin, FIleMode.Open, FIleAccess.Read, FileShare.Read);

Bien sûr, le " FileShare.Read " l'option est "facultative".

Lorsque vous avez isolé le champ que vous souhaitez convertir en valeur décimale (puis ultérieurement en chaîne ASCII si besoin est), vous pouvez utiliser le code suivant. Ce code a été volé à MicroSoft " UnpackDecimal ". ; poste que vous pouvez obtenir à:

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

J'ai isolé (je pense) quelles sont les parties les plus importantes de cette logique et l'ai consolidée en deux, une méthode que vous pouvez utiliser avec ce que vous voulez. Pour mes besoins, j'ai choisi de laisser ceci comme renvoyant une valeur décimale que je pourrais ensuite faire avec ce que je voulais. Fondamentalement, la méthode s'appelle "décompresser". et vous lui passez un tableau d'octets [] (pas plus de 12 octets) et l'échelle sous la forme d'un entier, qui correspond au nombre de décimales que vous souhaitez obtenir dans la valeur décimale. J'espère que cela fonctionne pour vous aussi bien que pour moi.

    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);
    }

Si vous avez des questions, postez-les ici - car je soupçonne que je vais me faire "flamber". comme tout le monde qui a choisi de poser des questions pertinentes pour les problèmes actuels ...

Merci, John - l'aîné.

Si les données d'origine étaient dans EBCDIC, votre champ COMP-3 a été altéré. Le processus FTP a effectué une conversion EBCDIC en ASCII des valeurs d'octet dans le champ COMP-3, ce qui n'est pas ce que vous voulez. Pour corriger cela, vous pouvez:

1) Utilisez le mode BINAIRE pour le transfert afin d’obtenir les données brutes EBCDIC. Ensuite, vous convertissez le champ COMP-3 en un nombre et traduisez tout autre texte EBCDIC de l'enregistrement en ASCII. Un champ condensé stocke chaque chiffre dans un demi-octet avec le demi-octet inférieur comme signe (F est positif et les autres valeurs, généralement D ou E, sont négatives). Le stockage de 123,4 dans un PIC 999.99 USAGE COMP-3 correspond à X'01234F '(trois octets) et -123 dans le même champ correspond à X'01230D'.

2) Demandez à l'expéditeur de convertir le champ en champ numérique USAGE IS DISPLAY SIGN IS LEADING (ou TRAILING). Ceci stocke le numéro sous forme de chaîne de chiffres numériques EBCDIC avec le signe sous la forme d'un caractère négatif (-) ou vide distinct. Tous les chiffres et le signe sont traduits correctement en équivalents ASCII lors du transfert FTP.

Je m'excuse si je ne suis pas à la hauteur, mais peut-être que cet exemple de code que je vais coller ici pourrait vous aider. Cela venait de 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

Quelques liens utiles pour la traduction EBCDIC:

Table de traduction - utile pour vérifier certaines des valeurs des champs décimaux condensés: http://www.simotime.com/asc2ebc1.htm

Liste des pages de code dans msdn:
http://msdn.microsoft.com/en-us /library/dd317756(VS.85).aspx

Et un morceau de code pour convertir les champs du tableau d'octets en C #:

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

Les champs compressés sont les mêmes dans EBCDIC ou ASCII. N'exécutez pas la conversion EBCDIC vers ASCII sur eux. En .Net les dump dans un octet [].

Vous utilisez des masques et des décalages au niveau des bits pour compresser / décompresser. - Mais les opérations au niveau des bits ne s’appliquent qu’aux types de nombres entiers dans .Net.

Un bon artiste COBOL ou C peut vous orienter dans la bonne direction.

Trouvez l’un des vieux gars et payez votre cotisation (environ trois bières devraient le faire).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top