2010-05-18 6 views
9

J'ai une valeur au format EBCDIC "000000 {". Je veux le convertir en type a.Net Int32. Quelqu'un peut-il me faire savoir ce que je peux faire à ce sujet ?? Donc, ma question est donnée une chaîne qui contient un numérique signé dans EBCDIC, que dois-je faire pour le convertir en .NET Int32.Comment convertir un EBCDIC en ASCII en C# .net

Merci beaucoup d'avance!

+1

Assez mauvais titre; cette question est complètement indépendante de l'ASCII. – Nyerguds

Répondre

1

De manière générale, vous devriez pouvoir charger des données EBCDIC en utilisant la bonne classe System.Text.Encoding (le lien pointe vers une liste de tous les encodages, qui inclut les codages EBCDIC). La chaîne est alors Unicode en mémoire et peut être sauvegardée en ASCII en utilisant le codage ASCII.

Ceci fait ce que vous demandez dans le titre de la question. Cependant, je ne suis pas sûr que ce soit ce que vous vouliez savoir, puisque votre question n'est pas entièrement claire pour moi. Si vous recherchez le code de caractère ASCII, vous pouvez simplement convertir le caractère en int tant que ce sont des caractères ASCII uniquement.

+0

Votre suggestion serait correcte et tout à fait correcte pour les données de caractères, mais hélas pas du tout bon pour les données numériques, car cela changerait les nombres avec le nouveau mapping de caractères. – ewall

+0

@ mur, merci pour la clarification.Je ne suis pas familier avec EBCDIC lui-même, mais je savais qu'il y avait des encodages pour cela dans le cadre. C'est aussi la raison pour laquelle j'ai écrit au bas du paragraphe que je ne savais pas si cela répondait à la question. Tant que le titre reste inchangé, je vais laisser ma réponse ici pour les autres qui recherchent la conversion de caractères EBCDIC et rencontrer cette question, mais je serai heureux de la supprimer lorsque le titre et le texte de la question seront plus clairs. – Lucero

+0

En effet, c'est une excellente réponse pour la conversion entre les encodages de caractères. – ewall

0

Essayez la fonction suivante ..

public string ConvertEBCDICtoASCII(string strEBCDICString) { 
    int[] e2a = new int[256]{ 
     0, 1, 2, 3,156, 9,134,127,151,141,142, 11, 12, 13, 14, 15, 
     16, 17, 18, 19,157,133, 8,135, 24, 25,146,143, 28, 29, 30, 31, 
     128,129,130,131,132, 10, 23, 27,136,137,138,139,140, 5, 6, 7, 
     144,145, 22,147,148,149,150, 4,152,153,154,155, 20, 21,158, 26, 
     32,160,161,162,163,164,165,166,167,168, 91, 46, 60, 40, 43, 33, 
     38,169,170,171,172,173,174,175,176,177, 93, 36, 42, 41, 59, 94, 
     45, 47,178,179,180,181,182,183,184,185,124, 44, 37, 95, 62, 63, 
     186,187,188,189,190,191,192,193,194, 96, 58, 35, 64, 39, 61, 34, 
     195, 97, 98, 99,100,101,102,103,104,105,196,197,198,199,200,201, 
     202,106,107,108,109,110,111,112,113,114,203,204,205,206,207,208, 
     209,126,115,116,117,118,119,120,121,122,210,211,212,213,214,215, 
     216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231, 
     123, 65, 66, 67, 68, 69, 70, 71, 72, 73,232,233,234,235,236,237, 
     125, 74, 75, 76, 77, 78, 79, 80, 81, 82,238,239,240,241,242,243, 
     92,159, 83, 84, 85, 86, 87, 88, 89, 90,244,245,246,247,248,249, 
     48, 49, 50, 51, 52, 53, 54, 55, 56, 57,250,251,252,253,254,255}; 

    char chrItem = Convert.ToChar("0"); 
    StringBuilder sb = new StringBuilder(); 
    for (int i = 0; i < strEBCDICString.Length; i++) { 
     try { 
      chrItem = Convert.ToChar(strEBCDICString.Substring(i, 1)); 
      sb.Append(Convert.ToChar(e2a[(int)chrItem])); 
     } catch (Exception ex) { 
      Console.WriteLine(ex.Message); 
      return string.Empty; 
     } 

    } 
    string result = sb.ToString(); 
    sb = null; 
    return result; 
} 
+1

Non, cela ne fonctionnera pas. Si vous lisez la question plus attentivement, Sai doit extraire des données numériques (un nombre entier) du tableau d'octets. La conversion d'EBDIC en ASCII changerait les nombres. – ewall

3

Vous allez vouloir lire sur binary-coded decimals, car c'est ce que vous faites face, et il y a des questions à répondre avant de pouvoir coder vraiment. Si la valeur est un seul caractère, il peut être aussi simple que d'obtenir le numéro de char - mais vous devez savoir si le système est Big Endian (comme la plupart des mainframes à partir desquels vous obtiendriez des fichiers encodés EBDIC) ou Little Endian (comme des systèmes d'exploitation plus modernes).

Si votre valeur entière utilise plus d'un caractère et inclut le signe (comme vous l'avez mentionné), alors il est plus complexe. Très probablement, chaque moitié (ou "grignoter", ou 4 bits) de chaque caractère représente le nombre - peut-être 0 à 9 ou dans hex 0 à F, et la chaîne est complétée avec des zéros (nulls, en fait) sur la gauche, et le dernier quart contient le signe. Ce système pourrait être appelé Zoned Decimal dans un certain jargon.

Dans l'ensemble, je recommanderais de commencer par reading this article, which should introduce you to how data is/was stored on COBOL-based mainframes, et de vous déplacer dans la bonne direction.


En C#, vous pourrez peut-être faire la conversion forme la Zoned commune décimal (qui sonne comme la meilleure solution pour vos données entrantes comme vous l'avez décrit) en utilisant int.Parse with the correct NumberStyles options, comme ceci:

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

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

4

Le programme suivant a fonctionné pour convertir une valeur EBCDIC en nombre entier, lors de la réception de données d'un de nos clients. Les données que nous obtenons peut-être un sous-ensemble de ce que vous pourriez obtenir, afin de voir 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); 
     } 
    } 
} 
+0

Cette solution gère réellement les valeurs de surexploitation EBCDIC. – lukevp

19

Essayez cette

#region public static byte[] ConvertAsciiToEbcdic(byte[] asciiData) 
    public static byte[] ConvertAsciiToEbcdic(byte[] asciiData)  
    {   
     // Create two different encodings.   
     Encoding ascii = Encoding.ASCII; 
     Encoding ebcdic = Encoding.GetEncoding("IBM037");   

     //Retutn Ebcdic Data 
     return Encoding.Convert(ascii, ebcdic, asciiData);  
    }  
    #endregion  

    #region public static byte[] ConvertEbcdicToAscii(byte[] ebcdicData) 
    public static byte[] ConvertEbcdicToAscii(byte[] ebcdicData) 
    {   
     // Create two different encodings.  
     Encoding ascii = Encoding.ASCII; 
     Encoding ebcdic = Encoding.GetEncoding("IBM037"); 

     //Retutn Ascii Data 
     return Encoding.Convert(ebcdic, ascii, ebcdicData); 
    } 
    #endregion 
+1

Downvoted car la question était liée à une valeur numérique EBCDIC over-punch, pas au texte codé EBCDIC. La réponse fournie par Simon est la manipulation correcte pour ces champs. – lukevp

+0

Upvoted parce que ça m'a aidé – coloboxp

0

Ce sont les méthodes d'extension et test unitaire 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); 
     } 
    } 
} 
Questions connexes