Apache Commons ZipArchiveOutputStream прерывается при добавлении имен файлов без символов ASCII - PullRequest
2 голосов
/ 27 октября 2010

Я использую org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream для добавления файлов из хранилища Subversion. Это прекрасно работает, пока я не использую немецкие умлауты (ä, ö, ü) или любые другие специальные символы в имени файла. Мне интересно, какой самый быстрый способ заставить его принимать символы не ASCII?

def zip(repo: SVNRepository, out: OutputStream, url: String, resourceList: Seq  
       [SVNResource]) {
  val zout = new ZipArchiveOutputStream(new BufferedOutputStream(out))
  zout.setEncoding("Cp437");
  zout.setFallbackToUTF8(true);
  zout.setUseLanguageEncodingFlag(true);
  zout.setCreateUnicodeExtraFields(ZipArchiveOutputStream.UnicodeExtraFieldPolicy.NOT_ENCODEABLE);
  try {
    for (resource <- resourceList) {
      addFileToStream(repo, zout, resource)
    }
  }
  finally {
    zout.finish
    zout.close
  }
}

private def addFileToStream(repo: SVNRepository, zout: ZipArchiveOutputStream, resource:SVNResource): ZipArchiveOutputStream = {
  val entry = resource.entry
  val url = YSTRepo.getAbsolutePath(entry)
  if (FILE == entry.getKind.toString) {
    val file = new File(url)
    val zipEntry = new ZipArchiveEntry(file, url)   
    zout.putArchiveEntry(zipEntry)
    val baos = new ByteArrayOutputStream()
    val fileprops = new SVNProperties()
    repo.getFile(url, -1, fileprops, baos)
    IOUtils.copy(new ByteArrayInputStream(baos.toByteArray), zout)
    zout.closeArchiveEntry
  } else if (DIR == entry.getKind.toString) {
    if (resource.hasChildren) {
      val dirProps = new SVNProperties()
      val entries = repo.getDir(url, -1, dirProps, new java.util.ArrayList[SVNDirEntry])
      for (child <- SVNResource.listDir(repo, entries.toList.asInstanceOf[Seq SVNDirEntry]])) {
        addFileToStream(repo, zout, child)
      }
    }
  }
  zout
}

Ответы [ 3 ]

3 голосов
/ 27 октября 2010

Я решил проблему, установив

UnicodeExtraFieldPolicy.NOT_ENCODEABLE 

до

UnicodeExtraFieldPolicy.ALWAYS

Имена файлов теперь отображаются правильно с использованием Linux-Unzip, Windows-Compressed-Folders, IZArc и WINZIP.

2 голосов
/ 27 октября 2010

Судя по вашим комментариям, реальная проблема заключается в программе Linux unzip и / или кодировке, поддерживаемой вашей файловой системой Linux. Одним из решений является передача опции -U для распаковки, которая будет экранировать любые символы Юникода в именах файлов.

При этом я также рекомендую удалить следующие строки при написании ZIP-файла:

zout.setEncoding("Cp437");
zout.setFallbackToUTF8(true);
zout.setUseLanguageEncodingFlag(true);

И замените их следующим:

zout.setEncoding("UTF-8");

Это должно привести к максимальной переносимости.

0 голосов
/ 27 октября 2010

Вы можете сначала попробовать передать имя файла через URLEncoder: http://download.oracle.com/javase/6/docs/api/java/net/URLEncoder.html

Это гарантирует, что заархивированное имя файла будет чисто ASCII

При чтении обратно используйте URLDecoder для восстановления полного набора символов UFT-8: http://download.oracle.com/javase/6/docs/api/java/net/URLDecoder.html

...