ממיר טקסט להקסדצימלי
המרת טקסט להקסדצימלי — הבייטים שלו ב־UTF-8 או ב־UTF-16, מופרדים ברווחים, כמערך, ברצפי בריחה או כדאמפ — והקסדצימלי בחזרה לטקסט מכל אחת מהצורות האלה.
D7 A9 D7 9C D7 95 D7 9D
מחרוזת כבייטים שבהם היא מאוחסנת
כל מחרוזת שתוכנית מטפלת בה היא מתחת לפני השטח שורה של בייטים, והעמוד הזה כותב אותם בהקסדצימלי, שתי ספרות לכל בייט. הקלידו Hello ותקבלו 48 65 6C 6C 6F, בייט אחד לכל אות ורווח אחרי כל אחד מהם מלבד האחרון. העבירו במקום זאת את הכיוון אל «הקסדצימלי לטקסט» והדביקו הקסדצימלי מלוג, ממסד נתונים או ממנפה שגיאות, ותקבלו בחזרה את הטקסט שהבייטים האלה מחזיקים.
אותו טקסט הוא בייטים שונים בקידודים שונים, והיחידה קובעת מה הן הספרות בעמוד הזה. היא מתחילה ב־UTF-8, הקידוד של הרשת, שבו H היא הבייט 48 ו־א היא הבייטים D7 90. גם ב־UTF-16 LE וגם ב־UTF-16 BE כל אחת מהן תופסת שני בייטים, בסדרים הפוכים — 48 00 או 00 48 עבור H — ואילו היחידה «נקודות קוד» מוותרת על בייטים לגמרי וכותבת את המספר שיוניקוד מקצה, U+05D0 עבור א. היחידה שנבחרה חלה על הקסדצימלי שאתם קוראים בדיוק כמו על טקסט שאתם כותבים, והיא נשארת כמו שהיא: אם הקסדצימלי שהודבק דומה לזה של יחידה אחרת, העמוד עשוי להציע אותה, אבל רק הלחיצה שלכם מזיזה אותה.
שתי ספרות הקסדצימליות לכל בייט
בייט מחזיק אחד מתוך 256 ערכים, מ־0 עד 255. בהקסדצימלי סופרים בבסיס שש־עשרה, עם הספרות 0 עד 9 ואחריהן A עד F לעשר עד חמש־עשרה, ושש־עשרה פעמים שש־עשרה הן 256, ולכן שתי ספרות הקסדצימליות נוקבות בכל בייט, ושלישית אף פעם לא נחוצה: 00 הוא 0, 7F הוא 127 ו־FF הוא 255. האות H היא 72, ארבע פעמים שש־עשרה ועוד שמונה, ולכן הבייט שלה הוא 48.
כל ספרה הקסדצימלית מייצגת בדיוק ארבעה ביטים, חצי בייט: ה־4 של 48 הוא 0100 וה־8 הוא 1000, וזו לצד זו הן 01001000, שמונת הביטים של H. העמוד שומר את שתי הספרות של כל בייט, ולכן מעבר שורה הוא 0A ורווח הוא 20, ומכיוון שכל בייט תופס את אותו רוחב, אפשר לקרוא הקסדצימלי בחזרה בלי שום דבר בין הבייטים: 4869 הוא Hi.
לאותיות בהקסדצימלי יש אותה משמעות בכל רישיות. העמוד כותב אותיות גדולות אלא אם תבחרו «אותיות קטנות», ולכן é היא C3 A9 או c3 a9, והוא קורא את שתי הצורות, גם כשהן מעורבבות בהדבקה אחת.
חמישה סגנונות, כל אחד בצורה שמתאימה למקום שבו מדביקים אותו
בהקסדצימלי, הבורר «סגנון» פורש את אותם בייטים בחמש דרכים, כל אחת למקום אחר שאליו הקסדצימלי הולך בהמשך. עבור Hi, שני הבייטים 48 ו־69:
- «מופרד ברווחים» נותן 48 69, רווח בין בייט לבייט: הקל ביותר לקריאה ולספירה, והסגנון שהעמוד נפתח עליו.
- «רציף» נותן 4869, הספרות צמודות זו לזו, לשדה או לפרמטר שמקבל ערך כמחרוזת אחת של הקסדצימלי.
- «מערך» נותן 0x48, 0x69, כל בייט מספר עם 0x לפניו ופסיק ביניהם, מוכן להדבקה לתוך מערך בייטים ב־C, ב־C#, ב־JavaScript, ב־Python או ב־Go.
- «רצפי בריחה» נותן \x48\x69, כל בייט כ־\x ושתי הספרות שלו, כפי שבייט נכתב בתוך מחרוזת של C או בתוך ליטרל בייטים של Python כמו b'\x48\x69'.
- «דאמפ הקסדצימלי» פורש את הבייטים בשורות, עם המקום שבו כל שורה מתחילה ועם אותם בייטים כטקסט לצידם: הפרק הבא קורא אחד כזה.
הקריאה מקבלת בחזרה את כל החמישה, וגם עיצוב אחר שאינו נוגע בבייטים: נקודתיים, כמו ב־48:69, המקפים ש־BitConverter.ToString של .NET כותב, כמו ב־48-69, 0x או 0X לפני כל בייט, ועטיפה אחת של כל ההדבקה בסוגריים עגולים, מרובעים או מסולסלים, או במירכאות. הסגנון והרישיות משנים רק בכתיבה, ולכן שני הבוררים נעלמים כשהכיוון הוא «הקסדצימלי לטקסט».
מלכודת אחת מסתתרת בסגנון «רצפי בריחה». במחרוזת של JavaScript, או במחרוזת רגילה של Python ולא בליטרל בייטים, \x מציין תו ולא בייט, ולכן \xD7\x90 הוא שם שני תווים ולא ה־א שהבייטים שלה ב־UTF-8 הם D7 90. מעבר ל־ASCII, תנו את הבייטים למשהו שמקבל בייטים.
קריאת דאמפ הקסדצימלי, עמודה אחר עמודה
דאמפ הקסדצימלי פורש בייטים שש־עשרה בשורה, עם עמודה בכל צד שעוזרת למצוא אותם. בסגנון «דאמפ הקסדצימלי», Hello, World! ומעבר שורה ממלאים שורה אחת: קודם 00000000, ההיסט, שהוא המקום שבו עומד הבייט הראשון של השורה כשסופרים מאפס, בשמונה ספרות הקסדצימליות; אחריו ארבעה־עשר הבייטים, שמונה ואחריהם שישה, עם רווח רחב יותר בין החצאים; ואחריהם |Hello, World!.|, אותם בייטים כתווים, כשכל בייט שאינו ASCII בר־הדפסה מוצג כנקודה, מעבר השורה ביניהם. שורה אחרונה מחזיקה רק 0000000E, כלומר ארבע־עשרה: המקום שבו הבייט הבא היה עומד, ולכן האורך. זו הפריסה ש־hexdump -C מדפיס.
- כשהכיוון הוא «הקסדצימלי לטקסט» ונבחרה כל יחידה מלבד «נקודות קוד», דאמפ הקסדצימלי שהודבק נקרא בשביל הבייטים שלו בלבד: עמודת הטקסט נשארת מחוץ לקריאה, שום היסט אינו נקרא כבייט, והערה מתחת לתוצאה אומרת שהקלט נלקח כדאמפ הקסדצימלי ונוקבת בפריסה.
- שתי פריסות נקראות כך: זו של hexdump -C, ומה ש־xxd מדפיס בלי אפשרויות, שבו נקודתיים באים אחרי כל היסט והבייטים עומדים בקבוצות של ארבע ספרות. ההקסדצימלי הפשוט ש־xxd -p מדפיס אינו צריך פריסה, ונקרא כמו כל הקסדצימלי אחר.
- hexdump -C מדפיס שורה של * בלבד במקום שורות שחוזרות על השורה שמעליהן, והעמוד ממלא את השורות האלה בחזרה לפי ההיסט שמתחת, כך שהבייטים חוזרים שלמים.
- כל היסט אחרי הראשון חייב לנבוע מהבייטים שמעליו, כולל האורך שבשורה האחרונה של hexdump -C, ושורה שההיסט שלה אינו נובע מהם נדחית שם ולא נקראת לא נכון: שם מתגלים שורה שהושמטה, בייט שאבד או היסט שהוקלד לא נכון. את מה שאחריו לא בא שום היסט אי אפשר לבדוק, ולכן דאמפ הקסדצימלי שחסרות בו השורות הראשונות, או סופו של דאמפ שאין אחריו שורת אורך — ו־xxd אינו כותב שורה כזאת — נקרא כמו מה שנשאר ממנו.
UTF-16 LE, ולמה כל בייט שני הוא 00
Windows שומרת טקסט ב־UTF-16 כשהבייט הנמוך ראשון, וזה UTF-16 LE; ב־.NET זה Encoding.Unicode, ו־SQL Server מאחסן ערך NVARCHAR באותו אופן. UTF-16 נותן לכל תו עד U+FFFF שני בייטים, ולכל דבר עד U+00FF — האותיות האנגליות, הספרות, é ושאר Latin-1 — הבייט הגבוה הוא 00. כשהבייט הנמוך ראשון, האפס הזה נוחת אחרי כל אות: Hi הוא 48 00 69 00.
SQL Server מציג ערך VARBINARY כ־0x ואחריו ההקסדצימלי שלו, ולכן NVARCHAR שמחזיק Hi, אחרי המרה ל־VARBINARY, מוצג כ־0x48006900. הדביקו את זה כאן כש־UTF-8 נבחר, והטקסט ייצא H, NUL, i ו־NUL, וההערה שמתחתיו תאמר שכל בייט שני הוא 00, כמו בטקסט באלפבית הלטיני שנכתב ב־UTF-16 ולא ב־UTF-8, עם הכפתור «החלף ל־UTF-16 LE» לצידה. לחצו עליו, ואותם בייטים ייקראו Hi.
UTF-16 BE מציב דווקא את הבייט הגבוה ראשון, ולכן Hi הוא שם 00 48 00 69, ו־א, שהיא D0 05 ב־UTF-16 LE, היא שם 05 D0. אפסים במקום הראשון של כל זוג גורמים להערה להציע את UTF-16 BE. היא לא אומרת דבר ברגע שיש בטקסט תו שמעבר ל־U+00FF, כי הבייט הגבוה של התו הזה אינו 00, והיא מדברת רק היכן שכל בייט שני הוא 00.
סימן סדר בייטים בהתחלה
טקסט יכול להתחיל ב־U+FEFF, תו שאינו מציג דבר ונמצא שם כדי להיות סימן סדר בייטים. ב־UTF-16 שני הבייטים שלו קובעים את הסדר של כל זוג שאחריהם, FF FE ב־UTF-16 LE ו־FE FF ב־UTF-16 BE, וב־UTF-8 הוא שלושת הבייטים EF BB BF, חתימה שאומרת שהטקסט הוא UTF-8, שיש לו רק סדר אחד.
העמוד שומר סימן כזה ולא משמיט אותו. הקסדצימלי שנפתח בסימן של היחידה שנבחרה נקרא כטקסט שמתחיל ב־U+FEFF, והערה אומרת שהסימן נשמר, כך שכתיבה מחדש של הטקסט הזה נותנת את אותם בייטים, כולל הסימן. הקסדצימלי שנפתח בסימן של סדר ה־UTF-16 השני, או בסימן של UTF-16 כש־UTF-8 נבחר, מקבל הערה שהבייטים נפתחים בסימן של יחידה אחרת, לצד כפתור שעובר לסדר שהסימן נוקב בו. בכל מקום אחרי ההתחלה, U+FEFF הוא תו רגיל ואינו מעורר שום הערה.
בייטים שאינם טקסט, מוצגים כ־U+FFFD
לא כל רצף של בייטים הוא טקסט ביחידה שנבחרה: תו שחסר לו הבייט האחרון, בייט תועה כמו E9, שדפי קוד ישנים כותבים עבור é, ובייט עודף שנשאר בסוף של UTF-16 — אף אחד מהם אינו מאיית דבר. אבל רצף פגום אחד לא מכשיל את ההדבקה כולה: כל רצף כזה מוחלף ב־U+FFFD, תו ההחלפה, וכל השאר נקרא כרגיל.
הערה נותנת אז את מספרם, ונוקבת בראשון לפי המקום שלו בין הבייטים, לפי הספרות שכתבתם עבורו ולפי השורה והעמודה שלו. Café שנשמרה ב־Windows-1252, דף הקוד של Windows לטקסט של מערב אירופה, היא 43 61 66 E9, כש־é היא שם בייט אחד, E9; כשקוראים אותה כ־UTF-8 היא חוזרת כ־Caf ו־U+FFFD, וההערה נוקבת בבייט 4, שנכתב E9, בשורה 1, עמודה 10. ב־UTF-8 המילה היא 43 61 66 C3 A9.
היא סופרת רצפים, לא בייטים: F0 9F 98, שלושה מארבעת הבייטים של 😀, הם U+FFFD אחד. ו־U+FFFD שבאמת נמצא בטקסט, הבייטים EF BF BD, נקרא כטקסט ואינו נספר כלל, כך שההערה עוסקת תמיד רק בבייטים שלא נקראו.
להפוך הקסדצימלי בחזרה לקובץ
הקריאה מוסרת את הבייטים וגם את הטקסט. כשהכיוון הוא «הקסדצימלי לטקסט» ונבחרו UTF-8, UTF-16 LE או UTF-16 BE, הכפתור «הורדה» שומר כקובץ בשם bytes.bin בדיוק את הבייטים שנקראו, כולל אלה שלא היו טקסט ולפני שמשהו מהם הוחלף: העבודה ש־xxd -r עושה עם דאמפ הקסדצימלי. אין «הורדה» לנקודות קוד, שאינן בייטים, וגם לא בזמן כתיבה, כשמה שאתם לוקחים איתכם הוא ספרות.
כך שגם הקסדצימלי של משהו שמעולם לא היה טקסט חוזר שלם. כל תמונת PNG מתחילה בשמונת הבייטים 89 50 4E 47 0D 0A 1A 0A; כשקוראים אותם כ־UTF-8 הם מוצגים כ־U+FFFD, האותיות PNG וארבעה תווי בקרה, עם הערה על הרצף האחד שאינו טקסט, והכפתור «הורדה» שומר את כל השמונה בדיוק. הקובץ תמיד נקרא bytes.bin, כי לבייטים אין שם, ולכן תנו לו שם משלו, כמו image.png, אחרי שהוא נשמר.
לאן לפנות בשביל תו, הביטים שלו או מספר
כדי לדעת מהו תו — השם שלו, הקטגוריה שלו, והאם הוא אחד מהתווים הבלתי נראים — בוחן תווי יוניקוד מפרק טקסט נקודת קוד אחר נקודת קוד, ומציג גם את הבייטים של כל אחת ב־UTF-8.
ממיר טקסט לבינארי הוא אותו עמוד עצמו כשהוא נפתח על בינארי, שבו אפשר לקרוא את הדפוס ש־UTF-8 הולך לפיו בביטים הראשונים של כל בייט. ומספר אינו טקסט: 255 שמוזן כאן הוא הספרות 2, 5 ו־5, ולכן הבייטים 32 35 35, ואילו ממיר בסיסי ספירה לוקח את 255 ככמות וכותב אותו בהקסדצימלי כ־ff.
שאלות נפוצות
- איך הופכים הקסדצימלי לטקסט?
- בחרו «הקסדצימלי לטקסט», הדביקו את ההקסדצימלי, וכוונו את היחידה לקידוד שבו הוא נכתב: UTF-8 לרוב הטקסטים, UTF-16 LE להקסדצימלי שנלקח ממחרוזת של Windows או של .NET, או מעמודת NVARCHAR. רווחים, פסיקים, נקודתיים ומקפים בין הבייטים, 0x או \x לפניהם ועטיפה אחת סביב הכול נקראים כולם, וכך גם אותיות גדולות או קטנות.
- למה יש NUL בין כל שתי אותיות בטקסט שלי?
- ככל הנראה ההקסדצימלי הוא UTF-16 LE שנקרא כ־UTF-8. ב־UTF-16 LE כל אות אנגלית נכתבת כשני בייטים, ערך ה־ASCII שלה ואחריו 00, ו־UTF-8 קורא כל אחד מהאפסים האלה כתו בפני עצמו, NUL. בחרו UTF-16 LE, או לחצו על כפתור ההחלפה אם העמוד מציע אותו לצד ההערה שלו, והאותיות ייצמדו שוב זו לזו.
- למה אותיות עם סימנים דיאקריטיים בהקסדצימלי שלי יוצאות U+FFFD?
- ככל הנראה ההקסדצימלי נכתב בדף קוד ישן כמו Windows-1252, שבו é היא בייט אחד, E9, ואילו ב־UTF-8 האות é היא C3 A9, ו־E9 לבדו אינו טקסט. העמוד קורא UTF-8 ו־UTF-16 ולא שום דף קוד ישן, ולכן במקום לנחש לאיזה מהם התכוונו, הוא מציג כל רצף כזה כ־U+FFFD ואומר היכן נמצא הראשון. «הורדה» עדיין נותנת לכם את הבייטים כפי שהיו.
- אפשר להדביק את מה ש־xxd או hexdump -C הדפיסו?
- כן: את הפריסה של hexdump -C, שהיא גם מה שהסגנון «דאמפ הקסדצימלי» כותב, ואת מה ש־xxd מדפיס בלי אפשרויות. עמודת הטקסט מושמטת ושום היסט אינו נקרא כבייט, שורת * מתמלאת בחזרה, והערה אומרת איזו משתי הפריסות נקראה; היסט שאינו נובע מהבייטים שלפניו עוצר את הקריאה בשורה שלו, כי השורות כבר אינן מסכימות זו עם זו. גם ההקסדצימלי הפשוט של xxd -p נקרא, כמו כל הקסדצימלי אחר, בלי הערה.
- האם משנה אם ההקסדצימלי כתוב באותיות גדולות או קטנות?
- לא לבייטים: 4A ו־4a הם אותו בייט, J. העמוד כותב אותיות גדולות אלא אם תבחרו «אותיות קטנות», והבחירה הזאת חלה על ההיסטים של דאמפ הקסדצימלי כמו על הבייטים שלו; הקריאה מקבלת את שתי הצורות, גם כשהן מעורבבות באותה הדבקה.
- איך מקבלים בחזרה קובץ מדאמפ הקסדצימלי?
- בחרו «הקסדצימלי לטקסט» ו־UTF-8 או אחד משני ה־UTF-16, הדביקו את הדאמפ או את ההקסדצימלי הפשוט, ולחצו על «הורדה». הקובץ שהכפתור שומר, bytes.bin, מחזיק בדיוק את הבייטים שנקראו ממה שהדבקתם, טקסט או לא, ולכן הוא עושה את העבודה של xxd -r; תנו לו בחזרה את השם שהיה לו.
- האם בטוח להדביק הקסדצימלי ממסד נתונים בפרודקשן או מלוג?
- כן, ככל שהדבר נוגע להמרה. היא מתבצעת על המכשיר שלכם עצמכם, לאיזה כיוון שהיא רצה: ההקסדצימלי שאתם מדביקים, הטקסט שהוא הופך אליו וכל קובץ שהכפתור «הורדה» שומר לעולם אינם נשלחים לשום מקום.
כלים קשורים
- ממיר טקסט לבינארי
בינארי כותב בייט כשמונת הביטים שלו, ובו אפשר לקרוא את הדפוס של UTF-8: é הוא C3 A9 כאן, ובעמוד ההוא 11000011 10101001 — הבייט הראשון נפתח ב־110 כי האות תופסת שניים, והשני ב־10 כי הוא ממשיך אותה. גם העמוד הזה מציע בינארי, והעמוד ההוא נפתח עליו.
- בוחן תווי יוניקוד
לראות בדיוק מאילו תווים בנויה מחרוזת.
- ממיר בסיסי ספירה
הקלידו 255 בעמוד הזה ותקבלו שלושה בייטים, אחד לכל תו: 32 35 35. העמוד ההוא קורא את 255 כמספר וממיר את הערך עצמו, שבהקסדצימלי הוא ff.
- Base64
קידוד ופענוח Base64 — תמיכה מלאה ב־UTF-8.