2014-10-04 3 views
3

Я хотел бы обновить содержимое текстового файла, находящегося внутри zip-файла.Изменение содержимого файла записи в zipfile

Я не могу узнать, как это сделать, а приведенный ниже код работает неправильно.

Может спасибо за помощь!

import java.util.zip.ZipFile 
import java.util.zip.ZipEntry 
import java.util.zip.ZipOutputStream 

String zipFileFullPath = "C:/path/to/myzipfile/test.zip" 

ZipFile zipFile = new ZipFile(zipFileFullPath) 
ZipEntry entry = zipFile.getEntry ("someFile.txt") 

if(entry){ 
    InputStream input = zipFile.getInputStream(entry) 
    BufferedReader br = new BufferedReader(new InputStreamReader(input, "UTF-8")) 

    String s = null 
    StringBuffer sb = new StringBuffer() 

    while ((s=br.readLine())!=null){ 
     sb.append(s) 
    } 

    sb.append("adding some text..") 


    ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFileFullPath)) 
    out.putNextEntry(new ZipEntry("someFile.txt")); 

    int length 


    InputStream fin = new ByteArrayInputStream(sb.toString().getBytes("UTF8")) 

    while((length = fin.read(sb)) > 0) 
    { 
      out.write(sb, 0, length) 
    }    

    out.closeEntry() 

} 

ответ

3

Что именно не работает? Есть ли какое-либо исключение?

Насколько я знаю, изменить zip-файл невозможно in situ. Следующий сценарий перезаписывает файл и, если требуется, обрабатывается - изменяет его.

import java.util.zip.* 

def zipIn = new File('lol.zip') 
def zip = new ZipFile(zipIn) 
def zipTemp = File.createTempFile('out', 'zip') 
zipTemp.deleteOnExit() 
def zos = new ZipOutputStream(new FileOutputStream(zipTemp)) 
def toModify = 'lol.txt' 

for(e in zip.entries()) { 
    if(!e.name.equalsIgnoreCase(toModify)) { 
     zos.putNextEntry(e) 
     zos << zip.getInputStream(e).bytes 
    } else { 
     zos.putNextEntry(new ZipEntry(toModify)) 
     zos << 'lollol\n'.bytes 
    } 
    zos.closeEntry() 
} 

zos.close() 
zipIn.delete() 
zipTemp.renameTo(zipIn) 

UPDATE

я был не прав. Можно изменить файл zip in situ, но ваше решение будет omit другие файлы, которые были заархивированы. Выходной файл будет содержать только один файл - файл, который вы хотите изменить. Я также предполагаю, что файл был поврежден из-за того, что не вызывал close() на out.

Ниже You сценарий немного изменен (более groovier):

import java.util.zip.* 

def zipFileFullPath = 'lol.zip' 
def zipFile = new ZipFile(zipFileFullPath) 
def entry = zipFile.getEntry('lol.txt') 

if(entry) { 
    def input = zipFile.getInputStream(entry) 
    def br = new BufferedReader(new InputStreamReader(input, 'UTF-8')) 
    def sb = new StringBuffer() 

    sb << br.text 
    sb << 'adding some text..' 

    def out = new ZipOutputStream(new FileOutputStream(zipFileFullPath)) 
    out.putNextEntry(new ZipEntry('lol.txt')) 

    out << sb.toString().getBytes('UTF8') 
    out.closeEntry() 
    out.close() 
} 
+0

Спасибо за вашу помощь Opal. Ваше первое решение выглядит великолепно, но по какой-то причине ничего не происходит, zipfile вообще не изменяется. – user955732

+0

Почтовый файл не удаляется. Временной файл выглядит нормально. – user955732

+0

Я тестировал Mac OS. Пожалуйста, дайте мне знать, если он решит проблему. Я могу проверить еще раз. – Opal

4

лишь некоторые незначительные изменения в @ ответ опала, Я просто:

  • используются заводной методы, где возможные
  • упакованные по методу

Groovy Snippet

void updateZipEntry(String zipFile, String zipEntry, String newContent){ 
    def zin = new ZipFile(zipFile) 
    def tmp = File.createTempFile("temp_${System.nanoTime()}", '.zip') 
    tmp.withOutputStream { os -> 
     def zos = new ZipOutputStream(os) 
     zin.entries().each { entry -> 
      def isReplaced = entry.name == zipEntry 
      zos.putNextEntry(isReplaced ? new ZipEntry(zipEntry) : entry) 
      zos << (isReplaced ? newContent.getBytes('UTF8') : zin.getInputStream(entry).bytes) 
      zos.closeEntry() 
     } 
     zos.close() 
    } 
    zin.close() 
    assert new File(zipFile).delete() 
    tmp.renameTo(zipFile) 
} 

Использование

updateZipEntry('/tmp/file.zip', 'META-INF/web.xml', '<foobar>new content!</foobar>') 
Смежные вопросы