טיפ Java 49: כיצד לחלץ משאבי Java מארכיוני JAR ו- zip

מרבית מתכנתי Java די ברורים לגבי היתרונות של שימוש בקובץ JAR כדי לאגד את כל המשאבים השונים (כלומר קבצי .class, צלילים ותמונות) המרכיבים את פתרון ה- Java שלהם. (אם אינך מכיר קבצי JAR, עיין בסעיף משאבים למטה.) שאלה נפוצה מאוד שנשאלת על ידי אנשים שרק התחילו לשלב קבצי JAR בתיק הטריקים שלהם היא, "איך אוכל לחלץ תמונה מ- קַנקַן?" אנחנו הולכים לענות על השאלה הזו ולספק שיעור שיעשה את זה פשוט מאוד לחלץ כל משאב מ- JAR!

טוען תמונת GIF

נניח שיש לנו קובץ JAR המכיל חבורה של קבצי תמונה .gif שאנו רוצים להשתמש ביישום שלנו. כך נוכל לגשת לקובץ תמונה מה- JAR באמצעות JarResources:

JarResources jar = JarResources חדש ("Images.jar"); לוגו תמונה = Toolkit.getDefaultToolkit (). CreateImage (jar.getResource ("logo.gif");

קטע הקוד מראה כי אנו יכולים ליצור JarResourcesאובייקט שאותחל מאותחל לקובץ JAR המכיל את המשאב בו אנו מעוניינים להשתמש - Images.jar. לאחר מכן אנו משתמשים JarResources'getResource()בשיטה כדי לספק את הנתונים הגולמיים מקובץ logo.gif createImage()לשיטת ערכת הכלים AWT .

הערה בנושא שמות

JarResource הוא דוגמה פשוטה למדי לאופן השימוש במתקנים שונים הניתנים על ידי Java 1.1 כדי לתפעל קבצי ארכיון JAR ו- zip.

הערה מהירה לגבי שמות. תמיכה בארכיון בג'אווה התחילה למעשה באמצעות פורמט ארכיון zip פופולרי (בדוק "טיפ ג'אווה 21: השתמש בקובצי ארכיון כדי להאיץ את טעינת היישומון"). לכן, במקור, ביישום תמיכת Java כדי לתפעל את קבצי הארכיון, כל השיעורים ומה לא הושמו בחבילה java.util.zip; שיעורים אלה נוטים להתחיל עם " Zip." אבל אי שם במעבר ל- Java 1.1, הכוחות שמשנים את שם הארכיון כדי להיות יותר ממוקדים ב- Java. לפיכך, מה שאנו מכנים כעת קבצי JAR הם בעצם קבצי zip.

איך זה עובד

שדות הנתונים החשובים JarResourcesבכיתה משמשים למעקב ואחסון של תוכן קובץ ה- JAR שצוין:

כיתת גמר ציבורית JarResources {debugOn public boolean = false; פרטי Hashtable htSizes = Hashtable חדש (); פרטי Hashtable htJarContents = Hashtable חדש (); פרטי מחרוזת jarFileName;

אז, המיידיות של הכיתה קובעת את שם קובץ ה- JAR ואז קוראת init()לשיטה לעשות את כל העבודה האמיתית:

JarResources ציבורי (jarFileName מחרוזת) {this.jarFileName = jarFileName; init (); }

כעת, init()השיטה פחות או יותר נטענת את כל התוכן של קובץ ה- JAR שצוין אל hashtable (שניתן לגשת אליו באמצעות שם המשאב).

זו שיטה חסונה למדי, אז בואו נפרק אותה עוד קצת. ZipFileבכיתה נותנת לנו גישה בסיסית JAR / zip פרטי כותרת ארכיון. זה דומה למידע הספריה במערכת קבצים. כאן אנו למנות דרך כל הערכים ZipFileולבנות את htSizes hashtable עם הגודל של כל משאב בארכיון:

init חלל פרטי () {נסה {ZipFile zf = ZipFile חדש (jarFileName); ספירה e = zf.entries (); בעוד (e.hasMoreElements ()) {ZipEntry ze = (ZipEntry) e.nextElement (); אם (debugOn) {System.out.println (dumpZipEntry (ze)); } htSizes.put (ze.getName (), מספר שלם חדש ((int) ze.getSize ())); } zf.close ();

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

FileInputStream fis = FileInputStream חדש (jarFileName); BufferedInputStream bis = BufferedInputStream חדש (fis); ZipInputStream zis = חדש ZipInputStream (bis); ZipEntry ze = null; בעוד ((ze = zis.getNextEntry ())! = null) {אם (ze.isDirectory ()) {המשך; } אם (debugOn) {System.out.println ("ze.getName () =" + ze.getName () + "," + "getSize () =" + ze.getSize ()); } int גודל = (int) ze.getSize (); // -1 פירושו גודל לא ידוע. אם (size == - 1) {size = ((Integer) htSizes.get (ze.getName ())). intValue (); } בתים [] b = גודל בת חדש [(int)]; int rb = 0; נתח int = 0; בעוד (((int) size - rb)> 0) {chunk = zis.read (b, rb, (int) size - rb); אם (נתח == - 1) {הפסקה; } rb + = נתח; } // הוסף למשאב הפנימי htJarContents.put (ze.getName (), b); אם (debugOn) {System.out.println (ze.getName () + "rb =" + rb + ", size =" + size + ", csize =" + ze.getCompressedSize ()); }}} לתפוס (NullPointerException e) {System.out.println ("נעשה."); } לתפוס (FileNotFoundException e) {e.printStackTrace (); } לתפוס (IOException e) {e.printStackTrace (); }}

שים לב שהשם המשמש לזיהוי כל משאב הוא שם הנתיב המוסמך של המשאב בארכיון, ולא למשל שם המחלקה בחבילה - כלומר ZipEntryהמחלקה מחבילה java.util.zip הייתה ייקרא "java / util / zip / ZipEntry", ולא "java.util.zip.ZipEntry."

החלק החשוב האחרון בקוד הוא נהג הבדיקה הפשוט. מנהל ההתקן הוא יישום פשוט הלוקח שם ארכיון JAR / zip ואת שם המשאב. הוא מנסה למצוא את המשאב בארכיון ומדווח על הצלחתו או כישלונו:

main static public main (String [] args) זורק IOException {if (args.length! = 2) {System.err.println ("use: java JarResources"); System.exit (1); } JarResources jr = JarResources חדשים (טענות [0]); בתא [] buff = jr.getResource (טענות [1]); אם (buff == null) {System.out.println ("לא ניתן היה למצוא" + טענות [1] + "."); } אחר {System.out.println ("נמצא" + טענות [1] + "(אורך =" + buff.length + ")."); }}} // סוף שיעור JarResources.

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

תרגילים לקורא

עכשיו שיש לך תחושה לחילוץ משאבים מקובץ ארכיון, הנה כמה כיוונים שתרצה לחקור בשינוי והרחבת JarResourcesהכיתה:

  • במקום לטעון הכל במהלך הבנייה, בצעו טעינה מאוחרת. במקרה של קובץ JAR גדול, ייתכן שלא יהיה מספיק זיכרון לטעינת כל הקבצים במהלך הבנייה.
  • במקום פשוט לספק שיטת accessor כללית כמו getResource(), נוכל לספק אביזרים ספציפיים למשאבים אחרים - למשל, getImage()שמחזירים Imageאובייקט Java getClass(), שמחזיר Classאובייקט Java (בעזרת מטעין מחלקה מותאם אישית) וכן הלאה. אם קובץ ה- JAR קטן מספיק, נוכל לבנות מראש את כל המשאבים על סמך התוספים שלהם (.gif, .class, וכן הלאה).
  • שיטות מסוימות צריכות לספק מידע על קובץ ה- JAR הנתון עצמו (בעיקרון עטיפה מסביב ZipFile), כולל: מספר ערכי ה- Jar / zip; מונה המחזיר את כל שמות המשאבים; אביזרים המחזירים את אורכו (ותכונות אחרות) של ערך מסוים; ואביזר המאפשר להוסיף לאינדקס, עד כמה שם.
  • JarResourcesיכול להיות מורחב לשימוש על ידי יישומונים. על ידי שימוש בפרמטרים של יישומונים URLConnectionוהמחלקה, ניתן להוריד את תוכן ה- JAR מהרשת במקום לפתוח את הארכיונים כקבצים מקומיים. יתר על כן, אנו עשויים להרחיב מחלקה זו כמטפל תוכן Java מותאם אישית.

סיכום

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

ארתור צ'וי עובד כיום עבור יבמ כמתכנת מייעץ. הוא עבד במספר חברות, כולל מעבדת רשת SamSung ו- MITRE. הפרויקטים השונים שעבד עליהם הם מערכות לקוח / שרת, מחשוב אובייקטים מבוזרים וניהול רשת. הוא השתמש במספר שפות בסביבות מערכת הפעלה שונות. הוא החל לתכנת בשנת 1981 עם FORTRAN IV ו- COBOL. מאוחר יותר הוא עבר ל- C ו- C ++, והוא עובד עם Java כבר כשנתיים. הוא מתעניין ביותר ביישומי ג'אווה בתחומי מאגרי נתונים דרך רשתות רחבות שטח, ועיבוד מקביל ומופץ דרך האינטרנט (באמצעות תכנות מבוסס סוכנים). ג'ון מיטשל, עובד, יועץ ומנהל חברה משלו, השקיע בעשר השנים האחרונות בפיתוח תוכנות מחשב חדישות,ובייעוץ והדרכה למפתחים אחרים. הוא סיפק ייעוץ בנושא טכנולוגיית Java, מהדרים, מתורגמנים, יישומים מבוססי אינטרנט ומסחר באינטרנט. ג'ון היה שותף לכתיבת Making Sense of Java: מדריך למנהלים ולשארנו ופרסם מאמרים בכתבי עת בתכנות. בנוסף לכתיבת העמודה Java Tips עבור JavaWorld, הוא מנחה את קבוצות הדיון comp.lang.tcl.announce ו- comp.binaries.geos.

למידע נוסף על נושא זה

  • הנה קובץ הכיתה JarResources.java//www.javaworld.com/javatips/javatip49/JarResources.java
  • JARs //www.javasoft.com/products/jdk/1.1/docs/guide/jar/index.html
  • למידע נוסף על תמיכה בארכיון ב- Java, ראה "Java Tip 21 השתמש בקבצי ארכיון כדי להאיץ את טעינת היישומון" //www.javaworld.com/javatips/jw-javatip21.html

סיפור זה, "טיפ Java 49: כיצד לחלץ משאבי Java מארכיוני JAR ו- zip" פורסם במקור על ידי JavaWorld.