2010-05-18 17 views
9

Tengo un valor en formato EBCDIC "000000 {". Quiero convertirlo en un tipo .Net Int32. ¿Alguien me puede decir qué puedo hacer al respecto? Entonces mi pregunta recibe una cadena que contiene un número firmado en EBCDIC, ¿qué debo hacer para convertirlo en .NET Int32?Cómo convertir de EBCDIC a ASCII en C# .net

¡Muchas gracias de antemano!

+1

Bastante mal el título; esta pregunta no tiene ninguna relación con ASCII. – Nyerguds

Respuesta

1

En general, debería poder cargar datos EBCDIC utilizando la clase correcta System.Text.Encoding (el enlace apunta a una lista de todas las codificaciones, que incluye codificaciones EBCDIC). La cadena es entonces Unicode en la memoria y se puede guardar en ASCII utilizando la codificación ASCII.

Esto hace lo que pide en el título de la pregunta. Sin embargo, no estoy seguro de si esto es lo que quería saber, ya que su pregunta no está del todo clara para mí. Si está buscando el código de carácter ASCII, puede simplemente convertir el carácter en int, siempre que sean caracteres ASCII solamente.

+0

Su sugerencia sería correcta y bastante correcta para los datos de caracteres, pero desafortunadamente no es nada bueno para los datos numéricos, ya que cambiaría los números con la nueva asignación de caracteres. – ewall

+0

@ewall, gracias por la aclaración.No estoy familiarizado con EBCDIC en sí, pero sabía que había codificaciones para él en el marco. Es también por eso que escribí el párrafo inferior sobre no estar seguro de si esto realmente responde a la pregunta en cuestión. Mientras el título no se modifique, dejaré aquí mi respuesta para otros que están buscando la conversión de caracteres EBCDIC y me encontraré con esta pregunta, pero me complacerá eliminarla cuando el título y el texto de la pregunta sean más claros. – Lucero

+0

De hecho, es una gran respuesta para la conversión entre las codificaciones de caracteres. – ewall

0

Try siguiente función ..

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

No, eso no funcionará. Si lee la pregunta con más cuidado, Sai necesita obtener datos numéricos (un entero) de la matriz de bytes. Convertirlo de EBDIC a ASCII cambiaría los números. – ewall

3

vas a querer leer sobre binary-coded decimals, ya que es lo que se enfrentan, y hay preguntas que responder antes de que realmente puede codificarlo.

Si el valor es un solo carácter, puede ser tan simple como obtener el número de char, pero necesita saber si el sistema es Big Endian (como la mayoría de los mainframes de los que obtendría archivos codificados con EBDIC) o Little Endian (como sistemas operativos más modernos).

Si su valor entero usa más de un carácter e incluye el signo (como usted menciona), entonces es más complejo. Lo más probable es que cada mitad (o "mordisco", o 4 bits) de cada personaje represente el número, tal vez 0 a 9 o en hex 0 a F, y la cadena se rellena con ceros (nulos, en realidad) a la izquierda, y el último mordisco contiene el signo. Este sistema podría llamarse Zoned Decimal en algún lenguaje.

En general, recomendaría comenzar por reading this article, which should introduce you to how data is/was stored on COBOL-based mainframes, y hacerlo avanzar en la dirección correcta.


En C#, puede ser capaz de hacer la conversión formar el Zonal decimal común (que suena como el mejor ajuste para los datos entrantes como usted ha descrito) mediante el uso de int.Parse with the correct NumberStyles options, así:

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

(Por cierto, todavía estoy buscando código de ejemplo en C#, ya que los ejemplos que tengo están todos en Java.) – ewall

4

El siguiente programa ha funcionado para convertir un valor EBCDIC a un número entero, al recibir datos de uno de nuestros clientes. Los datos que obtenemos puede ser un subconjunto de lo que se podría conseguir, por lo que ver si esto funciona para usted:

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

Esta solución realmente maneja los valores EBCDIC de over-punch. – lukevp

19

probar este

#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 porque la pregunta estaba relacionada con un valor numérico de sobredup del EBCDIC, no con texto codificado EBCDIC. La respuesta proporcionada por Simon es el manejo correcto para estos campos. – lukevp

+0

Upvoted porque me ayudó – coloboxp

0

Estos son los métodos de extensión y unidad de prueba que utilizamos:

/// <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); 
     } 
    } 
} 
Cuestiones relacionadas