Tag Archive for case-sensitivity

איך לשמור על אותיות גדולות וקטנות בעולם עוין

כמתכנת C#, אני רגיל לחשיבות של case sensitivity – משתנים בשם test ו-TEST הם שונים ונפרדים. גם ב-XML וב-JSON, שני הפורמטים הנפוצים לתעבורת מידע, נהוג להקפיד על case sensitivity בשמות של השדות/אלמנטים. ולרוב זה לא בעיה – אתה שומר עם case מסוים ואז קורא באותו case, והכל בסדר.

אבל היום נתקלתי בבעיה. במערכת מורכבת ומבוזרת שעליה אני עובד, מידע מעובד בקצה אחד, שדות נשמרים, והישות כולה נשמרת בתוך מסד נתונים מסוים, כשכל ערכי השדות שלה נשמרים תמיד ב-UPPERCASE. אבל היום הייתי צריך לשמור בתוך כמה שדות מידע שה-case שלו היה חשוב לשימור – במקרה הזה, שם קובץ מתוך שרת לינוקס עם מערכת קבצים רגישה ל-case, ובלוק של XML שגם בו הייתי חייב לשמור על גודל האותיות. אבל המנגנון היחיד שהיה לי לשמור את המידע בשביל להוציא אותו ולפעול עליו בקצה השני של המערכת לא משמר את ה-case של הנתונים. אז מה עושים?

המחשבה הראשונה שלי היתה לקודד את המידע ב-Base64, שמאפשר לקדד מידע שרירותי לתוך “שפה” של 64 תווים בלבד. אבל גם זו שפה גדולה מדי, וכוללת גם אותיות קטנות וגם גדולות, כך ש-Base64 הוא case sensitive גם הוא. אז השלב הבה היה לקודד את המידע לשפה “רזה” יותר, שאין בה את ההפרדה הזו בין אותיות גדולות וקטנות.

האופציה הבאה שלי היתה Base32 או Base36. שתיהן שיטות קידוד דומות ל-base64, אם כי פחות סטנדרטיות. הן לא case sensitive, שזה טוב, אבל בגלל שהן לא שיטת קידוד נפוצה, אין ב-.NET Framework תמיכה מובנית בהן, כמו שיש ל-base64. אפשר למצוא לא מעט מימושים, כמו כאן או כאן, אבל במקרה הזה לא רציתי להכניס קוד לא ידוע או ארוך מדי למערכת ברגע האחרון, למרות שברגע שירגע המצב קצת, יתכן שאחזור אליו.

אז האופציה הבאה אחרי כן היא פשוט לקודד את ה-bytes של הטקסט שלי כצמדי תווים הקסדצימליים – זו המרה די ישירה, ודרך די נפוצה להציג שטחי זכרון גולמיים. החסרון של זה הוא שזו שיטה בזבזנית הרבה יותר מ-base36 (שלא לומר base64), כי את אותו כמות מידע תדרוש יותר תווים באלף-בית ההקסדצימלי – שאפשר גם לכנות אותו base16 – מאשר בבסיסים הגדולים יותר. אבל היתרון הגדול הוא שיש כבר בתוך ה-framework דרך לעשות את ההמרה אוטומטית, מה שהופך את זמן הפיתוח – ובעיקר הבדיקות – לקצרצר הרבה יותר. אמנם המימוש הוא במחלקה קצת נידחת כחלק מהתמיכה ב-SOAP, אבל הוא שם, והוא נתמך מאז .NET 1.1 ב-2003. ועם האפשרות לכתוב את זה כ-extension method, אז השימוש בכלל נהיה קל מאד.

public static string ToHexBytes(this string plainText,
     Encoding encoding = null)
{
    encoding = encoding ?? Encoding.UTF8;
    var bytes = encoding.GetBytes(plainText);
    return new SoapHexBinary(bytes).ToString();
}

public static string FromHexBytes(this string hexText,
    Encoding encoding = null)
{
    encoding = encoding ?? Encoding.UTF8;
    var bytes = SoapHexBinary.Parse(hexText).Value;
    return encoding.GetString(bytes);
}