[JAVA] [Kotlin] Compression ZIP des fichiers japonais

introduction

Utilisé lors de la compression ZIP, c'est-à-dire avec ZipOutputStream La valeur par défaut du jeu de caractères est UTF-8.

Le nom de fichier japonais pour Windows est MS932, donc s'il est laissé tel quel, il sera brouillé lors de la décompression avec Windows. Par conséquent, spécifiez Charset dans ZipOutputStream pour éviter les caractères déformés. Il existe de nombreux articles similaires en Java, mais peu en Kotlin, je vais donc les supprimer.

Je ne suis pas si familier avec Kotlin (Java) que je ne sais pas comment utiliser FileInputStream, alors j'apprécierais que vous m'apprendriez une meilleure façon de l'écrire.

Ce que vous pouvez voir dans cet article

Comment compresser ZIP (support japonais) à l'aide de Kotlin.

Articles que j'ai utilisés comme référence

code

import java.io.BufferedOutputStream
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
import java.nio.charset.Charset
import java.util.zip.ZipEntry
import java.util.zip.ZipOutputStream

/**
 *ZIP archive les fichiers dans la ArrayList spécifiée et les crée dans le chemin spécifié.
 *Le code de caractère par défaut est Shift_Puisqu'il s'agit de JIS, les noms de fichiers japonais peuvent également être pris en charge.
 *
 * @param fromFiles Liste des fichiers à compresser.(Exemple; {C:/sample1.txt, C:/sample2.txt} )
 * @param toZipFile Spécifiez le nom du fichier compressé avec le chemin complet.(Exemple: C:/sample.zip )
 * @param charset Jeu de caractères utilisé lors de la conversion en Zip. * 1
 */
fun zipFiles(fromFiles: List<File>, toZipFile: File, charset: Charset = Charset.forName("MS932")) {
    try {
        //Si vous utilisez use, la ressource sera fermée automatiquement à la fin de l'étendue.
        //Dans le premier argument de ZipOutputStream, spécifiez le fichier à compresser.
        //Si le deuxième argument de ZipOutputStream est vide, Charset est UTF-Ce sera 8.
        ZipOutputStream(BufferedOutputStream(FileOutputStream(toZipFile)), charset).use { zipOutputStream ->
            fromFiles.forEach { file ->
                if (file.isFile) {
                    archiveFile(zipOutputStream, file, file.name)
                } else if (file.isDirectory) {
                    archiveDirectory(zipOutputStream, file, file)
                }
            }
        }
    } catch (e: Exception) {
        //La gestion des erreurs.
    }
}

/**
 *ZIP archive les fichiers dans la ArrayList spécifiée et les crée dans le chemin spécifié.
 *Le code de caractère par défaut est Shift_Puisqu'il s'agit de JIS, les noms de fichiers japonais peuvent également être pris en charge.
 *
 * @param zipOutputStream Stream pour écrire targetFile.
 * @param baseFile Le fichier racine du répertoire à compresser.
 * @param targetFile Le répertoire à compresser.
 */
fun archiveDirectory(zipOutputStream: ZipOutputStream, baseFile: File, targetFile: File) {
    targetFile.listFiles()?.forEach { file ->
        if (file.isDirectory) {
            archiveDirectory(zipOutputStream, baseFile, file)
        } else if (file.isFile) {
            //Étant donné que entryName doit être spécifié comme chemin relatif, obtenez le chemin relatif vers baseFile.
            val relativeEntryName = file.toRelativeString(baseFile.parentFile)
            archiveFile(zipOutputStream, file, relativeEntryName)
        } else {
            //Si le fichier n'existe pas, ce n'est ni isDirectory ni isFile.
            //Si vous souhaitez traiter dans ce cas, écrivez le processus ici.
        }
    }
}

/**
 *ZIP archive les fichiers dans la ArrayList spécifiée et les crée dans le chemin spécifié.
 *Le code de caractère par défaut est Shift_Puisqu'il s'agit de JIS, les noms de fichiers japonais peuvent également être pris en charge.
 *
 * @param zipOutputStream Stream pour écrire targetFile.
 * @param targetFile Fichier à compresser.
 * @param entryName Nom de fichier lors de l'écriture de targetFile dans zipOutputStream(Chemin relatif)。
 *          ex) hoge/fuga.Si c'est txt, pétiller.zip/hoge/fuga.Un fichier sera créé en txt.
 */
fun archiveFile(zipOutputStream: ZipOutputStream, targetFile: File, entryName: String) {
    // ※2
    val zipBufferSize = 100 * 1024
    // ${Chemin du fichier spécifié par ZipOutputStream} / ${entryName}Le fichier sera créé au format.
    zipOutputStream.putNextEntry(ZipEntry(entryName))
    FileInputStream(targetFile).use { inputStream ->
        val bytes = ByteArray(zipBufferSize)
        var length: Int
        //Lisez le fichier pour zipBufferSize. Après le chargement-Renvoie 1.
        while (inputStream.read(bytes).also { length = it } != -1) {
            zipOutputStream.write(bytes, 0, length)
        }
    }
    //L'entrée n'est pas fermée à l'usage et doit être fermée manuellement.
    zipOutputStream.closeEntry()
}

Note

* 1 À propos du jeu de caractères à utiliser

Cette fois, MS932 est sélectionné comme jeu de caractères à utiliser. La raison de l'utilisation de MS932 au lieu de SHIFT_JIS, qui est un code de caractère similaire, est basée sur l'article suivant.

* 2 À propos de la taille de la mémoire tampon utilisée par FileInputStream

Référence: copie du fichier Java (modifier la taille du tampon) バッファサイズ

Cette fois, la taille estimée du fichier téléchargé était d'environ 1 Mo à 5 Mo, j'ai donc spécifié 100 Ko.

À propos de net.lingala.zip4j.ZipFile

Net.lingala.zip4j.ZipFile avec de nombreuses fonctions utiles est Charset Cela ne peut pas être changé. Par conséquent, si vous souhaitez prendre en charge le japonais, utilisez java.util.zip.

Recommended Posts

[Kotlin] Compression ZIP des fichiers japonais
[Kotlin] Supprimer les fichiers en double [Java]