سؤال

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

أقوم أيضًا بإرفاق جزء من الكود الخاص بي للرجوع إليه حتى تتمكن من إرشادي وفقًا لذلك.

private void zip() {
    int BUFFER_SIZE = 4096;
    byte[] buffer = new byte[BUFFER_SIZE];

    try {
        // Create the ZIP file
        String outFilename = "H:\\OUTPUT.zip";
        ZipOutputStream out = new ZipOutputStream(new FileOutputStream(
                outFilename));

        // Compress the files
        for (int i : list.getSelectedIndices()) {
            System.out.println(vector.elementAt(i));
            FileInputStream in = new FileInputStream(vector.elementAt(i));
            File f = vector.elementAt(i);

            // Add ZIP entry to output stream.
            out.putNextEntry(new ZipEntry(f.getName()));

            // Transfer bytes from the file to the ZIP file
            int len;

            while ((len = in.read(buffer)) > 0) {
                buffer = org.apache.commons.codec.binary.Base64
                        .encodeBase64(buffer);
                out.write(buffer, 0, len);

            }

            // Complete the entry
            out.closeEntry();
            in.close();

        }

        // Complete the ZIP file
        out.close();
    } catch (IOException e) {
        System.out.println("caught exception");
        e.printStackTrace();
    }
}
هل كانت مفيدة؟

المحلول

عادةً ما تكون البيانات المشفرة BASE64 أطول من المصدر، ولكنك تستخدم طول البيانات المصدر للكتابة المشفرة إلى تدفق الإخراج.

لقد استخدمت حجم المصفوفة التي تم إنشاؤها بدلاً من المتغير الخاص بك len.

الإشعار الثاني - لا تعيد التعريف buffer في كل مرة تقوم فيها بتشفير بايت.فقط اكتب النتيجة في الإخراج.

 while ((len = in.read(buffer)) > 0)  {                         
     byte [] enc = Base64.encodeBase64(Arrays.copyOf(buffer, len));
     out.write(enc, 0, enc.length);
 }

تحديث:يستخدم المصفوفات.نسخ(...) لتعيين طول المخزن المؤقت للإدخال للتشفير.

نصائح أخرى

مشكلتك الرئيسية هي أنه لا يمكن تطبيق ترميز base64 بشكل جماعي (خاصة تطبيق apache-commons).تزداد هذه المشكلة سوءًا لأنك لا تعرف حتى حجم الكتل الخاصة بك لأن ذلك يعتمد على البايتات التي تقرأها in.read(..).

لذلك لديك بديلان:

  1. قم بتحميل الملف الكامل إلى الذاكرة ثم قم بتطبيق ترميز base64.
  2. استخدام تطبيق بديل لتشفير Base64 يعمل على أساس الدفق (يبدو أن مشروع Apache Batik يحتوي على مثل هذا التنفيذ: org.apache.batik.util.Base64EncoderStream)

عند قراءة محتوى الملفات في المخزن المؤقت تحصل عليه Len بايت.عندما ترميز Base64 هذا تحصل على أكثر من Bytes Len ، ولكنك لا تزال تكتب فقط Len بايت إلى الملف.هذه الفاصوليا التي سيتم اقتطاع الجزء الأخير من قطع القراءة الخاصة بك.

أيضا، إذا كان قرأتك لا تملأ المخزن المؤقت بأكمله، فلا يجب أن ترميز Base64 أكثر من بايت Len كما ستجري خلاف ذلك 0S في حشوة البايت الأخير.

يجمع بين المعلومات أعلاه وهذا يعني أنه يجب عليك أن تقوم Base64 بتشفير الملف بأكمله (اقرأ كل شيء في بايت []) ما لم يكن بإمكانك ضمان أن كل قطعة تقرأها يمكن أن تناسب تماما في رسالة مشفرة Base64.إذا كانت ملفاتك ليست كبيرة جدا، فسوف أوصي بقراءة الملف بأكمله.

مشكلة أصغر هي أنه عند القراءة في حلقة الخاص بك، يجب عليك التحقق من "> -1"، وليس "> 0"، ولكن كثف حالته أنه لا يحدث فرقا.

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