// -----------------------------------------------------------------------
//
// By: MOHSEN DORPARASTI - 1391
//
// -----------------------------------------------------------------------
namespace _0_Framework.Application;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
public enum TextEncoding
{
Arabic1256 = 1256,
CP1252 = 1252
}
public static class ConvertTo
{
#region private Members (3)
// متغیری برای نگهداری اعدادی که در رشته ایران سیستم وجود دارند
static Stack NumbersInTheString;
// کد کاراکترها در ایران سیستم و معادل آنها در عربی 1256
static Dictionary CharactersMapper = new Dictionary
{
{128,48}, // 0
{129,49}, // 1
{130,50}, // 2
{131,51}, // 3
{132,52}, // 4
{133,53}, // 5
{134,54}, // 6
{135,55}, // 7
{136,56}, // 8
{137,57}, // 9
{138,161}, // ،
{139,220}, // -
{140,191}, // ؟
{141,194}, // آ
{142,196}, // ﺋ
{143,154}, // ء
{144,199}, // ﺍ
{145,199}, // ﺎ
{146,200}, // ﺏ
{147,200}, // ﺑ
{148,129}, // ﭖ
{149,129}, // ﭘ
{150,202}, // ﺕ
{151,202}, // ﺗ
{152,203}, // ﺙ
{153,203}, // ﺛ
{154,204}, //ﺝ
{155,204},// ﺟ
{156,141},//ﭼ
{157,141},//ﭼ
{158,205},//ﺡ
{159,205},//ﺣ
{160,206},//ﺥ
{161,206},//ﺧ
{162,207},//د
{163,208},//ذ
{164,209},//ر
{165,210},//ز
{166,142},//ژ
{167,211},//ﺱ
{168,211},//ﺳ
{169,212},//ﺵ
{170,212},//ﺷ
{171,213},//ﺹ
{172,213},//ﺻ
{173,214},//ﺽ
{174,214},//ﺿ
{175,216},//ط
{224,217},//ظ
{225,218},//ﻉ
{226,218},//ﻊ
{227,218},//ﻌ
{228,218},//ﻋ
{229,219},//ﻍ
{230,219},//ﻎ
{231,219},//ﻐ
{232,219},//ﻏ
{233,221},//ﻑ
{234,221},//ﻓ
{235,222},//ﻕ
{236,222},//ﻗ
{237,152},//ﮎ
{238,152},//ﮐ
{239,144},//ﮒ
{240,144},//ﮔ
{241,225},//ﻝ
{242,225},//ﻻ
{243,225},//ﻟ
{244,227},//ﻡ
{245,227},//ﻣ
{246,228},//ﻥ
{247,228},//ﻧ
{248,230},//و
{249,229},//ﻩ
{250,229},//ﻬ
{251,170},//ﻫ
{252,236},//ﯽ
{253,237},//ﯼ
{254,237},//ﯾ
{255,160} // فاصله
};
///
/// لیست کاراکترهایی که بعد از آنها باید یک فاصله اضافه شود
///
static byte[] charactersWithSpaceAfter = {
146, // ب
148, // پ
150, // ت
152, // ث
154, // ج
156, // چ
158, // ح
160, // خ
167, // س
169, // ش
171, // ص
173, // ض
225, // ع
229, // غ
233, // ف
235, // ق
237, // ک
239, // گ
241, // ل
244, // م
246, // ن
249, // ه
252, //ﯽ
253 // ی
};
#endregion
///
/// تبدیل یک رشته ایران سیستم به یونیکد با استفاده از عربی 1256
///
/// رشته ایران سیستم
///
[Obsolete("بهتر است از UnicodeFrom استفاده کنید")]
public static string Unicode(string iranSystemEncodedString)
{
return UnicodeFrom(TextEncoding.Arabic1256, iranSystemEncodedString);
}
///
/// تبدیل یک رشته ایران سیستم به یونیکد
///
/// کدپیج رشته ایران سیستم
/// رشته ایران سیستم
///
public static string UnicodeFrom(TextEncoding textEncoding, string iranSystemEncodedString)
{
// حذف فاصله های موجود در رشته
iranSystemEncodedString = iranSystemEncodedString.Replace(" ", "");
/// بازگشت در صورت خالی بودن رشته
if (string.IsNullOrWhiteSpace(iranSystemEncodedString))
{
return string.Empty;
}
// در صورتی که رشته تماماً عدد نباشد
if (!IsNumber(iranSystemEncodedString))
{
/// تغییر ترتیب کاراکترها از آخر به اول
iranSystemEncodedString = Reverse(iranSystemEncodedString);
/// خارج کردن اعداد درون رشته
iranSystemEncodedString = ExcludeNumbers(iranSystemEncodedString);
}
// وهله سازی از انکودینگ صحیح برای تبدیل رشته ایران سیستم به بایت
Encoding encoding = Encoding.GetEncoding((int)textEncoding);
// تبدیل رشته به بایت
byte[] stringBytes = encoding.GetBytes(iranSystemEncodedString.Trim());
// آرایه ای که بایت های معادل را در آن قرار می دهیم
// مجموع تعداد بایت های رشته + بایت های اضافی محاسبه شده
byte[] newStringBytes = new byte[stringBytes.Length + CountCharactersRequireTwoBytes(stringBytes)];
int index = 0;
// بررسی هر بایت و پیدا کردن بایت (های) معادل آن
for (int i = 0; i < stringBytes.Length; ++i)
{
byte charByte = stringBytes[i];
// اگر جز 128 بایت اول باشد که نیازی به تبدیل ندارد چون کد اسکی است
if (charByte < 128)
{
newStringBytes[index] = charByte;
}
else
{
// اگر جز حروف یا اعداد بود معادلش رو قرار می دیم
if (CharactersMapper.ContainsKey(charByte))
{
newStringBytes[index] = CharactersMapper[charByte];
}
}
// اگر کاراکتر ایران سیستم "لا" بود چون کاراکتر متناظرش در عربی 1256 "ل" است و باید یک "ا" هم بعدش اضافه کنیم
if (charByte == 242)
{
newStringBytes[++index] = 199;
}
// اگر کاراکتر یکی از انواعی بود که بعدشان باید یک فاصله باشد
// و در عین حال آخرین کاراکتر رشته نبود
if (charactersWithSpaceAfter.Contains(charByte) && Array.IndexOf(stringBytes, charByte) != stringBytes.Length - 1)
{
// یک فاصله بعد ان اضافه می کنیم
newStringBytes[++index] = 32;
}
index += 1;
}
// تبدیل به رشته و ارسال به فراخواننده
byte[] unicodeContent = Encoding.Convert(encoding, Encoding.Unicode, newStringBytes);
string convertedString = Encoding.Unicode.GetString(unicodeContent).Trim();
return IncludeNumbers(convertedString);
}
#region Private Methods (4)
///
/// رشته ارسال شده تنها حاوی اعداد است یا نه
///
///
///
static bool IsNumber(string str)
{
return Regex.IsMatch(str, @"^[\d]+$");
}
///
/// محاسبه تعداد کاراکترهایی که بعد از آنها یک کاراکتر باید اضافه شود
/// شامل کاراکتر لا
/// و کاراکترهای غیرچسبان تنها در صورتی که کاراکتر پایانی رشته نباشند
///
///
///
static int CountCharactersRequireTwoBytes(byte[] irTextBytes)
{
return (from b in irTextBytes
where (
charactersWithSpaceAfter.Contains(b) // یکی از حروف غیرچسبان باشد
&& Array.IndexOf(irTextBytes, b) != irTextBytes.Length - 1) // و کاراکتر آخر هم نباشد
|| b == 242 // یا کاراکتر لا باشد
select b).Count();
}
///
/// خارج کردن اعدادی که در رشته ایران سیستم قرار دارند
///
///
///
static string ExcludeNumbers(string iranSystemString)
{
/// گرفتن لیستی از اعداد درون رشته
NumbersInTheString = new Stack(Regex.Split(iranSystemString, @"\D+"));
/// جایگزین کردن اعداد با یک علامت جایگزین
/// در نهایت بعد از تبدیل رشته اعداد به رشته اضافه می شوند
return Regex.Replace(iranSystemString, @"\d+", "#");
}
///
/// اضافه کردن اعداد جدا شده پس از تبدیل رشته
///
///
///
static string IncludeNumbers(string convertedString)
{
while (convertedString.IndexOf("#") >= 0)
{
string number = Reverse(NumbersInTheString.Pop());
if(!string.IsNullOrWhiteSpace(number))
{
int index = convertedString.IndexOf("#");
convertedString = convertedString.Remove(index, 1);
convertedString = convertedString.Insert(index, number);
}
}
return convertedString;
}
static string Reverse(string s)
{
char[] charArray = s.ToCharArray();
Array.Reverse(charArray);
return new string(charArray);
}
#endregion
}