2012-11-17 26 views
5

मैं क्लासफ़ाइल को बदलने के लिए एएसएम नामक एक बाइटकोड लाइब्रेरी का उपयोग कर रहा हूं, तो मैं क्लास फाइलों से भरे फ़ोल्डर के बजाय प्रत्येक क्लासफ़ाइल को एक जार फ़ाइल में वापस लिखना चाहता हूं। मैं इस कोड चलाने ऐसा करते हैं:अमान्य प्रविष्टि संपीड़ित आकार

मेरे समस्या तब होती है जब एक ZipException की उम्मीद आकार नहीं होने के लिए फेंक

java.util.zip.ZipException: invalid entry compressed size (expected 695 but got 693 bytes) 
    at java.util.zip.ZipOutputStream.closeEntry(Unknown Source) 
    at org.steinburg.client.accessor.Accessor.accessJar(Accessor.java:64) 
    at org.steinburg.client.accessor.Accessor.<init>(Accessor.java:41) 
    at Loader.main(Loader.java:5) 


package org.steinburg.client.accessor; 

import java.io.DataInputStream; 
import java.io.File; 
import java.io.FileOutputStream; 
import java.io.InputStream; 
import java.util.Enumeration; 
import java.util.jar.JarEntry; 
import java.util.jar.JarFile; 
import java.util.jar.JarOutputStream; 

import org.objectweb.asm.ClassReader; 
import org.objectweb.asm.ClassWriter; 

public class Accessor { 

private String input; 
private File inFile; 
private JarEntry jarEntry; 
private JarFile jarFile; 
private Enumeration<JarEntry> entries; 
private InputStream is; 

private String out; 
private File outFile; 
private FileOutputStream fos; 
private JarOutputStream jos; 

private byte[] bytes; 

public Accessor(){ 
    try{ 
     input = new String("Input Jar.jar"); 
     inFile = new File(input); 
     jarFile = new JarFile(inFile); 
     entries = jarFile.entries(); 
     out = new String("Output Jar.jar"); 
     outFile = new File(out); 
     fos = new FileOutputStream(outFile); 
     jos = new JarOutputStream(fos); 
     accessJar(); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 

protected final void accessJar(){ 
    try { 
     while (entries.hasMoreElements()){ 
      jarEntry = entries.nextElement(); 
      is = jarFile.getInputStream(jarEntry); 
      if (jarEntry.getName().endsWith(".class")){ 
       ClassReader cr = new ClassReader(is); 
       ClassWriter cw = new ClassWriter(cr, 0); 
       FieldAdapter fa = new FieldAdapter(cw); 
       cr.accept(fa, 0); 
       bytes = cw.toByteArray(); 
      } else { 
       bytes = readBytes(is); 
      } 
      JarEntry je = new JarEntry(jarEntry); 
      jos.putNextEntry(je); 
      jos.write(bytes); 
      jos.closeEntry(); 
     } 
     jos.close(); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 

protected byte[] readBytes(InputStream inputStream){ 
    try{ 
     DataInputStream reader = new DataInputStream(inputStream); 
     byte[] toReturn = new byte[reader.available()]; 
     reader.readFully(toReturn); 
     reader.close(); 
     return toReturn; 
    } catch (Exception e){ 
     e.printStackTrace(); 
     return null; 
    } 
} 

} 

ClassReader, ClassWriter (पुस्तकालय के प्रत्येक भाग), और FieldAdapter (बनाई गई है, यानी अपने आप से) बस कोड को वेदी, और पूरे वर्ग के बाइट प्राप्त करने के लिए मैं cw.toByteArray() का उपयोग करता हूं। बाइटकोड मैनिपुलेशन के लिए कोई समस्या नहीं है, यह सिर्फ एक जारऑटपुटस्ट्रीम के माध्यम से एक नई जार फ़ाइल के लिए लेखन है। किसी को भी इस समस्या को हल करने के लिए जाना जाता है?

+1

जो विधि इस अपवाद फेंकता से अन्य सभी विशेषताओं कॉपी हो जाएगा? क्या आप पूरे स्टैक ट्रेस पोस्ट कर सकते हैं? – ShyJ

उत्तर

8

समस्याग्रस्त लाइन यह है:

JarEntry je = new JarEntry(jarEntry); 

यह भी संकुचित आकार कॉपी जाएगा।

जब तक आप नाम के अलावा अन्य क्षेत्रों के संरक्षण के बारे में परवाह है, तो आप this constructor का उपयोग करें और केवल फ़ाइल नाम प्रदान करते हैं, इस के रूप में करना चाहिए:

JarEntry je = new JarEntry(jarEntry.getName()); 

संकुचित आकार फिर स्वचालित रूप से गणना की जाएगी।

+0

काम किया 100% धन्यवाद –

4

इस तरह से यह जार विशेषताओं और अन्य मेटा जानकारी की प्रतिलिपि नहीं करेगा। समस्या तब होती है जब प्रारंभ में पैक होने के बाद जार/ज़िप फ़ाइल संशोधित होती है।

आप ऐसा कर सकते हैं:

JarEntry je = new JarEntry(jarEntry); 
je.setCompressedSize(-1); 

इस प्रविष्टि के आकार का कारण होगा पुनर्गणना किया जाना है और आप मूल jarEntry