تصف هذه المقالة طريقة Java لتحليل ملفات الصور الطبية DCM واستخراج معلومات الملف. شاركه للرجوع إليه ، على النحو التالي:
1. التثبيت
أولاً ، انتقل إلى GitHub لتنزيل الكود المصدر ، ثم قم بتنفيذ تثبيت MVN للتثبيت المحلي. مستودع مافن المركزي ليس لديه الجرة. . بعد التثبيت الناجح ، ما يلي على النحو التالي:
ثم قدم حزمة الجرة في ملف pom.xml:
<Rependency> <roupeD> org.dcm4che </rougeid> <StifactId> dcm4che-core </artifactid> <sophy> 3.3.2 </version> </sependency>
2. فئة الاختبار
/** * projectName: xxx * filename: displaytag.java * packagename: com.xxxx.xxxx.common.util * التاريخ: 2018-03-26 10:07 * حقوق الطبع والنشر (c) 2017-2020 xxx java.io.file ؛ استيراد java.io.ioException ؛ استيراد java.sql.time ؛ import java.util.arrays ؛ استيراد java.util.date ؛ استيراد java.util.logging.level org.dcm4che3.data.elementDictionary ؛ استيراد org.dcm4che3.data.fragments ؛ استيراد org.dcm4che3.data org.dcm4che3.io.dicominputStream ؛ استيراد org.dcm4che3.io.dicomoutputstream ؛ استيراد org.dcm4che3.util.safeclose ؛ import java.awt.image.raster ClassName: DisplayTag * packagename: com.xxxx.xxxx.common.util * description: tag parsing * data: 2018-03-26 خاص dicominputstream din. استاتيكي خاص النتيجة DoubleFactordix ؛ نتيجة سلسلة خاصة = فارغة ؛ نتيجة مزدوجة خاصة 2 = فارغة ؛ سلسلة خاصة = فارغة ؛ سلسلة خاصة NOUNSTRING = NULL ؛ private int val2 = 0 ؛ خاص int valeurreturn ؛ سلسلة خاصة NOUNUNIT = NULL ؛ static static double resultfacteurdix = 0 ؛ قيم مزدوجة خاصة = فارغة ؛ سلسلة خاصة noununitratio = null ؛ خاص dicominputstream dis ؛ char char hex_digits hex_digits = {'0' ، 1 '، 2' ، '3' ، '4' ، '5' ، '6' ، '7' ، '8' ، '9' ، '' ، 'b' ، 'c' ، 'd' ، 'e' ، 'f' ؛ dicomencodingoptions الخاصة encopts = dicomencodingOptions.Default ؛ dict elementDictionary الثابت الخاص = elementDictionary.getStandardElementDictionary () ؛ Public DisplayTag (ملف ملف) {try {setObject (loadDicOmObject (file)) ؛ } catch (ioException ex) {logger.getLogger (displaytag.class.getName ()). log (level.severe ، null ، ex) ؛ }} / ** * اقرأ بيانات التعريف من DICOM 3.0 * param f: ملف الإدخال * regurtibutes * throws ioException * / سمات ثابتة public loaddicomobject (file f) يلقي ioException {if (f == null) {return null ؛ } آخر {dicominputStream dis = new dicominputStream (f) ؛ //attr.setspecificCharCterset("GBK ") ؛ إرجاع dis.readdataset (-1 ، -1) ؛ }} / ** * pum attribute * param obj * / public void setObject (entributes obj) {this.obj = obj ؛ } / ** * إعطاء سمة من البيانات الوصفية * @RETURN * / سمات ثابتة عامة getObject () {return obj ؛ } / ** * عرض بيانات التعريف * param: ملف inout * throws ioException * / public string readtagdicom (ملف الملف) يلقي ioException {din = new dicominputStream (ملف) ؛ object = din.readfileMetAinformation () ؛ قيمة السلسلة = object.toString () ؛ object = din.readdataset (-1 ، -1) ؛ قيمة الإرجاع } / ** * permet d'Afticher l'heure d'Une valeur dicom en Standard International yyyy.mm.dd / تصريح وقت عرض في التنسيق yyyy.mm.dd * param tag: valeur du tag yyyy.mm.dd آخر dd.mm.yyyyy * param valuenoun: "dot" mettre la date en format dd.mm.yyyyy else yyyy mm أو dd mm yyyyy * @return antring le string du tag selon le stander international/ return string date * athrows ioexception */ public string dicomdate (int tagval ، boolean valueBool ، string valuenoun) getObject (). getString (tag) ؛ سلسلة tagDayFomat = formatDate (tagValue ، valueBool ، Valuenoun) ؛ إرجاع tagdayfomat ؛ } آخر {return null ؛ }}/ ** * permet d'Afticher l'heure d'une valeur dicom en international yyyy.mm.dd/ تصريح عرض وقت في metadata لـ yyyy.mm.dd * object * @param tag: valeur du tag/ value of parambool: إذا كان التنسيق الحقيقي yyyy.mm.dd آخر dd.mm.yyyyy * param valuenoun: "dot" mettre la date en format yyyy.mm.dd ou dd.mm.yyyy sinon dd.mm.yyy else yyyy mm أو dd mm yyyy * return antring le string du tag selon le stander international/ return string * @throws ioexception */ public static string dicomd (attibutes tage ، int tag ، formatdate (tagvalue ، valueBool ، valuenoun) ؛ آخر في التنسيق yyyy mm dd أو dd mm yyyyy *return */public static string formatdate (String numero ، boolean valueBool ، string valuenoun) {if (numero.matches ("^[0-9] *$") == true) {// format yyyy.mm.dd لـ (int i = 0 ، j = numero.length () ؛ i <j ؛ i ++) {r.append (numero.charat (i)) ؛ R.Append ('.') ؛ valuenoun.equals ("dot") {r.append ('.') ؛ ) {if (valuenoun == null؟ "dot" == NULL: التالي في الفهرس الأول ، وما إلى ذلك ، بالنسبة لفهرسة الصفيف. GetHeaderDatevalue (سلسلة tagnr) {return getheaderdatevalue (totagint (tagnr)) ؛ تمثيل السلسلة لرقم رأس * على سبيل المثال 0008،0010 إلى عدد صحيح مقابل كـ 0x00080010 * كما هو مستخدم في @see org.dcm4che2 integer.parseint (headernr.replaceall ("،" ، "") ، 16) ؛ TAG of VR = DA * param tagnr: "0000،0010" * param dicomobj * return */ date getheaderdatevalue (string tagnr ، entributes dicomobj) Static String TextDicom (سلسلة num) {num = num.replaceall ("//^+" ، "") في القائمة إلى سلسلة tagValue = arrays.aslist (tagValue2) .ToString () ؛ Object.getStrings (TAG) الفاصل) {StringBuffer = New StringBuffer () ؛ (0008،0030) في وقت الدراسة * (0008،0031) في وقت السلسلة S * (0008،0032) في وقت الاستحواذ S * (0008،0033) في s time time * param tag: give tag * return * throws ioexception */ public string dicomtime (int tag) throws ioexception tagvalue = getString (tag) ؛ (0008،0031) في وقت السلسلة S * (0008،0032) في وقت الاستحواذ * (0008،0033) في وقت الصورة * param tag: إعطاء علامة * return * @throws ioexception */ public string dicomtimetal (int tag) يلقي ioException {if (getObject (). GetObject (). في وقت الصورة * param كائن: metadata * param العلامة: القيمة dicom * @Return سلسلة القيمة * throws ioException */ public string dicomtime2 (سمات الكائن ، int tag) rewrows ioException {string tagvalue = object.getstring (tag) ؛ System.out.println (tagvaluenotdot) ؛ (0008،0033) في وقت الصورة * param الكائن: metadata * param العلامة: القيمة dicom * return string * therwes IoException * يقرأ قيمة int من dicomheader * param tagnr to to read * return as int * / public int getheaderintegervalue (int tagnr) {return getObject (). getint (tagnr ، 0) ؛ "0008،0102#0054،0220" للحصول على مصمم مخطط الترميز بعد تسلسل رمز العرض * inturn int */ public int getheaderIntegerValue (String tagnr) {return getheaderintegervalue (totagint (tagnr)) ؛ يحتوي على string tagnr) {return inventsheadertag (tagnr)) ؛ */ static string public getheadername (int tagnr) {return dict.keywor (tagnr) ؛ } / ** * إرجاع تمثيل السلسلة لحقل الرأس المعطى * إذا كان موجودًا في الرأس * param tagnr * / public string getheader (int tagnr) {try {string dcmele = getObject () Static String toElementString (سلسلة dcmele ، int) {stringbuffer sb = new StringBuffer () ؛ ". إلى الصدفة المقابلة كـ 0x00080010 * كما هو مستخدم في see org.dcm4che2 /** قم بإزالة السلسلة * param num * @ @ @Return */ public Static String Formattime (سلسلة numero) {if (numero.matches ("^[0-9] R.Append (':') ؛ 0 ، j = numero.length () i <j ؛ */Public Double Floor (double a ، int n) {double p = math.pow (10.0 ، n) ؛ resultfactordix = math.pow (النتيجة 3 ، عامل) ؛ dcmobj.getints (tag.pixeldata) ؛ dcmobj * return * throws ioexception */ public byte [] lattricepixeldatabytes (dcmobj) يلقي ioexception LattricePixelDataBytes2 () يلقي IoException {byte [] Raster.getheight () ؛ = Raster.getSampe (y ، 0) ؛ x = 0 ؛ *FilePutStream = FileInptStream جديد (FileInpt) ؛ المريض_ } // system.print (value [0]+"/n") ؛ seq = dcm.getObject (). inportfile: ملف الإدخال * param tagsq: tag vr = sq * param tag: seq.get (0) ؛ PixelComponentPhysicalUnits * * * param النتيجة: Value String */public void (int tag ، string) {if (tag النموذج (آثار فسيولوجية ، آثار دوبلر ، ... ") ؛ كسر ؛ الحالة 3: setNoununit (" Spectral (cw أو pw doppler ") ؛ break ؛ الحالة 2: this.setnoununit (" m-mode (tissue أو flow) ") ؛ Break ؛ Setnounit (تتبع المنطقة "؛ هذا. هذا. هذا. tag.pixelponentPhysicalunits) {val2 = integer.valueof (result) setnounit (cm*pixel/sec. هذا. this.setnounit ("cm*cm*pixel/sec" setNounUnit("Computed Border"); break; case 8: setNounUnit("Integrated Backscatter"); br eak; case 7: setNounUnit("Color bar"); break; case 6: this.setNounUnit("Gray bar"); break; case 5: this.setNounUnit("Color Flow Intensity"); break; case 4: setNounUnit("Color Flow Variance"); break; case 3: هذا التصنيف ") ؛}} آخر {this.setNoununit (" لا شيء أو غير قابل للتطبيق ") ؛}} / ** * enregistre l'unité des heats / pub unity of heat * @param noununit * return this.noununit = noununit * / public string setnunit (string noununit) { L'Unité des items./giving unity of heads * @le nom de l'unité */ public string getNoununit () {return noununit ؛ -PixelComponentPhysicalUnits * * param النتيجة: prend l'unite */ public void unitratiospatial (int tag ، string result) {if (tag == tag.physicalunitsxdirection || tag == tag.physicalunitsydirection || tag. integer.valueof (result) .intvalue () ؛ // switchen en int switch (val2) {case 9: double datepatial1 = getValeurtagiTemDoubleratio ()* setfacteurpuissance (10،1) ؛ setnounitratio (mm*mm.pixel/sec " Setnountratio (MM*Pixel ") ؛ هذا. Break ؛ DATERSPATIAL 4 = GetValeurtagiTeMderatio () /** * prend la valeur نسبة المكانية/وضع نسبة القيمة المكانية * param valuespatial */public double setteragitemdbleratio (Double Datepatial) {return this.valuespatial = dountpatial ؛ getValeurtagItemDoubleratio () {return valudepatial ؛ } / ** * SOTIENT LA VALEUR DE PUISSAND this.noununitratio = noununitratio ؛ des items./giving unity heat * return le nom de l'unité */ public string getNoununitratio () {return noununitratio ؛ }/ ** * prend la valeur interne d'un tag item/ put tag ite * @param result * return */ public string settagitem (string result) {return this.result = result ؛ }/** * donne la valeur du tag rachercher/إعطاء قيمة من العلامة SEEP * regurn le string de la valeur rachercher du tag dans un item */public string getValeurtagItem () {return return ؛ }/ ** * prend la valeur interne d'un tag item/ put the value tag itemù * @return */ public double settagitemdouble (double result2) {return this.result2 = result2 ؛ }/** * donne la valeur du tag rachercher/إعطاء علامة القيمة * regurn le double de la valeur rachercher du tag dans un item */public double getValeurtagItemDouble () {return result2 ؛ } / ** * يقرأ قيمة السلسلة من العلامة dicom (dcm4che2) * param tagnr tag to read * @return as string * reproved reproved the report there reprict repressed en eleme * / 000 regite string elem elem = getObject () ؛ Elem.SetSpecificCharcterset ("GB18030") ؛ String val = elem.getString (tagnr) ؛ if (val == null) {val = "" ؛ } إرجاع فال ؛ } catch (استثناء e) {return "" ؛ }} / ** * يقرأ قيمة سلسلة من العلامة dicom (dcm4che2) * param tagnr tag to to read * @return as string * report the report the report the set en elemencence eleme * / 000 eleme eleme eleme * / 000. {system.out.println (222) ؛ سمات elem = getObject () ؛ Elem.SetSpecificCharcterset ("GB18030") ؛ String [] val = elem.getStrings (tagnr) ؛ إرجاع فال } catch (استثناء e) {return null ؛ }} / ** * يقرأ قيمة السلسلة من dicomheader * param tagnr tag to read * param dcmelement * @return as string * / public string getheaderstringValue (السمات dcmelement ، int tagnr) {try {system.out.println (333) ؛ /* dcmelement.setspecificCharCterseT ("ISO_IR 100") ؛ */ dcmelement.SetSpecificCharcterset ("GB18030") ؛ String val = dcmelement.getString (tagnr) ؛ if (val == null) {val = "" ؛ } إرجاع فال ؛ } catch (استثناء e) {return "" ؛ }} / ** * يقرأ العلامة (المجموعة ، العنصر) * param headernr على سبيل المثال "0018،0050" للحصول على سمك الشريحة <br> * @string * / سلسلة عامة getheaderstringvalue (String headernr) {headernr = headernr.replaceall ("xx" ، "00"). إرجاع getheaderstringValue (totagint (headernr)) ؛ } / ** * إعطاء الوقت علامة ("xxxx ،") * param tagnr * return * / public time getheadertimeValue (String tagnr) {return getheadertimeValue (totagint (tagnr)) ؛ } / ** * إعطاء الوقت علامة * param tagnr * return الوقت * / الوقت العام getheadertimeValue (int tagnr) {string time = getheaderstringValue (tagnr) ؛ if (time.length ()! = 6) {return null ؛ } try {int hour = integer.parseint (time.substring (0،2)) ؛ int min = integer.parseint (time.substring (2،4)) ؛ int sec = integer.parseint (time.substring (4،6)) ؛ إرجاع وقت جديد (ساعة ، دقيقة ، ثانية) ؛ } catch (استثناء e) {} return null ؛ } /** * يسترجع Headertag محدد الموجود داخل علامة Anotehr * أو "0008،0102 ، 0054،0220" للحصول على مصمم مخطط الترميز بعد عرض رمز العرض * sturn string * * param taghierarchy ؛ eg {tag.uid ، tag.sopinstanceuid ، tag.codeMeaning} * return */ public string getheadervalueinsidetag (int [] tagHierarchy) {try {for (int i = 0 ؛ i <tagHierarchy.length-1 ؛ i ++) {return getObject (). }} catch (استثناء e) {string tags = "" ؛ لـ (int i = 0 ؛ i <tagHierarchy.length ؛ i ++) {tags += totagString (tagHierarchy [i]) +"" ؛ } يعود ""؛ } إرجاع فارغ ؛ } / ** * يحول تمثيل int لرقم الرأس * على سبيل المثال 0x00080010 إلى السلسلة المقابلة 0008،0010 * regurn 0008،0010 كسلسلة * / سلسلة ثابتة عامة totagstring (int tagnr) {return Shorttoex (tagnr >> } السلسلة الثابتة العامة ShortToHex (int val) {char [] ch = new char [4] ؛ Shorttohex (Val ، ch ، 0) ؛ إرجاع سلسلة جديدة (الفصل) ؛ } Static Static StringBuffer ShortToHex (int val ، stringbuffer sb) {sb.append (hex_digits [(val >> 12) & 0xf]) ؛ sb.append (Hex_Digits [(Val >> 8) & 0xf]) ؛ sb.append (Hex_digits [(Val >> 4) & 0xf]) ؛ sb.append (Hex_Digits [Val & 0xf]) ؛ إرجاع SB ؛ ) CH [OFF+1] = HEX_DIGITS [(Val >> 8) & 0xf] ؛ CH [OFF+2] = HEX_DIGITS [(Val >> 4) & 0xf] ؛ CH [OFF+3] = Hex_Digits [Val & 0xf] ؛ } / ** * إنشاء إخراج ملف dicom * param fileOutput: إخراج الملف * throws ioException * * * مثال: * * * * * / public void writeTo (file fileOutput ، السمات fmi ، سمات كائن) atsibutes) رمي ioException dos.setencodingOptions (الترميز) ؛ dos.writedataset (FMI ، كائن) ؛ dos.finish () ؛ dos.flush () ؛ } / ** * writting * param fileOutput * param h * param w * throws ioException * / public void writeToSegress (fileOutput ، int h ، int w) يلقي iOexception {dicomoutputstream dos = new dicomoutputStream (ملف جديد (fileOutput +". dcm")) ؛ dos.setencodingOptions (الترميز) ؛ } / ** * إنشاء تراكب في pixeldata * param object * / public void overlaycreate (entributes object) {int position = object.getInt (tag.overlaybitposition ، 0) ؛ if (الموضع == 0) {return ؛ } int bit = 1 << الموضع ؛ int [] pixels = object.getInts (tag.pixeldata) ؛ عدد int = 0 ؛ لـ (int pix: pixels) {int overlay = pix & bit ؛ وحدات البكسل [count ++] = pix - تراكب ؛ } object.setint (tag.pixeldata ، vr.ow ، pixels) ؛ } /*** dicom.SetString (tag.performingPhysicianname ، vr.pn ، "Jean") ؛ dicom.SetString (tag.admittingDiagnoseDescription ، vr.lo ، "chu") ؛ تسلسل seq = dicom.newequence (tag.anatomicregionsequence ، 0) ؛ السمات dicom2 = سمات جديدة () ؛ * param dicom */ public void setItem (السمات DICOM ، int tagequencenkename) {sequence seq = dicom.newequence (tagequencename ، 0) ؛ dicom.SetString (tag.codingschemedesignator ، vr.sh ، "srt") ؛ dicom.setstring (tag.codevalue ، vr.sh ، "t-aa000") ؛ dicom.SetString (tag.codeMeaning ، vr.lo ، "Eye") ؛ seq.add (dicom) ؛ } static void main (string [] args) يلقي الاستثناء {file file = ملف جديد ("c: // users // fendo // documents // wechat files // fen_do // files // 1234.dcm") ؛ DisplayTag d = new DisplayTag (file) ؛ suppressWarnings ("static-access") سمات = d.loaddicomobject (ملف) ؛ // إخراج جميع معلومات السمة system.out.println ("جميع المعلومات:" + attrs) ؛ // GET ROW int row = attrs.getInt (tag.rows ، 1) ؛ // الحصول على عمود أعمدة int = attrs.getInt (tag.columns ، 1) ؛ // نافذة عرض نافذة تعويم win_center = attrs.getFloat (tag.windowCenter ، 1) ؛ float win_width = attrs.getFloat(Tag.WindowWidth, 1); System.out.println("" + "row=" + row + ",columns=" + row + ",row*columns = " + row * columns); String patientName = attrs.getString(Tag.PatientName, ""); System.out.println("Name:" + patientName); //Birthday String patientBirthDate = attrs.getString(Tag.PatientBirthDate, ""); System.out.println("Birthday: " + patientBirthDate); //Institution String institution = attrs.getString(Tag.InstitutionName, ""); System.out.println("Institution: " + institution); //Site String station = attrs.getString(Tag.StationName, ""); System.out.println("Site: " + station); //Manufacturer String Manufacturer = attrs.getString(Tag.Manufacturer, ""); System.out.println("Manufacturer: " + Manufacturer); //Manufacturer Model String ManufacturerModelName = attrs.getString(Tag.ManufacturerModelName, ""); System.out.println("ManufacturerModelName: " + ManufacturerModelName); //Description--Atrial String description = attrs.getString(Tag.StudyDescription, ""); System.out.println("Description--Atrial: " + Description); //Description--Specific String SeriesDescription = attrs.getString(Tag.SeriesDescription, ""); System.out.println("Description--Specific: " + SeriesDescription); //Description time String studyData = attrs.getString(Tag.StudyDate, ""); System.out.println("Description time: " + studyData); byte[] bytename = attrs.getBytes(Tag.PatientName); System.out.println("Name: " + new String(bytename,"gb18030")); byte[] bytesex = attrs.getBytes(Tag.PatientSex); System.out.println("Gender: " + new String(bytesex,"gb18030")); }}输出如下:
所有信息: (0008,0005) CS [ISO_IR 100] SpecificCharacterSet
(0008,0008) CS [ORIGINAL/PRIMARY] ImageType
(0008,0016) UI [1.2.840.10008.5.1.4.1.1.1.1] SOPClassUID
(0008,0018) UI [1.2.840.113619.2.203.4.2147483647.1486521160.448521] SOPInstan
(0008,0020) DA [20170208] StudyDate
(0008,0021) DA [20170208] SeriesDate
(0008,0022) DA [20170208] AcquisitionDate
(0008,0023) DA [20170208] ContentDate
(0008,002A) DT [20170208103237.000000] AcquisitionDateTime
(0008,0030) TM [103154.000] StudyTime
(0008,0031) TM [103158.000] SeriesTime
(0008,0032) TM [103237.000] AcquisitionTime
(0008,0033) TM [103240.000] ContentTime
(0008,0050) SH [T77792] AccessionNumber
(0008,0060) CS [DX] Modality
(0008,0068) CS [FOR PRESENTATION] PresentationIntentType
(0008,0070) LO ["GE Healthcare"] Manufacturer
(0008,0080) LO [HeFei RICH] InstitutionName
(0008,0081) ST [Not Initialized
Not Initialized
HeFei
AnHui
Not Initialize(0008,0090) PN [] ReferringPhysicianName
(0008,1010) SH [082407110134] StationName
(0008,1030) LO [ACHEST] StudyDescription
(0008,103E) LO [Chest] SeriesDescription
(0008,1040) LO [Not Initialized] InstitutionalDepartmentName
(0008,1050) PN [] PerformingPhysicianName
(0008,1090) LO ["Definium 6000"] ManufacturerModelName
(0008,1110) SQ [] ReferencedStudySequence
(0008,1120) SQ [] ReferencedPatientSequence
(0008,2112) SQ [1 Items] SourceImageSequence
>Item #1
>(0008,1150) UI [1.2.840.10008.5.1.4.1.1.1.1.1] ReferencedSOPClassUID
>(0008,1155) UI [1.2.840.113619.2.203.4.2147483647.1486521157.927189] Referenc
(0008,2218) SQ [1 Items] AnatomicRegionSequence
>Item #1
>(0008,0100) SH [T-D3000] CodeValue
>(0008,0102) SH [SNM3] CodingSchemeDesignator
>(0008,0104) LO [Chest] CodeMeaning
(0010,0010) PN [zhang^xiao di] PatientName
(0010,0020) LO [T77792] PatientID
(0010,0030) DA [19860618] PatientBirthDate
(0010,0032) TM [] PatientBirthTime
(0010,0040) CS [F] PatientSex
(0010,1010) AS [030Y] PatientAge
(0010,1030) DS [] PatientWeight
(0011,0010) LO [GEMS_GDXE_FALCON_04]
(0011,1003) UI [1.2.840.113619.2.203.4.2147483647.1486521118.562807]
(0011,1004) CS [SE]
(0011,1005) UI [1.2.840.113619.2.203.4.2147483647.1486521152.970120]
(0011,1006) DS [0.083936]
(0011,1009) SL [0]
...
row=2021,columns=2021,row*columns = 4084441
姓名:zhang^xiao di
生日:19860618
机构:HeFei RICH
站点:082407110134
制造商:"GE Healthcare"
制造商模型:"Definium 6000"
描述--心房:ACHEST
描述--具体:Chest
描述时间:20170208
姓名: zhang^xiao di
性别: F
更多关于java算法相关内容感兴趣的读者可查看本站专题:《Java文件与目录操作技巧汇总》、《Java数据结构与算法教程》、《Java操作DOM节点技巧总结》和《Java缓存操作技巧汇总》
آمل أن يكون هذا المقال مفيدًا لبرمجة Java للجميع.