המרת מחרוזת למערך בתים והיפוך בג'אווה

1. הקדמה

לעתים קרובות אנו צריכים להמיר בין חוּט ו בתים מערך בג'אווה. במדריך זה נבחן את הפעולות הללו בפירוט.

ראשית, נבחן דרכים שונות להמיר א חוּט אל א בתים מַעֲרָך. לאחר מכן, נסתכל על פעולות דומות הפוך.

2. המרה חוּט ל בייט מַעֲרָך

א חוּט מאוחסן כמערך של תווי Unicode בג'אווה. להמיר אותו לא בתים מערך, אנו מתרגמים את רצף התווים לרצף של בתים. לתרגום זה, אנו משתמשים במופע של ערכת. מחלקה זו מציינת מיפוי בין רצף של לְהַשְׁחִירs ורצף של בתיםס.

אנו מתייחסים לתהליך הנ"ל כ- הַצפָּנָה.

אנחנו יכולים לקודד א חוּט לתוך בתים מערך ב- Java במספר דרכים. בואו נסתכל על כל אחד מהם בפירוט עם דוגמאות.

2.1. באמצעות String.getBytes ()

ה חוּט הכיתה מספקת שלוש עומס יתר getBytes שיטות לקידוד א חוּט לְתוֹך בתים מַעֲרָך:

  • getBytes () - מקודד באמצעות ערכת ברירת המחדל של הפלטפורמה
  • getBytes (מחרוזת charsetName) - מקודד באמצעות ערכת התווים שצוינה
  • getBytes (Charset charset) - מקודד באמצעות ערכת התווים המסופקת

קוֹדֶם כֹּל, בוא נקודד מחרוזת באמצעות ערכת ברירת המחדל של הפלטפורמה:

String inputString = "שלום עולם!"; בייט [] byteArrray = inputString.getBytes ();

השיטה לעיל תלויה בפלטפורמה מכיוון שהיא משתמשת בערכת ברירת המחדל של הפלטפורמה. אנו יכולים להשיג את ערכת התווים הזו על ידי התקשרות Charset.defaultCharset ().

שנית, בוא נקודד מחרוזת באמצעות ערכת שם בשם:

@ מבחן ציבורי בטל כאשר GetBytesWithNamedCharset_thenOK () זורק UnsupportedEncodingException {String inputString = "שלום עולם!"; מחרוזת charsetName = "IBM01140"; בתים [] byteArrray = inputString.getBytes ("IBM01140"); assertArrayEquals (בתים חדשים [] {-56, -123, -109, -109, -106, 64, -26, -106, -103, -109, -124, 90}, byteArrray); }

שיטה זו זורקת לא נתמך קידוד יוצא אם ערכת התווים הנקובה אינה נתמכת.

ההתנהגות של שתי הגרסאות הנ"ל אינה מוגדרת אם הקלט מכיל תווים שאינם נתמכים על ידי ערכת התווים. לעומת זאת, הגרסה השלישית משתמשת במערך בתים החלופי המוגדר כברירת מחדל של הצ'ארסה כדי לקודד קלט שאינו נתמך.

הַבָּא, בואו נקרא לגרסה השלישית של ה- getBytes () שיטה ולהעביר מופע של ערכת:

@ מבחן ציבורי בטל כאשר GetBytesWithCharset_thenOK () {String inputString = "שלום ਸੰਸਾਰ!"; Charset charset = Charset.forName ("ASCII"); בייט [] byteArrray = inputString.getBytes (ערכת תווים); assertArrayEquals (בתים חדשים [] {72, 101, 108, 108, 111, 32, 63, 63, 63, 63, 63, 33}, byteArrray); }

הנה, אנו משתמשים בשיטת המפעל Charset.forName כדי לקבל מופע של ערכת. שיטה זו מפעילה חריג של זמן ריצה אם שם ערכת התווים המבוקשת אינו חוקי. זה גם יוצר חריג של זמן ריצה אם ערכת התווים נתמכת ב- JVM הנוכחי.

עם זאת, מובטח כי כמה ערכות תווים יהיו זמינות בכל פלטפורמת Java. ה סטנדרטי ערכות class מגדיר קבועים עבור ערמות אלה.

סוף כל סוף, בואו נקודד באמצעות אחת מערכות התווים הרגילות:

@ מבחן ציבורי בטל כאשר GetBytesWithStandardCharset_thenOK () {String inputString = "שלום עולם!"; ערכת Charset = StandardCharsets.UTF_16; בייט [] byteArrray = inputString.getBytes (ערכת תווים); assertArrayEquals (בתים חדשים [] {-2, -1, 0, 72, 0, 101, 0, 108, 0, 108, 0, 111, 0, 32, 0, 87, 0, 111, 0, 114, 0 , 108, 0, 100, 0, 33}, byteArrray); }

לפיכך, אנו משלימים את הסקירה על השונים getBytes גרסאות. לאחר מכן, בואו נבדוק את השיטה המסופקת על ידי ערכת את עצמה.

2.2. באמצעות Charset.encode ()

ה ערכת הכיתה מספקת לְהַצְפִּין(), שיטה נוחה המקודדת תווי Unicode לבתים. שיטה זו מחליפה תמיד תווים לא חוקיים ותווים שאינם ניתנים לתיקון באמצעות מערך בתים החלופי המוגדר כברירת מחדל של ערכת התווים.

בואו נשתמש ב- לְהַצְפִּין שיטה להמיר חוּט לתוך בתים מַעֲרָך:

@Test ציבורי בטל כאשרEncodeWithCharset_thenOK () {String inputString = "שלום ਸੰਸਾਰ!"; ערכת Charset = StandardCharsets.US_ASCII; בייט [] byteArrray = charset.encode (inputString) .array (); assertArrayEquals (בתים חדשים [] {72, 101, 108, 108, 111, 32, 63, 63, 63, 63, 63, 33}, byteArrray); }

כפי שניתן לראות לעיל, תווים שאינם נתמכים הוחלפו בהחלפת ברירת המחדל של ערכת התווים בתים 63.

הגישות ששימשו עד כה משתמשות ב CharsetEncoder בכיתה באופן פנימי לביצוע קידוד. בואו נבחן שיעור זה בסעיף הבא.

2.3. CharsetEncoder

CharsetEncoder הופך תווי Unicode לרצף של בתים עבור ערכת תווים מסוימת. יתר על כן, הוא מספק שליטה דקה בתהליך הקידוד.

בואו נשתמש בכיתה זו להמרת a חוּט לתוך בתים מַעֲרָך:

@Test ציבורי בטל כאשרUsingCharsetEncoder_thenOK () זורק CharacterCodingException {String inputString = "שלום ਸੰਸਾਰ!"; מקודד CharsetEncoder = StandardCharsets.US_ASCII.newEncoder (); encoder.onMalformedInput (CodingErrorAction.IGNORE) .onUnmappableCharacter (CodingErrorAction.REPLACE) .replaceWith (בית חדש [] {0}); בייט [] byteArrray = encoder.encode (CharBuffer.wrap (inputString)) .array (); assertArrayEquals (בתים חדשים [] {72, 101, 108, 108, 111, 32, 0, 0, 0, 0, 0, 33}, byteArray); }

הנה, אנו יוצרים מופע של CharsetEncoder על ידי קריאה ל newEncoder שיטה על א ערכת לְהִתְנַגֵד.

לאחר מכן אנו מציינים פעולות לתנאי שגיאה על ידי קריאה ל onMalformedInput () ו onUnmappableCharacter () שיטות. אנו יכולים לציין את הפעולות הבאות:

  • התעלם - שחרר את הקלט השגוי
  • החלף - החלף את הקלט השגוי
  • דווח - דווח על השגיאה על ידי החזרת a CoderResult חפץ או זריקה א CharacterCodingException

יתר על כן, אנו משתמשים ב- להחליף ב() שיטה לציון ההחלפה בתים מערך.

לפיכך, אנו משלימים את הסקירה של גישות שונות להמרת מחרוזת למערך בתים. הבה נבחן את הפעולה ההפוכה.

3. המרת מערך בתים למחרוזת

אנו מתייחסים לתהליך המרת א בתים מערך ל- a חוּט כפי ש פִּעַנוּחַ. בדומה לקידוד, תהליך זה דורש ערכת.

עם זאת, איננו יכולים להשתמש בסימן כל ערכה לפענוח מערך בתים. עלינו להשתמש בערכת התווים ששימשה לקידוד ה- חוּט לתוך ה בתים מַעֲרָך.

אנו יכולים להמיר מערך בתים למחרוזת במובנים רבים. בואו נבחן כל אחד מהם בפירוט.

3.1. משתמש ב חוּט בַּנַאִי

ה חוּט בכיתה יש מעט בונים שלוקחים א בתים מערך כקלט. כולם דומים ל getBytes שיטה אבל עבודה הפוכה.

ראשון, בואו להמיר מערך בתים ל- חוּט באמצעות ערכת ברירת המחדל של הפלטפורמה:

@ מבחן ציבורי בטל כאשר StringConstructorWithDefaultCharset_thenOK () {byte [] byteArrray = {72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33}; מחרוזת מחרוזת = מחרוזת חדשה (byteArrray); assertNotNull (מחרוזת); }

שים לב שאנחנו לא טוענים שום דבר כאן לגבי תוכן המחרוזת המפוענחת. הסיבה לכך היא שהיא עשויה לפענח למשהו אחר, תלוי בערכת ברירת המחדל של הפלטפורמה.

מסיבה זו, בדרך כלל עלינו להימנע משיטה זו.

שנית, בואו נשתמש בערכת תווים בשם לפענוח:

@Test ציבורי בטל כאשר StringConstructorWithNamedCharset_thenOK () זורק UnsupportedEncodingException {String charsetName = "IBM01140"; בייט [] byteArrray = {-56, -123, -109, -109, -106, 64, -26, -106, -103, -109, -124, 90}; מחרוזת מחרוזת = מחרוזת חדשה (byteArrray, charsetName); assertEquals ("שלום עולם!", מחרוזת); }

שיטה זו מציגה חריג אם ערכת התווים הנקובה אינה זמינה ב- JVM.

שְׁלִישִׁית, בואו נשתמש ב- ערכת התנגד לבצע פענוח:

@Test ציבורי בטל כאשר StringConstructorWithCharSet_thenOK () {Charset charset = Charset.forName ("UTF-8"); בייט [] byteArrray = {72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33}; מחרוזת מחרוזת = מחרוזת חדשה (byteArrray, charset); assertEquals ("שלום עולם!", מחרוזת); }

סוף כל סוף, בואו נשתמש בתקן ערכת לאותו הדבר:

@Test ציבורי בטל כאשר StringConstructorWithStandardCharSet_thenOK () {Charset charset = StandardCharsets.UTF_16; בתים [] byteArrray = {-2, -1, 0, 72, 0, 101, 0, 108, 0, 108, 0, 111, 0, 32, 0, 87, 0, 111, 0, 114, 0, 108, 0, 100, 0, 33}; מחרוזת מחרוזת = מחרוזת חדשה (byteArrray, charset); assertEquals ("שלום עולם!", מחרוזת); }

עד כה המירו א בתים מערך לתוך חוּט באמצעות הקונסטרוקטור. בואו נבחן את הגישות האחרות.

3.2. באמצעות Charset.decode ()

ה ערכת הכיתה מספקת את לְפַעֲנֵחַ() שיטה הממירה א ByteBuffer ל חוּט:

@ מבחן ציבורי בטל כאשר DecodeWithCharset_thenOK () {בתים [] byteArrray = {72, 101, 108, 108, 111, 32, -10, 111, 114, 108, -63, 33}; ערכת Charset = StandardCharsets.US_ASCII; מחרוזת מחרוזת = charset.decode (ByteBuffer.wrap (byteArrray)). ToString (); assertEquals ("שלום  orl !", מחרוזת); }

פה, הקלט הלא חוקי מוחלף בתו החלפת ברירת המחדל עבור ערכת התווים.

3.3. CharsetDecoder

כל הגישות הקודמות לפענוח פנימי משתמשות ב- CharsetDecoder מעמד. אנו יכולים להשתמש בכיתה זו ישירות לבקרת גרגירים עדינים בתהליך הפענוח:

@ מבחן פומבי בטל כאשר שימושCharsetDecoder_thenOK () זורק CharacterCodingException {byte [] byteArrray = {72, 101, 108, 108, 111, 32, -10, 111, 114, 108, -63, 33}; מפענח CharsetDecoder = StandardCharsets.US_ASCII.newDecoder (); decoder.onMalformedInput (CodingErrorAction.REPLACE) .onUnmappableCharacter (CodingErrorAction.REPLACE) .replaceWith ("?"); מחרוזת מחרוזת = decoder.decode (ByteBuffer.wrap (byteArrray)) .toString (); assertEquals ("שלום? אורל ?!", מחרוזת); }

הנה, אנו מחליפים תשומות לא חוקיות ותווים לא נתמכים ב- "?".

אם אנו רוצים לקבל הודעה במקרה של תשומות לא חוקיות, אנו יכולים לשנות את מפענח כפי ש:

decoder.onMalformedInput (CodingErrorAction.REPORT) .onUnmappableCharacter (CodingErrorAction.REPORT)

4. מסקנה

במאמר זה חקרנו דרכים רבות להמרה חוּט למערך בתים ולהפוך. עלינו לבחור את השיטה המתאימה בהתבסס על נתוני הקלט וכן על רמת השליטה הנדרשת לתשומות לא חוקיות.

כרגיל, ניתן למצוא את קוד המקור המלא ב- GitHub.