Java InputStream למחרוזת

1. סקירה כללית

במדריך זה נבחן כיצד להמיר InputStream למחרוזת, באמצעות גויאבה, ספריית IO של Apache Commons, ו- Java רגיל.

מאמר זה הוא חלק מסדרת "Java - Back to Basic" כאן בבלדונג.

2. המרה עם גויאבה

נתחיל בדוגמה של גויאבה - מינוף ה- ByteSource פונקציונליות:

@Test הציבור בטל givenUsingGuava_whenConvertingAnInputStreamToAString_thenCorrect () זורק IOException {String originalString = randomAlphabetic (8); InputStream inputStream = ByteArrayInputStream חדש (originalString.getBytes ()); ByteSource byteSource = ByteSource חדש () {@Override InputStream ציבורי openStream () זורק IOException {return inputStream; }}; טקסט מחרוזת = byteSource.asCharSource (Charsets.UTF_8) .read (); assertThat (טקסט, equalTo (originalString)); }

בואו נעבור על השלבים:

  • ראשון אנחנו עוטפים את שלנו InputStream א ByteSource - ולפי הידוע לי, זו הדרך הקלה ביותר לעשות זאת
  • לאחר מכן אנו רואים את שלנו ByteSource כ CharSource עם ערכת UTF8.
  • סוף כל סוף אנו משתמשים ב- CharSource לקרוא את זה כמחרוזת.

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

@Test הציבור בטל givenUsingGuavaAndJava7_whenConvertingAnInputStreamToAString_thenCorrect () זורק IOException {String originalString = randomAlphabetic (8); InputStream inputStream = ByteArrayInputStream חדש (originalString.getBytes ()); טקסט מחרוזת = null; נסה (קורא קורא = InputStreamReader חדש (inputStream)) {text = CharStreams.toString (קורא); } assertThat (טקסט, equalTo (originalString)); }

3. המרה עם IO של Apache Commons

בואו נבחן כעת כיצד לעשות זאת באמצעות ספריית IO של Commons.

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

@ מבחן בטל ציבורי שניתןUsingCommonsIo_whenConvertingAnInputStreamToAString_thenCorrect () זורק IOException {String originalString = randomAlphabetic (8); InputStream inputStream = ByteArrayInputStream חדש (originalString.getBytes ()); טקסט מחרוזת = IOUtils.toString (inputStream, StandardCharsets.UTF_8.name ()); assertThat (טקסט, equalTo (originalString)); }

אנו יכולים גם להשתמש ב- StringWriter לבצע את ההמרה:

@Test הציבור בטל שניתןUsingCommonsIoWithCopy_whenConvertingAnInputStreamToAString_thenCorrect () זורק IOException {String originalString = randomAlphabetic (8); InputStream inputStream = ByteArrayInputStream חדש (originalString.getBytes ()); סופר StringWriter = חדש StringWriter (); קידוד מחרוזת = StandardCharsets.UTF_8.name (); IOUtils.copy (inputStream, כותב, קידוד); assertThat (writer.toString (), equalTo (originalString)); }

4. המרה עם Java - InputStream

בואו נסתכל כעת על גישה ברמה נמוכה יותר באמצעות Java רגיל - an InputStream ופשוט StringBuilder:

@Test הציבור בטל givenUsingJava5_whenConvertingAnInputStreamToAString_thenCorrect () זורק IOException {String originalString = randomAlphabetic (DEFAULT_SIZE); InputStream inputStream = ByteArrayInputStream חדש (originalString.getBytes ()); StringBuilder textBuilder = StringBuilder חדש (); נסה (Reader Reader = BufferedReader חדש (InputStreamReader חדש (inputStream, Charset.forName (StandardCharsets.UTF_8.name ())))) {int c = 0; בעוד ((c = reader.read ())! = -1) {textBuilder.append ((char) c); }} assertEquals (textBuilder.toString (), originalString); }

4.1. באמצעות Java 8

Java 8 מביא חדש שורות() שיטה ל BufferedReader. בואו נראה איך נוכל להשתמש בו כדי להמיר InputStream אל א חוּט:

@Test הציבור בטל givenUsingJava8_whenConvertingAnInputStreamToAString_thenCorrect () {String originalString = randomAlphabetic (DEFAULT_SIZE); InputStream inputStream = ByteArrayInputStream חדש (originalString.getBytes ()); טקסט מחרוזת = BufferedReader חדש (InputStreamReader חדש (inputStream, StandardCharsets.UTF_8))) .lines () .collect (Collectors.joining ("\ n")); assertThat (טקסט, equalTo (originalString)); }

חשוב להזכיר זאת שורות() משתמש ב- קריאת שורה() שיטה מתחת למכסה המנוע. קריאת שורה() מניח שקו מסתיים על ידי כל אחד מהזנת השורה ("\ n"), החזרת הכרכרה ("\ r"), או החזרת הכרכרה ואחריה מייד הזנת השורה. במילים אחרות, זה תומך בכל המשותף סוף השורה סגנונות - יוניקס, חלונות ואפילו Mac OS ישנים.

מצד שני, כשאנחנו משתמשים Collectors.joining (), עלינו להחליט במפורש באיזה סוג של EOL אנו רוצים להשתמש עבור הנוצר חוּט.

נוכל גם להשתמש ב- Collectors.joining (System.lineSeparator ()), ובמקרה זה הפלט תלוי בהגדרות המערכת.

5. המרה עם Java ו- סוֹרֵק

לאחר מכן - בואו נסתכל על דוגמת Java רגילה - באמצעות טקסט רגיל סוֹרֵק:

@Test הציבור בטל givenUsingJava7_whenConvertingAnInputStreamToAString_thenCorrect () זורק IOException {String originalString = randomAlphabetic (8); InputStream inputStream = ByteArrayInputStream חדש (originalString.getBytes ()); טקסט מחרוזת = null; נסה (סורק סורק = סורק חדש (inputStream, StandardCharsets.UTF_8.name ())) {text = scanner.useDelimiter ("\ A"). הבא (); } assertThat (טקסט, equalTo (originalString)); }

שים לב שה- InputStream הולך להיסגר על ידי סגירת ה- סוֹרֵק.

כדאי גם להבהיר מה useDelimiter ("\ A") עושה. כאן, עברנו את ה- \ A 'שהוא סמן גבול regex המציין את תחילת הקלט. בעיקרו של דבר, המשמעות היא שה- הַבָּא() שיחה קוראת את כל זרם הקלט.

הסיבה היחידה שזו דוגמא ל- Java 7, ולא Java 5 היא השימוש ב- נסה עם משאבים הצהרה - להפוך את זה לתקן נסה סוף סוף לַחסוֹם יתכנס בסדר גמור עם Java 5.

6. המרה באמצעות ByteArrayOutputStream

לסיום, בואו נסתכל על דוגמא פשוטה אחרת של Java, הפעם באמצעות ה- ByteArrayOutputStream מעמד:

@Test הציבור בטל givenUsingPlainJava_whenConvertingAnInputStreamToString_thenCorrect () זורק IOException {String originalString = randomAlphabetic (8); InputStream inputStream = ByteArrayInputStream חדש (originalString.getBytes ()); מאגר ByteArrayOutputStream = ByteArrayOutputStream חדש (); int n קריאה; בתים [] נתונים = בתים חדשים [1024]; בעוד ((nRead = inputStream.read (נתונים, 0, data.length))! = -1) {buffer.write (data, 0, nRead); } buffer.flush (); בייט [] byteArray = buffer.toByteArray (); טקסט מחרוזת = מחרוזת חדשה (byteArray, StandardCharsets.UTF_8); assertThat (טקסט, equalTo (originalString)); }

בדוגמה זו, ראשית, InputStream מומר ל- ByteArrayOutputStream על ידי קריאה וכתיבה של גושי בתים, ואז ה- OutputStream הופך למערך בתים המשמש ליצירת a חוּט.

7. המרה עם java.nio

פיתרון נוסף הוא העתקת תוכן ה- InputStream לקובץ, ואז המירו זאת ל- חוּט:

@Test הציבור בטל givenUsingTempFile_whenConvertingAnInputStreamToAString_thenCorrect () זורק IOException {String originalString = randomAlphabetic (DEFAULT_SIZE); InputStream inputStream = ByteArrayInputStream חדש (originalString.getBytes ()); נתיב tempFile = Files.createTempDirectory (""). לפתור (UUID.randomUUID (). ToString () + ".tmp"); Files.copy (inputStream, tempFile, StandardCopyOption.REPLACE_EXISTING); תוצאת מחרוזת = מחרוזת חדשה (Files.readAllBytes (tempFile)); assertThat (תוצאה, equalTo (originalString)); }

הנה, אנו משתמשים ב- java.nio.file.Files בכיתה ליצירת קובץ זמני וכן להעתקת תוכן ה- InputStream לקובץ. לאחר מכן, אותו מחלקה משמש להמרת תוכן הקובץ ל- a חוּט עם ה readAllBytes () שיטה.

8. מסקנה

לאחר שחיברתי את הדרך הטובה ביותר לבצע את ההמרה הפשוטה - InputStream to String - בצורה נכונה וקריאה - ואחרי שראיתי כל כך הרבה תשובות ופתרונות שונים בתכלית - אני חושב ש דרוש שיטה מומלצת ברורה ותמציתית לכך.

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