2010-05-18 12 views
9

EBCDIC biçiminde "000000 {" değeri var. Bunu bir intima Int32 türüne dönüştürmek istiyorum. Bu konuda neler yapabileceğimi bilen var mı? Bu yüzden soruma EBCDIC'de imzalı bir sayısal içeren bir dize verildi, bunu .NET Int32'ye dönüştürmek için ne yapmalıyım?EBCDIC'den ASCII'ye nasıl dönüştürülür C# .net

Şimdiden çok teşekkürler!

+1

Oldukça kötü bir başlık; Bu soru ASCII ile tamamen ilgisiz. – Nyerguds

cevap

1

Genel olarak EBCDIC verilerini doğru System.Text.Encoding sınıfını kullanarak yükleyebilmeniz gerekir (bağlantı, EBCDIC kodlamaları içeren tüm kodlamaların bir listesini gösterir). Dize sonra bellekte Unicode ve ASCII kodlaması kullanılarak ASCII'ye kaydedilebilir.

Bu, sorunun başlığında istediğini yapar. Ancak, sormak istediğin şeyin bu olduğundan emin değilim, çünkü sorunuz bana tamamen açık değil. ASCII karakter kodunu arıyorsanız, karakteri yalnızca ASCII karakterleri olduğu sürece int'a atayabilirsiniz. fonksiyonu aşağıdaki

+0

Öneriniz, karakter verisi için tamam ve oldukça doğru olur, ancak rakamlar yeni karakter eşleştirmesiyle değişeceğinden, sayısal veriler için her şey iyi değildir. – ewall

+0

@ewall, açıklama için teşekkürler.EBCDIC'in kendisiyle aşina değilim, ancak çerçevede bunun için kodlamalar olduğunu biliyordum. Bu aynı zamanda, bu sorunun cevabını verdiğinden emin olmamak için alt paragrafı da yazdım. Başlık değişmeden kaldığı sürece cevabımı EBCDIC karakter dönüşümü arayan ve bu soruyla karşılaşan diğer kişiler için burada bırakacağım, ancak başlık ve soru metni daha net olduğunda onu silmek için mutlu olacağım. – Lucero

+0

Gerçekten de, karakter kodlamaları arasında dönüştürme yapmak için harika bir yanıt. – ewall

0

deneyin ..

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

Hayır, işe yaramadı. Soruyu daha dikkatli okursanız, Sai'nin bayt dizisinden sayısal veri (bir tamsayı) alması gerekir. EBDIC'den ASCII'ye dönüştürme sayıları değiştirecektir. – ewall

3

Bunu karşılaştığınız ne gibi binary-coded decimals hakkında bilgi edinmek istiyorum gidiyoruz, ve gerçekten bu kodu önce cevap sorular vardır.

Değer tek bir karakterse, karakter numarası almak kadar basit olabilir - ancak sistemin Big Endian olup olmadığını bilmeniz gerekir (EBDIC kodlu dosyaları alacağınız çoğu ana çerçeve gibi). veya Küçük Endian (daha modern OS'ler gibi).

Eğer tamsayı değeriniz birden fazla karakter kullanıyorsa ve işaretini (söz ettiğiniz gibi) içeriyorsa, daha karmaşıktır. Büyük olasılıkla, her bir karakterin her bir yarısı (veya "nibble", veya 4 bit) sayıyı gösterir - belki 0'dan 9'a veya hex 0'dan F'ye, ve dize solda sıfırlar (gerçekte null'lar) ile doldurulur. ve son nibble işareti içerir. Bazı sistemlerde bu sistem Zoned Decimal olarak adlandırılabilir.

Sonuç olarak, reading this article, which should introduce you to how data is/was stored on COBOL-based mainframes ile başlamanızı öneririm ve doğru yönü değiştirmenizi öneririm. Bu gibi int.Parse with the correct NumberStyles options kullanarak (bunu tarif ettiğim gelen veriler için en iyi seçim gibi görünüyorsa)

C# '

, ortak Zoned ondalık formu dönüşüm yapmak mümkün olabilir:

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

(BTW, C# içinde örnek kodu arıyorum, çünkü sahip olduğum örnekler Java'da.) – ewall

4

Aşağıdaki program, müşterilerimizden birinden veri alırken EBCDIC değerini tamsayıya dönüştürmek için çalışmıştır.

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

Bu çözüm aslında EBCDIC over-punch değerlerini işliyor. – lukevp

19

Bunlar kullandığımız uzatma yöntemleri ve birim test olan bu

#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

Düşündüğüm soru, EBCDIC kodlanmış metin değil, EBCDIC over-punch sayısal değeriyle ilişkiliydi. Simon tarafından sağlanan cevap, bu alanlar için doğru yoldur. – lukevp

+0

Atanan bana yardımcı oldu – coloboxp

0

deneyin: bu sizin için çalışıyorsa aldığımız verileri ne elde edebileceğiniz bir alt kümesi olabilir, bu yüzden görebilirsiniz:

/// <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); 
     } 
    } 
} 
İlgili konular