11
votes

Comment convertir de l'EBCDIC en ASCII en C # .NET

J'ai une valeur au format EBCDIC "000000 {". Je veux le convertir en type A.net Int32. Quelqu'un peut-il me dire ce que je peux faire à ce sujet ?? Donc, ma question reçoive une chaîne qui contient un numérique signé dans EBCDIC, que dois-je faire pour la convertir en un .NET INT32.

Merci beaucoup d'avance!


1 commentaires

Assez mauvais titre; Cette question est totalement sans rapport avec ASCII.


7 Réponses :


1
votes

En règle générale, vous devriez pouvoir charger des données EBCDIC à l'aide du correct System.Text.Coding classe (le lien pointe vers une liste de tous les codages, qui comprend des codages EBCDIC). La chaîne est alors unicode en mémoire et peut être sauvegardée en ASCII à l'aide du codage ASCII.

Cela fait ce que vous demandez dans le titre de la question. Cependant, je ne suis pas sûr de savoir si c'est ce que vous vouliez savoir, car votre question n'est pas complètement claire pour moi. Si vous recherchez le code de caractères ASCII, vous pouvez simplement lancer le caractère à un int tant qu'ils sont des caractères ASCII uniquement.


3 commentaires

Votre suggestion irait bien et bien correcte pour les données de caractères, mais il n'est pas du tout bon pour les données numériques, car cela modifierait les chiffres avec le nouveau mappage de caractères.


@ewall, merci pour la clarification. Je ne connais pas l'Ebcdic lui-même, mais je savais qu'il y avait des codages pour cela dans le cadre. C'est aussi pourquoi j'ai écrit le paragraphe inférieur sur ne pas être sûr que cela réponde à la question à la main. Tant que le titre est laissé inchangé, je quitterai ma réponse ici pour d'autres personnes qui recherchent une conversion de personnage EBCDIC et surviennent à cette question, mais je serai heureux de le supprimer lorsque le texte et le texte de la question sont plus clairs.


En effet, c'est une bonne réponse pour la conversion entre les codages de caractères.



0
votes

essayer la fonction suivante .. xxx


1 commentaires

Non, ça ne fonctionnera pas. Si vous lisez la question plus attentivement, SAI doit obtenir des données numériques (un entier) hors du réseau d'octets. La conversion de EBDIC à ASCII changerait les chiffres.



3
votes

Vous allez vouloir lire sur Décimales codées binaires , Comme c'est ce que vous êtes confronté et qu'il y a des questions à répondre avant de pouvoir le coder.

Si la valeur est un seul caractère, il peut être aussi simple que d'obtenir le numéro de caractère - mais vous devez savoir si Le système est grand Endian (comme la plupart des personnages principaux à partir desquels vous obtiendriez des fichiers codés EBDIC) ou un peu d'Endian (comme des OSE plus modernes). p>

Si votre valeur entière utilise plus d'un caractère et comprend le signe (Comme vous le mentionez), alors il est plus complexe. Très probablement, chaque moitié (ou "Nibble", ou 4 bits) de chaque caractère représente le nombre - peut-être 0 à 9 ou en hexagonal 0 à F, et la chaîne est rembourrée de zéros (nulls, en fait) à gauche, et le dernier nibble contient le signe. Ce système peut être appelé ZONED Decimal dans certaines langues. P>

Tout dans Tout, je vous recommanderais de commencer par lire cet article, qui devrait introduire à la manière dont les données sont / ont été stockées sur les ordinateurs de mainframes basés sur COBOL et vous permettent de déplacer la bonne direction. P>


en C #, vous pourrez peut-être effectuer la forme de conversion la forme commune Decimal zoné (qui sonne comme le meilleur ajustement pour vos données entrantes, comme vous l'avez décrit) en utilisant INT.PARSE avec les options de numéros de numéros correctes , comme ceci: p>

int val = int.Parse(num, NumberStyles.AllowLeadingWhite | NumberStyles.AllowTrailingWhite);


1 commentaires

(BTW, je suis toujours à la recherche d'exemple de code dans C #, puisque les exemples que j'ai sont tous en Java.)



4
votes

Le programme suivant a fonctionné pour convertir une valeur EBCDIC en un entier, lors de la réception de données d'un de nos clients. Les données que nous obtenons peuvent être un sous-ensemble de ce que vous pourriez obtenir, alors voyez si cela fonctionne pour vous:

using System;
using System.Text;

namespace ConsoleApplication6
{
    class Program
    {
        static void Main(string[] args)
        {
            string strAmount = "00007570{";
            Console.WriteLine("{0} is {1}", strAmount, ConvertEBCDICtoInt(strAmount));
            strAmount = "000033}";
            Console.WriteLine("{0} is {1}", strAmount, ConvertEBCDICtoInt(strAmount));
            Console.ReadLine();
        }

        // This converts "00007570{" into "75700", and "000033}" into "-330"
        public static int? ConvertEBCDICtoInt(string i_strAmount)
        {
            int? nAmount = null;

            if (string.IsNullOrEmpty(i_strAmount))
                return(nAmount);

            StringBuilder strAmount = new StringBuilder(i_strAmount);
            if (i_strAmount.IndexOfAny(new char[] { '}', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R' }) >= 0)
                strAmount.Insert(0, "-");

            strAmount.Replace("{", "0");
            strAmount.Replace("}", "0");
            strAmount.Replace("A", "1");
            strAmount.Replace("J", "1");
            strAmount.Replace("B", "2");
            strAmount.Replace("K", "2");
            strAmount.Replace("C", "3");
            strAmount.Replace("L", "3");
            strAmount.Replace("D", "4");
            strAmount.Replace("M", "4");
            strAmount.Replace("E", "5");
            strAmount.Replace("N", "5");
            strAmount.Replace("F", "6");
            strAmount.Replace("O", "6");
            strAmount.Replace("G", "7");
            strAmount.Replace("P", "7");
            strAmount.Replace("H", "8");
            strAmount.Replace("Q", "8");
            strAmount.Replace("I", "9");
            strAmount.Replace("R", "9");

            // Convert the amount to a int:
            int n;
            if (int.TryParse(strAmount.ToString(), out n))
                nAmount = n;
            return (nAmount);
        }
    }
}


1 commentaires

Cette solution gère réellement les valeurs de sur-perforation EBCDIC.



26
votes

Essayez ceci xxx


1 commentaires

Downvoted Parce que la question était liée à une valeur numérique OverR-Punch EBCDIC, pas de texte codé EBCDIC. La réponse fournie par Simon est la bonne gestion de ces champs.



1
votes

Ce sont les méthodes d'extension et le test d'unité que nous utilisons:

    /// <summary>
    /// parses a signed or unsigned decimal in EBCDIC format int an integer
    /// </summary>
    /// <param name="value"></param>
    /// <returns></returns>
    private static int? FromZonedDecimalString(this string value)
    {
        var trimmed = ("" + value).Trim();
        if (trimmed.Length == 0)
            return null;

        int testValue;
        if (Int32.TryParse(trimmed, out testValue))
            return testValue;

        var lastChar = Convert.ToChar(trimmed.Substring(trimmed.Length - 1, 1));
        var result = 0;

        if (trimmed.Length > 1)
            result = Int32.Parse(trimmed.Substring(0, trimmed.Length - 1)) * 10;

        switch (lastChar)
        {
            case '{':
                return result;
            case '}':
                return -1 * result;
            default:
                if (lastChar >= 'A' && lastChar <= 'I')
                    return result + lastChar - 'A' + 1;
                if (lastChar >= 'J' && lastChar <= 'R')
                    return (result + lastChar - 'J' + 1) * -1;
                if (lastChar >= '0' && lastChar <= '9')
                    return (result + lastChar - '0' + 1) * -1;
                break;
        }
        return null;
    }

    /// <summary>
    /// converts an integer value into zoned signed EBCDIC decimal format
    /// </summary>
    /// <param name="value"></param>
    /// <returns></returns>
    public static string ToZonedSignedDecimalString(this int value)
    {
        var str = Math.Abs(value).ToString();
        str = str.Substring(0, str.Length - 1);
        var lastDigit = Math.Abs(value % 10);

        if (value < 0)
        {
            if (lastDigit == 0) return str + "}";
            if (lastDigit == 1) return str + "J";
            if (lastDigit == 2) return str + "K";
            if (lastDigit == 3) return str + "L";
            if (lastDigit == 4) return str + "M";
            if (lastDigit == 5) return str + "N";
            if (lastDigit == 6) return str + "O";
            if (lastDigit == 7) return str + "P";
            if (lastDigit == 8) return str + "Q";
            if (lastDigit == 9) return str + "R";

            throw new NotSupportedException("If this throws, I'm at a loss. Last digit was: " + lastDigit);
        }

        if (lastDigit == 0) return str + "{";
        if (lastDigit == 1) return str + "A";
        if (lastDigit == 2) return str + "B";
        if (lastDigit == 3) return str + "C";
        if (lastDigit == 4) return str + "D";
        if (lastDigit == 5) return str + "E";
        if (lastDigit == 6) return str + "F";
        if (lastDigit == 7) return str + "G";
        if (lastDigit == 8) return str + "H";
        if (lastDigit == 9) return str + "I";

        throw new NotSupportedException("If this throws, I'm at a loss. Last digit was: " + lastDigit);
    }


[TestClass]
public class IntExtensionsTests
{
    [TestMethod]
    public void TestConversion()
    {
        string signedDecimalString;
        int convertedlValue;
        for (int i = -1000001; i <= 1000001; i++)
        {
            signedDecimalString = i.ToZonedSignedDecimalString();
            convertedlValue = signedDecimalString.ConvertRightSignedJustifySignedValueToInt();

            Assert.AreEqual(i, convertedlValue);
        }
    }
}


0 commentaires

1
votes

Cette question est assez ancienne, mais nous avons récemment rencontré le même problème. Il semble que certaines grandes institutions financières (je vous envisagent de la fidélité) utilisent toujours des systèmes de mainframe de vieille école que vous devez communiquer avec et ces systèmes s'attendent à une décimale zonée.

Le problème que j'ai trouvé avec d'autres réponses est qu'ils utilisent des opérations de manipulation de chaîne, qui sont lentes. Je mets ensemble une simple bibliothèque C # qui fait la conversion numériquement et la déposa sur GitHub. Vérifiez le lien ci-dessous pour une description approfondie du problème. J'ai inclus la mise en œuvre (actuelle dès maintenant) de la classe ZonedDecimalconverter.

zoné -Decimal sur github xxx


0 commentaires