2010-05-18 93 views
9

Tôi có một giá trị theo định dạng EBCDIC "000000 {". Tôi muốn chuyển đổi nó thành a.Net Int32 loại. Có ai cho tôi biết tôi có thể làm gì không? Vì vậy, câu hỏi của tôi được đưa ra một chuỗi có chứa một chữ ký số trong EBCDIC, tôi nên làm gì để chuyển đổi nó thành một Int32. NET.Cách chuyển đổi từ EBCDIC sang ASCII trong C# .net

Cảm ơn bạn rất nhiều trước!

+1

Tiêu đề khá xấu; câu hỏi này hoàn toàn không liên quan đến ASCII. – Nyerguds

Trả lời

1

Nói chung, bạn có thể tải dữ liệu EBCDIC sử dụng đúng lớp System.Text.Encoding (liên kết trỏ tới danh sách tất cả các mã hóa, bao gồm mã hóa EBCDIC). Chuỗi này sau đó là Unicode trong bộ nhớ và có thể được lưu vào ASCII bằng cách sử dụng mã hóa ASCII.

Điều này làm những gì bạn yêu cầu trong tiêu đề của câu hỏi. Tuy nhiên, tôi không chắc đây có phải là điều bạn muốn biết hay không, vì câu hỏi của bạn không hoàn toàn rõ ràng với tôi. Nếu bạn đang tìm mã ký tự ASCII, bạn chỉ có thể truyền ký tự đến một số int miễn là chúng chỉ là các ký tự ASCII.

+0

Đề xuất của bạn sẽ ổn và khá chính xác cho dữ liệu ký tự, nhưng không phải tất cả đều tốt cho dữ liệu số, vì nó sẽ thay đổi các số có ánh xạ ký tự mới. – ewall

+0

@ewall, cảm ơn bạn đã làm rõ.Tôi không quen với EBCDIC, nhưng tôi biết rằng đã có mã hóa cho nó trong khuôn khổ. Đó cũng là lý do tại sao tôi đã viết đoạn cuối về việc không chắc chắn liệu điều này có thực sự trả lời câu hỏi trong tầm tay không. Miễn là tiêu đề không thay đổi, tôi sẽ để lại câu trả lời ở đây cho những người khác đang tìm kiếm chuyển đổi ký tự EBCDIC và xem qua câu hỏi này, nhưng tôi sẽ vui lòng xóa nó khi tiêu đề và văn bản câu hỏi rõ ràng hơn. – Lucero

+0

Thật vậy, nó là một câu trả lời tuyệt vời để chuyển đổi giữa các mã hóa ký tự. – ewall

0

Hãy thử chức năng sau ..

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

Không, điều đó sẽ không hoạt động. Nếu bạn đọc câu hỏi cẩn thận hơn, Sai cần lấy dữ liệu số (số nguyên) ra khỏi mảng byte. Chuyển đổi nó từ EBDIC sang ASCII sẽ thay đổi số. – ewall

3

Bạn sẽ muốn đọc lên trên binary-coded decimals, vì đó là những gì bạn đang phải đối mặt, và có những câu hỏi để trả lời trước khi bạn thực sự có thể mã hóa nó.

Nếu giá trị là một ký tự đơn, nó có thể đơn giản như nhận số char - nhưng bạn cần biết liệu hệ thống có phải là Big Endian hay không (giống như hầu hết các máy tính lớn mà bạn sẽ nhận các tệp được mã hóa EBDIC) hoặc Little Endian (giống như hệ điều hành hiện đại hơn).

Nếu giá trị số nguyên của bạn sử dụng nhiều hơn một ký tự và bao gồm dấu (như bạn đề cập), thì nó phức tạp hơn. Nhiều khả năng, mỗi nửa (hoặc "nibble", hoặc 4 bit) của mỗi ký tự đại diện cho số - có thể 0 đến 9 hoặc trong hex 0 qua F, và chuỗi được đệm với số không (nulls, thực sự) ở bên trái, và nibble cuối cùng chứa dấu. Hệ thống này có thể được gọi là Zoned Decimal theo cách nói nào đó.

Tất cả trong tất cả, tôi khuyên bạn nên bắt đầu bằng reading this article, which should introduce you to how data is/was stored on COBOL-based mainframes và giúp bạn di chuyển đúng hướng.


Trong C#, bạn có thể thực hiện chuyển đổi hình thức phổ biến qui vùng Decimal (mà có vẻ như phù hợp nhất cho dữ liệu đến bạn như bạn đã mô tả nó) bằng cách sử dụng int.Parse with the correct NumberStyles options, như thế này:

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

(BTW, tôi vẫn đang tìm mã ví dụ trong C#, vì các ví dụ tôi có tất cả đều bằng Java.) – ewall

4

Chương trình sau đây đã làm việc để chuyển đổi giá trị EBCDIC thành số nguyên, khi nhận dữ liệu từ một trong các khách hàng của chúng tôi. Các dữ liệu chúng tôi có được có thể là một tập hợp con của những gì bạn có thể nhận được, vì vậy xem nếu công trình này dành cho bạn:

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

Giải pháp này thực sự xử lý các giá trị over-punch EBCDIC. – lukevp

19

Hãy thử điều này

#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

Bị bỏ qua vì câu hỏi có liên quan đến giá trị số EBCDIC over-punch, chứ không phải văn bản được mã hóa EBCDIC. Câu trả lời được cung cấp bởi Simon là xử lý chính xác cho các lĩnh vực này. – lukevp

+0

Được thăng hạng vì nó đã giúp tôi – coloboxp

0

Đây là những phương pháp mở rộng và thử nghiệm đơn vị mà chúng ta sử dụng:

/// <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); 
     } 
    } 
} 
Các vấn đề liên quan