2015-09-30 12 views
5

का उपयोग करके अवैध अर्ग्यूमेंट अपवाद, मैं बेस 64.java फ़ाइलों को एन्कोड और डीकोड करने के लिए उपयोग करना चाहता था। Encode.wrap(InputStream) और decode.wrap(InputStream) काम किया लेकिन धीरे-धीरे चलाया। तो मैंने निम्नलिखित कोड का इस्तेमाल किया।Java8 Base64 डिकोडर

public static void decodeFile(String inputFileName, 
     String outputFileName) 
     throws FileNotFoundException, IOException { 

    Base64.Decoder decoder = Base64.getDecoder(); 
    InputStream in = new FileInputStream(inputFileName); 
    OutputStream out = new FileOutputStream(outputFileName); 

    byte[] inBuff = new byte[BUFF_SIZE]; //final int BUFF_SIZE = 1024; 
    byte[] outBuff = null; 
    while (in.read(inBuff) > 0) { 
     outBuff = decoder.decode(inBuff); 
     out.write(outBuff); 
    } 
    out.flush(); 
    out.close(); 
    in.close(); 
} 

हालांकि, यह हमेशा फेंकता

Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException: Input byte array has wrong 4-byte ending unit 
    at java.util.Base64$Decoder.decode0(Base64.java:704) 
    at java.util.Base64$Decoder.decode(Base64.java:526) 
    at Base64Coder.JavaBase64FileCoder.decodeFile(JavaBase64FileCoder.java:69) 
    ... 

बाद मैं final int BUFF_SIZE = 3*1024; में final int BUFF_SIZE = 1024; बदल गया है, कोड काम किया। चूंकि "BUFF_SIZE" का उपयोग फ़ाइल को एन्कोड करने के लिए भी किया जाता है, मेरा मानना ​​है कि फ़ाइल एन्कोडेड में कुछ गड़बड़ है (1024% 3 = 1, जिसका अर्थ है कि फाइल के बीच में पैडिंग जोड़े गए हैं)।

इसके अलावा, जैसा कि @ जोन स्कीट और @ टगीर वैलेव ने उल्लेख किया है, मुझे InputStream.read() से वापसी मूल्य को अनदेखा नहीं करना चाहिए। इसलिए, मैंने नीचे कोड को संशोधित किया है।

(हालांकि, मुझे लगता है कि कोड बहुत तेजी से wrap() का उपयोग करने से चलती है उल्लेख करना होगा। मैं गति अंतर पर ध्यान क्योंकि मैं कोडित था और गहन Base64.encodeFile()/decodeFile (प्रयुक्त) से काफी पहले jdk8 जारी किया गया था। अब , मेरे buffed jdk8 कोड अपने मूल कोड के रूप में के रूप में तेजी से चलाता है। तो, मैं नहीं जानता कि क्या wrap() साथ चल रहा है ...)

public static void decodeFile(String inputFileName, 
     String outputFileName) 
     throws FileNotFoundException, IOException 
{ 

    Base64.Decoder decoder = Base64.getDecoder(); 
    InputStream in = new FileInputStream(inputFileName); 
    OutputStream out = new FileOutputStream(outputFileName); 

    byte[] inBuff = new byte[BUFF_SIZE]; 
    byte[] outBuff = null; 
    int bytesRead = 0; 
    while (true) 
    { 
     bytesRead = in.read(inBuff); 
     if (bytesRead == BUFF_SIZE) 
     { 
      outBuff = decoder.decode(inBuff); 
     } 
     else if (bytesRead > 0) 
     { 
      byte[] tempBuff = new byte[bytesRead]; 
      System.arraycopy(inBuff, 0, tempBuff, 0, bytesRead); 
      outBuff = decoder.decode(tempBuff); 
     } 
     else 
     { 
      out.flush(); 
      out.close(); 
      in.close(); 
      return; 
     } 
     out.write(outBuff); 
    } 
} 

@Jon स्कीट और @Tagir Valeev को विशेष धन्यवाद।

उत्तर

5

मुझे दृढ़ता से संदेह है कि समस्या यह है कि आप स्ट्रीम के अंत की जांच के अलावा InputStream.read से वापसी मूल्य को अनदेखा कर रहे हैं। तो यह:

while (in.read(inBuff) > 0) { 
    // This always decodes the *complete* buffer 
    outBuff = decoder.decode(inBuff); 
    out.write(outBuff); 
} 

होना चाहिए

int bytesRead; 
while ((bytesRead = in.read(inBuff)) > 0) { 
    outBuff = decoder.decode(inBuff, 0, bytesRead); 
    out.write(outBuff); 
} 

मैं इस उम्मीद नहीं हैं किसी भी हालांकि wrap का उपयोग कर से अधिक तेजी से किया जाना है।

1

decode.wrap(new BufferedInputStream(new FileInputStream(inputFileName))) का उपयोग करने का प्रयास करें। बफरिंग के साथ यह कम से कम आपके मैन्युअल रूप से तैयार किए गए संस्करण के रूप में तेज़ होना चाहिए।

क्यों आपका कोड काम नहीं करता है: ऐसा इसलिए है क्योंकि अंतिम खंड 1024 बाइट से कम होने की संभावना है, लेकिन आप पूरे byte[] सरणी को डीकोड करने का प्रयास करते हैं। विवरण के लिए @JonSkeet उत्तर देखें।

0

ठीक है, मैं

बदल

"अंतिम पूर्णांक BUFF_SIZE = 1024;"

में

"अंतिम पूर्णांक BUFF_SIZE = 1024 * 3,"

यह काम किया!

तो, मुझे लगता है कि प्रोबैबली में पैडिंग के साथ कुछ गड़बड़ है ... मेरा मतलब है, फ़ाइल को एन्कोड करते समय, (1024% 3 = 1 के बाद) पैडिंग होना चाहिए। और डीकोडिंग के दौरान समस्याएं बढ़ सकती हैं ...

+2

यह एन्कोडिंग का कारण बन सकता है समस्याएं (बेस 64 के रूप में प्रत्येक 3 बाइट्स को 4 में एन्कोड करता है), लेकिन डिकोडिंग समस्याओं का कारण नहीं बनना चाहिए (प्रत्येक 4 बाइट्स को डीकोड करने में 3 में परिवर्तित किया जाता है)। शायद अब आपकी समस्या सिर्फ अधिक छिपी हुई है (उदाहरण के लिए, यह अपवाद की रिपोर्ट नहीं कर सकती है, लेकिन चुपचाप गलत परिणाम उत्पन्न करती है)। –

0
  • आप चाहिए Base64 में बाइट्स आप पढ़ लिया है, इस के बगल की संख्या,
  • आप सुनिश्चित करें कि आपके बफर आकार 3 के लिए विभाज्य है होना चाहिए, कारण रिकॉर्ड करता है, हर 3 बाइट्स चार उत्पादन (64 2 है^6, और 3 * 8 बराबर 4 * 6), ऐसा करके, आप पैडिंग समस्याओं से बच सकते हैं। (इस तरह आपके आउटपुट में "=" का गलत अंत नहीं होगा)
संबंधित मुद्दे