문제

C# 응용 프로그램에서 처리하기 위해 메인프레임에서 들어오는 일련의 ASCII 플랫 파일이 있습니다.숫자 값으로 변환해야 하는 Packed Decimal(COMP-3) 필드가 포함된 새 피드가 도입되었습니다.

파일은 ASCII 전송 모드를 사용하여 FTP를 통해 전송되고 있습니다.바이너리 필드에 값 대신 매우 낮은 ASCII 코드나 제어 문자로 해석되는 내용이 포함될 수 있다는 점이 걱정됩니다. 더 나쁜 경우에는 FTP 프로세스에서 손실될 수도 있습니다.

게다가 필드는 문자열로 읽혀집니다.이 부분을 유연하게 해결할 수 있습니다(예:일종의 스트림), 하지만 비즈니스에서 반발을 불러일으킬 것입니다.

요구 사항은 "HEX에서 ASCII로 변환"이라고 읽었지만 분명히 올바른 값을 산출하지 못했습니다.어떤 도움이라도 주시면 감사하겠습니다.변환 프로세스의 논리를 설명할 수 있는 한 언어별로 다를 필요는 없습니다.

도움이 되었습니까?

해결책

우선 ASCII 전송 모드로 인해 발생할 EOL (End of Line) 번역 문제를 제거해야합니다. BCD 값이 EOL 문자에 해당하는 경우 데이터 손상에 대해 걱정하는 것이 절대적으로 옳습니다. 이 문제의 최악의 측면은 거의 예기치 않게 발생한다는 것입니다.

가장 좋은 솔루션은 전송 모드를 빈으로 변경하는 것입니다. 전송중인 데이터가 이진이므로 적절합니다. 올바른 FTP 전송 모드를 사용할 수 없으면 코드에서 ASCII 모드 손상을 취소 할 수 있습니다. r n 쌍을 다시 n으로 변환하기 만하면됩니다. 내가 당신이라면 나는 이것이 잘 테스트되었는지 확인할 것입니다.

EOL 문제를 처리 한 후에는 COMP-3 변환이 꽤 스트라이트 포워드입니다. 나는 찾을 수 있었다 이 기사 기본의 샘플 코드가있는 MS Knowledgebase에서. 이 코드의 vb.net 포트는 아래를 참조하십시오.

Comp-3 값을 다루고 있으므로 읽고있는 파일 형식은 필드 길이가 고정 된 고정 레코드 크기를 가지고 있습니다. 내가 당신이라면, 나는 당신이 이것으로 더 나아 가기 전에 파일 형식 사양의 손을 얻을 것입니다. 이 데이터를 사용하여 이진 리더를 사용해야합니다. 누군가 가이 시점에서 뒤로 밀고 있다면, 나는 떠날 것입니다. 어리 석음에 빠질 다른 사람을 찾으십시오.

다음은 기본 샘플 코드의 VB.NET 포트입니다. Comp-3 파일에 액세스 할 수 없기 때문에 이것을 테스트하지 않았습니다. 이것이 효과가 없다면, 지침을 위해 원래 MS 샘플 코드를 다시 참조 하거나이 질문에 대한 다른 답변에 대한 참조를 참조합니다.

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

다른 팁

저는 "레거시" 메인프레임 파일의 Comp-3 BCD 데이터를 C#에서 사용할 수 있는 파일로 변환하는 것에 관한 수많은 게시판의 게시물을 지켜보았습니다.첫째, 저는 이러한 게시물 중 일부에서 받은 응답, 특히 "C#/C++와 관련되지 않은 게시물로 우리를 괴롭히는 이유가 무엇입니까?" 및 "만약 일종의 COBOL 규칙에 대한 답변이 필요하다면 COBOL 지향 사이트를 방문하는 것이 어떻겠습니까?"(불행히도) 소프트웨어 개발자가 현실 세계에 존재하는 이러한 레거시 문제 중 일부를 처리하는 방법을 이해해야 하기 때문에 이것은 나에게 완전한 학사입니다.따라서 다음 코드로 인해 이 게시물에서 비난을 받더라도 COMP-3/EBCDIC 변환과 관련하여 처리해야 했던 실제 경험을 여러분과 공유하려고 합니다. 플로피 디스크, 종이 테이프, 디스크 팩 등...- 나는 1979년부터 소프트웨어 엔지니어로 일해 왔습니다.")

첫째, IBM과 같은 레거시 메인프레임 시스템에서 읽는 모든 파일은 EBCDIC 형식으로 데이터를 제공하고 해당 데이터를 처리할 수 있는 C#/C++ 문자열로 변환한다는 점을 이해하십시오. 데이터를 ASCII 형식으로 가져오려면 적절한 코드 페이지 변환을 사용해야 합니다.이를 처리하는 방법에 대한 좋은 예는 다음과 같습니다.

StreamReader readFile = 새로운 StreamReader(경로, Encoding.GetEncoding(037);// 037 = EBCDIC를 ASCII로 변환합니다.

이렇게 하면 이 스트림에서 읽는 모든 내용이 ASCII로 변환되어 문자열 형식으로 사용될 수 있습니다.여기에는 COBOL에서 선언한 "Zoned Decimal"(Pic 9) 및 "Text"(Pic X) 필드가 포함됩니다.그러나 char[] 또는 byte[] 배열로 읽을 때 COMP-3 필드를 올바른 "이진" 등가물로 변환할 필요는 없습니다.이렇게 하려면 코드 페이지를 올바르게 번역할 수 있는 유일한 방법(UTF-8, UTF-16, 기본 등을 사용하더라도) 다음과 같이 파일을 열어야 합니다.

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

물론 "FileShare.Read" 옵션은 "선택 사항"입니다.

10진수 값(필요한 경우 이후에 ASCII 문자열)으로 변환하려는 필드를 분리한 경우 다음 코드를 사용할 수 있습니다. 이 코드는 기본적으로 MicroSoft "UnpackDecimal" 게시에서 도난당했습니다. 다음 주소로 갈 수 있습니다:

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

나는 이 논리의 가장 중요한 부분이 무엇인지 분리하고 원하는 대로 수행할 수 있는 두 가지 방법으로 통합했습니다.내 목적을 위해 나는 이것을 내가 원하는 대로 수행할 수 있는 Decimal 값을 반환하는 것으로 두기로 선택했습니다.기본적으로 이 메서드는 "unpack"이라고 하며 이를 byte[] 배열(12바이트 이하)과 소수점 이하 자릿수인 int로 전달합니다. 이는 Decimal 값으로 반환하려는 소수 자릿수입니다.이것이 나에게 그랬던 것처럼 당신에게도 효과가 있기를 바랍니다.

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

질문이 있으면 여기에 게시하세요. 오늘 문제와 관련된 질문을 게시하기로 선택한 다른 모든 사람들처럼 저도 "불타오르게" 될 것이라고 생각하기 때문입니다...

고마워요, 존 - 장로.

원래 데이터가 EBCDIC에있는 경우 COMP-3 필드가 차가워졌습니다. FTP 프로세스는 COMP-3 필드에서 바이트 값의 ASCII 변환을 수행했습니다. 이를 수정하려면 다음과 같습니다.

1) 전송에 이진 모드를 사용하여 원시 EBCDIC 데이터를 얻으십시오. 그런 다음 COMP-3 필드를 숫자로 변환하고 레코드의 다른 EBCDIC 텍스트를 ASCII로 변환합니다. 포장 된 필드는 각각 반 바이트로 각 자리를 저장합니다. 하반부 바이트는 부호로서 (F는 양수이고 다른 값, 일반적으로 d 또는 e는 음수입니다). PIC 999.99 사용 COMP -3에 123.4를 저장하는 것은 X'01234F '(3 바이트)이고 동일한 필드에서 -123은 X'01230D'입니다.

2) 발신자가 필드를 사용법으로 전환하도록합니다. 이것은 숫자를 EBCDIC 숫자 숫자의 문자열로 저장하여 부호를 별도의 음수 (-) 또는 빈 문자로 사용합니다. 모든 숫자와 부호는 FTP 전송에서 ASCII와 동등한 ASCII로 올바르게 변환됩니다.

여기에 기본이되면 사과 드리지만 아마도 여기에 붙여 넣을 수있는이 코드 샘플이 도움이 될 수 있습니다. 이것은 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

EBCDIC 번역을위한 유용한 링크 :

번역 테이블 - 포장 된 소수점 필드의 일부 값을 확인하는 데 유용합니다.http://www.simotime.com/asc2ebc1.htm

MSDN의 코드 페이지 목록 :
http://msdn.microsoft.com/en-us/library/dd317756(vs.85).aspx

그리고 C#에서 바이트 배열 필드를 변환하는 코드 조각 :

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

포장 필드는 EBCDIC 또는 ASCII에서 동일합니다. EBCDIC에서 ASCII 변환을 실행하지 마십시오. .NET에서 바이트 []에 덤프하십시오.

Bitwise 마스크와 교대를 사용하여 포장/포장을 풀습니다. - 그러나 Bitwise OPS는 .NET의 정수 유형에만 적용되므로 일부 후프를 뛰어 넘어야합니다!

좋은 Cobol 또는 C 아티스트가 올바른 방향을 가리킬 수 있습니다.

노인 중 한 명을 찾아 회비를 지불하십시오 (약 3 마리의 맥주가해야합니다).

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top