Có ai có thể đăng một đoạn mã đơn giản không?Làm cách nào để lưu trữ nhiều tệp vào tệp .zip bằng scala?
Tệp là các tệp văn bản, do đó, nén sẽ đẹp hơn là chỉ lưu trữ tệp.
Tôi có tên tệp được lưu trữ trong một lần lặp lại.
Có ai có thể đăng một đoạn mã đơn giản không?Làm cách nào để lưu trữ nhiều tệp vào tệp .zip bằng scala?
Tệp là các tệp văn bản, do đó, nén sẽ đẹp hơn là chỉ lưu trữ tệp.
Tôi có tên tệp được lưu trữ trong một lần lặp lại.
Hiện chưa cách nào để làm điều này loại điều từ thư viện Scala tiêu chuẩn, nhưng nó khá dễ sử dụng java.util.zip
:
def zip(out: String, files: Iterable[String]) = {
import java.io.{ BufferedInputStream, FileInputStream, FileOutputStream }
import java.util.zip.{ ZipEntry, ZipOutputStream }
val zip = new ZipOutputStream(new FileOutputStream(out))
files.foreach { name =>
zip.putNextEntry(new ZipEntry(name))
val in = new BufferedInputStream(new FileInputStream(name))
var b = in.read()
while (b > -1) {
zip.write(b)
b = in.read()
}
in.close()
zip.closeEntry()
}
zip.close()
}
Tôi đang tập trung vào sự đơn giản thay vì hiệu quả ở đây (không kiểm tra lỗi và đọc và viết một byte tại một thời điểm không phải là lý tưởng), nhưng nó hoạt động, và có thể dễ dàng được cải thiện.
Đây là thêm một chút phong cách scala trong trường hợp bạn muốn chức năng:
def compress(zipFilepath: String, files: List[File]) {
def readByte(bufferedReader: BufferedReader): Stream[Int] = {
bufferedReader.read() #:: readByte(bufferedReader)
}
val zip = new ZipOutputStream(new FileOutputStream(zipFilepath))
try {
for (file <- files) {
//add zip entry to output stream
zip.putNextEntry(new ZipEntry(file.getName))
val in = Source.fromFile(file.getCanonicalPath).bufferedReader()
try {
readByte(in).takeWhile(_ > -1).toList.foreach(zip.write(_))
}
finally {
in.close()
}
zip.closeEntry()
}
}
finally {
zip.close()
}
}
và đừng quên nhập khẩu:
import java.io.{BufferedReader, FileOutputStream, File}
import java.util.zip.{ZipEntry, ZipOutputStream}
import io.Source
Câu trả lời Travis là đúng nhưng tôi đã tinh chỉnh một ít để có phiên bản mã nhanh hơn của mình:
val Buffer = 2 * 1024
def zip(out: String, files: Iterable[String], retainPathInfo: Boolean = true) = {
var data = new Array[Byte](Buffer)
val zip = new ZipOutputStream(new FileOutputStream(out))
files.foreach { name =>
if (!retainPathInfo)
zip.putNextEntry(new ZipEntry(name.splitAt(name.lastIndexOf(File.separatorChar) + 1)._2))
else
zip.putNextEntry(new ZipEntry(name))
val in = new BufferedInputStream(new FileInputStream(name), Buffer)
var b = in.read(data, 0, Buffer)
while (b != -1) {
zip.write(data, 0, b)
b = in.read(data, 0, Buffer)
}
in.close()
zip.closeEntry()
}
zip.close()
}
Gần đây, tôi phải làm việc với các tệp zip quá và thấy tiện ích này rất đẹp: https://github.com/zeroturnaround/zt-zip
Dưới đây là một ví dụ về nén tất cả các file bên trong một thư mục:
import org.zeroturnaround.zip.ZipUtil
ZipUtil.pack(new File("/tmp/demo"), new File("/tmp/demo.zip"))
Rất thuận tiện.
Một chút sửa đổi (ngắn hơn) phiên bản sử dụng NIO2:
private def zip(out: Path, files: Iterable[Path]) = {
val zip = new ZipOutputStream(Files.newOutputStream(out))
files.foreach { file =>
zip.putNextEntry(new ZipEntry(file.toString))
Files.copy(file, zip)
zip.closeEntry()
}
zip.close()
}
Bạn nên 'in.close() 'khi bạn đã hoàn tất với' in'. – leedm777
Vâng, tất nhiên — tôi đã sửa nó ngay bây giờ. –
Và tôi biết nó không được tối ưu hóa, nhưng không cần phải bọc byte trong một mảng. Bạn có thể chỉ đơn giản là 'zip.write (b)'. – leedm777