1. نظرة عامة
سيوضح هذا البرنامج التعليمي كيفية قراءة الملفات الكبيرة بكفاءة في Java. جافا - العودة إلى الأساسيات.
2. اقرأ في الذاكرة
الطريقة القياسية لقراءة خطوط الملفات هي القراءة في الذاكرة. يوفر كل من الجوافة و ApacheCommonsio طرقًا لقراءة خطوط الملفات بسرعة على النحو التالي:
Files.readLines(new File(path), Charsets.UTF_8);
FileUtils.readLines(new File(path));
تكمن المشكلة في هذه الطريقة في أن جميع خطوط الملف يتم تخزينها في الذاكرة ، وعندما يكون الملف كبيرًا بما يكفي ، فإنه سيؤدي بسرعة إلى إلقاء البرنامج على استثناء OutofMemoryerror.
على سبيل المثال: اقرأ ملفًا بحوالي 1G:
testpublic void givenusingguava_wheniteratingafile_thenworks () يلقي ioException {string path = ... files.readlines (ملف جديد (مسار) ، charsets.utf_8) ؛}لا تأخذ هذه الطريقة سوى كمية صغيرة من الذاكرة في البداية: (تستهلك حوالي 0 ميجابايت من الذاكرة)
[Main] Info org.baeldung.java.corejavaiounittest - إجمالي الذاكرة: 128 ميغابايت [رئيسية] معلومات org.baeldung.java.corejavaiounittest - ذاكرة مجانية: 116 ميغابايت
ومع ذلك ، عندما تتم قراءة جميع الملفات في الذاكرة ، يمكننا أن نرى أخيرًا (يتم استهلاك حوالي 2 جيجابايت من الذاكرة):
[Main] Info org.baeldung.java.corejavaiounittest - إجمالي الذاكرة: 2666 ميغابايت [رئيسية] معلومات org.baeldung.java.corejavaiounittest - ذاكرة حرة: 490 ميغابايت
هذا يعني أن هذه العملية تستهلك حوالي 2.1 جيجابايت من الذاكرة - والسبب بسيط: الآن يتم تخزين جميع خطوط الملف في الذاكرة.
إن وضع جميع محتويات ملف في الذاكرة سوف ينفد بسرعة من الذاكرة المتاحة - بغض النظر عن حجم الذاكرة الفعلية المتاحة ، وهذا واضح.
بالإضافة إلى ذلك ، لا نحتاج عادةً إلى وضع جميع خطوط الملف في الذاكرة في وقت واحد - بدلاً من ذلك ، نحتاج فقط إلى اجتياز كل سطر من الملف ، ثم القيام بالمعالجة المقابلة ، ورميها بعيدًا بعد المعالجة. لذلك ، هذا بالضبط ما سنفعله - التكرار عبر الصفوف ، بدلاً من وضع جميع الصفوف في الذاكرة.
3. دفق الملف
الآن دعونا نلقي نظرة على هذا الحل - سنستخدم فئة java.util.scanner لمسح محتويات الملف وقراءتها بشكل مستمر سطر:
fileInputStream inputStream = null ؛ scanner sc = null ؛ حاول {inputStream = جديد fileInputStream (path) ؛ SC = ماسح ضوئي جديد (inputStream ، "UTF-8") ؛ بينما (sc.hasNextLine ()) {string line = sc.nextline () ؛ // system.out.println (line) ؛ } // لاحظ أن الماسح الضوئي يقمع الاستثناءات إذا (sc.ioException ()! = null) {throw sc.ioException () ؛ }} أخيرًا {if (inputStream! = null) {inputStream.close () ؛ } if (sc! = null) {sc.close () ؛ }}سوف يعبر هذا الحل جميع الخطوط في الملف - مما يسمح بمعالجة كل سطر دون الإشارة إليه. على أي حال ، لم يتم تخزينهم في الذاكرة: (تم استهلاك حوالي 150 ميجابايت من الذاكرة)
[Main] Infoorg.Baeldung.java.corejavaiounittest-totalmemory: 763MB
[Main] Infoorg.baeldung.java.corejavaiounittest-freememory: 605MB
4. دفق ApacheCommonsio
يمكنك أيضًا استخدام مكتبة Commonsio لتنفيذها ، باستخدام Lineiterator المخصصة التي توفرها المكتبة:
lineIterator it = fileUtils.lineIrator (thefile ، "utf-8") ؛ حاول {بينما (it.hasNext ()) {string line = it.nextline () ؛ // افعل شيئًا باستخدام السطر}} أخيرًا {lineIratorator.Closequietly (it) ؛}نظرًا لأن الملف بأكمله لا يتم تخزينه في الذاكرة ، فإن هذا يؤدي إلى استهلاك ذاكرة محافظة إلى حد ما: (يتم استهلاك حوالي 150 ميجابايت من الذاكرة)
[Main] Infoo.B.Java.CorejavaioIntegrationTest-Totalmemory: 752MB
[Main] Infoo.B.Java.CorejavaioIntegrationTest-Freememory: 564MB
5. الخلاصة
تصف هذه المقالة القصيرة كيفية معالجة الملفات الكبيرة دون القراءة المتكررة ونفاد الذاكرة - وهذا يوفر حلاً مفيدًا لمعالجة الملفات الكبيرة.
يتم تنفيذ كل هذه الأمثلة ومقتطفات التعليمات البرمجية المتاحة في مشروع GitHub الخاص بي - هذا مشروع قائم على الكسوف ، لذلك يجب استيراده وتشغيله بسهولة.
ما ورد أعلاه هو كل محتوى هذه المقالة حول قراءة Java الفعالة للملفات الكبيرة. آمل أن يكون ذلك مفيدًا للجميع. يمكن للأصدقاء المهتمين الاستمرار في الرجوع إلى الموضوعات الأخرى ذات الصلة على هذا الموقع. إذا كانت هناك أي أوجه قصور ، فيرجى ترك رسالة لإشارةها. شكرا لك يا أصدقائك لدعمكم لهذا الموقع!