سؤال

أنا أتطلع إلى الكتابة إلى ملف Excel (.xls MS Excel 2003) باستخدام Java برمجيا. قد تحتوي ملفات إخراج Excel على 200000 صف أو 200000 صف أخطط لتنقسم عدد الأوراق (صفوف 64 كيلويا لكل ورقة، بسبب حد Excel).

لقد حاولت استخدام Apis APACHE POI ولكن يبدو أنه خنزير ذاكرة بسبب طراز كائن API. أنا أجبر على إضافة خلايا / أوراق إلى كائن المصنف في الذاكرة وفقط بمجرد إضافة جميع البيانات، يمكنني كتابة المصنف إلى ملف! فيما يلي عينة من كيفية توصي Apache بجهاز إرسال ملفات Excel باستخدام API:

Workbook wb = new HSSFWorkbook();
Sheet sheet = wb.createSheet("new sheet");

//Create a row and put some cells in it
Row row = sheet.createRow((short)0);

// Create a cell and put a value in it.
Cell cell = row.createCell(0);
cell.setCellValue(1);

// Write the output to a file
FileOutputStream fileOut = new FileOutputStream("workbook.xls");
wb.write(fileOut);
fileOut.close();

من الواضح أن الكتابة ~ 20K الصفوف (مع وجود حوالي 10-20 أعمدة في كل صف) تعطيني "java.lang.lang.outofmemory المروع: جافا كومة الفضاء".

لقد حاولت زيادة حجم Heapsize الأولي JVM وماكس كومة باستخدام معلمات XMS و XMX ك XMS512M و XMX1024. لا يزال غير قادر على كتابة أكثر من 150 كيلو صفوف إلى الملف.

أنا أبحث عن طريقة للدفق إلى ملف Excel بدلا من بناء الملف بأكمله في الذاكرة قبل كتابةه إلى القرص الذي نأمل أن يوفر الكثير من استخدام الذاكرة. سيكون موضع تقدير أي API أو الحلول البديلة، لكنني مقصور على استخدام جافا. شكرا! :)

هل كانت مفيدة؟

المحلول

جميع واجهات برمجة التطبيقات جافا الحالية تحاول بناء المستند بأكمله في ذاكرة الوصول العشوائي مرة واحدة. حاول كتابة ملف XML يتوافق مع تنسيق ملف XSLX الجديد بدلا من ذلك. للحصول على البدء، أقترح بناء ملف صغير في النموذج المطلوب في Excel وحفظه. ثم افتحها وفحص الهيكل واستبدال الأجزاء التي تريدها.

ويكيبيديا لديه مقال جيد حول التنسيق العام.

نصائح أخرى

حاول استخدام SXSSF. مصنف، وهذا أمر عظيم وثائق XLS ضخمة، وثيقة بناءها ولا تأكل الكبش على الإطلاق، باستخدام Nio

اضطررت إلى تقسيم ملفاتي إلى عدة ملفات Excel من أجل التغلب على استثناء مساحة الكومة. أحسب أنه حول صفوف 5 كيلو بايت مع 22 أعمدة كان حول هذا الموضوع، لذلك قمت فقط بمنطقتي بحيث يكون كل صف 5K أود أن أنهي الملف، وبدء تشغيل ملفات جديدة فقط والملفات وفقا لذلك.

في الحالات التي كان لدي فيها صفوف 20K + سيكون لدي 4 ملفات مختلفة تمثل البيانات.

إلقاء نظرة على HSSF Serializer. من مشروع شرنقة.

يمسك Serializer HSSF أحداث SAX وإنشاء جدول بيانات بتنسيق XLS المستخدمة من قبل Microsoft Excel

هناك أيضا Jexcelapi، لكنها تستخدم المزيد من الذاكرة. أعتقد أنه يجب عليك إنشاء ملف .csv وفتحه في Excel. يتيح لك تمرير الكثير من البيانات، لكنك لن تكون قادرا على القيام بأي "سحر إكسل".

النظر في استخدام تنسيق CSV. بهذه الطريقة لا تقتصر على الذاكرة بعد الآن، ربما فقط أثناء إعداد بيانات CSV، ولكن يمكن القيام بذلك بكفاءة أيضا، على سبيل المثال، من مجموعات فرعية من الصفوف من DB باستخدام DB LIMIT/OFFSET واكتبها على الفور إلى ملف بدلا من حذف محتويات جدول DB بالكامل في ذاكرة Java قبل كتابة أي سطر. سيزداد الحد من Excel من الصفوف المبلغ في واحدة "ورقة" إلى حوالي مليون.

ومع ذلك، إذا كانت البيانات تأتي فعلا من DB، فسأعيد النظر للغاية إذا كانت Java هي الأداة المناسبة لهذا. معظم DB لائق لديها وظيفة تصدير إلى CSV التي يمكن أن تفعل هذه المهمة أكثر فعالية بشكل شبه أوثل كثيرا. في حالة مثل MySQL، يمكنك استخدام LOAD DATA INFILE أمر لهذا.

قمنا بتطوير مكتبة Java لهذا الغرض وتتوفر حاليا كمشروع مفتوح المصدر https://github.com/jbaliuka/x4j-analytic. وبعد نستخدمها للإبلاغ التشغيلي. نوفر ملفات Excel ضخمة، يجب أن يعمل ~ 200،000 بدون مشاكل، يتجاوز Excel لفتح مثل هذه الملفات أيضا. يستخدم رمزنا POI لتحميل القالب ولكن يتم تشغيل المحتوى الذي تم إنشاؤه مباشرة إلى ملف بدون XML أو طبقة نموذج كائن في الذاكرة.

هل تحدث مشكلة الذاكرة هذه عند إدراج البيانات في خلية، أو عند إجراء حساب / جيل بيانات؟

إذا كنت ستقوم بتحميل الملفات في Excel تتكون من تنسيق قالب ثابت محدد مسبقا، فاستخدم بشكل أفضل لحفظ القالب وإعادة استخدام وقت متعدد. تحدث حالات القالب عادة عند قيامك بتوليد تقرير المبيعات اليومية أو إلخ ...

آخر، في كل مرة تحتاج فيها إلى إنشاء صف جديد، حدود، عمود وما إلى ذلك من الصفر.

حتى الآن، Apache Poi هو الاختيار الوحيد الذي وجدته.

"بوضوح، الكتابة ~ 20k الصفوف (مع وجود أعمدة 10-20 في كل صف) يعطيني" java.lang.outofmemoryerror ": جافا كومة المساحة". "

"Enterprise IT"

ما يمكنك القيام به- أداء إدخال بيانات الدفعات. قم بإنشاء جدول QueuEtask، في كل مرة بعد إنشاء صفحة واحدة، واستريح لمدة ثوان، ثم استمر في الجزء الثاني. إذا كنت تقلق بشأن تغييرات البيانات الديناميكية أثناء مهمة انتظارك، فيمكنك أولا الحصول على المفتاح الأساسي في Excel (عن طريق إخفاء وعرض العمود من عرض المستخدم). سيتم إدراج التشغيل الأول المفتاح الأساسي، ثم سيتم تشغيل قائمة الانتظار الثانية فصاعدا من المفكرة والقيام بجزء المهمة حسب جزء.

لقد فعلنا شيئا مشابها تماما، نفس القدر من البيانات، وكان علينا التبديل إلى Jexcelapi لأن POI ثقيلة للغاية على الموارد. جرب Jexcelapi، لن تندم عليه عندما تضطر إلى التعامل مع ملفات Excel الكبيرة!

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top