Open
Description
std.zip
doesn't make it easy to find an entry by path, also there is no easy way to extract a single entry. I think that std.zip
should have a helper function to find and extract an entry by path. I made a helper function in my project that finds an entry and writes the contents to a writer. This is just an example, but i think that a similar function should exist in the stdlib. There is no reason that people should use an external zip library or implement this every time they need to read a zip file because most of the work is already implemented in the stdlib.
fn readZipEntry(it: anytype, path: []const u8, writer: anytype) !void {
it.cd_record_index = 0;
it.cd_record_offset = 0;
const stream = it.stream;
var filename_buf: [std.fs.max_path_bytes]u8 = undefined;
while (try it.next()) |entry| {
const filename = filename_buf[0..entry.filename_len];
try stream.seekTo(entry.header_zip_offset + @sizeOf(std.zip.CentralDirectoryFileHeader));
try stream.context.reader().readNoEof(filename);
if (!mem.eql(u8, filename, path)) continue;
const local_header = blk: {
try stream.seekTo(entry.file_offset);
break :blk try stream.context.reader().readStructEndian(std.zip.LocalFileHeader, .little);
};
const local_data_header_offset = @as(u64, local_header.filename_len) + @as(u64, local_header.extra_len);
const local_data_file_offset = @as(u64, entry.file_offset) + @as(u64, @sizeOf(std.zip.LocalFileHeader)) + local_data_header_offset;
try stream.seekTo(local_data_file_offset);
var lr = std.io.limitedReader(stream.context.reader(), entry.compressed_size);
const crc32 = try std.zip.decompress(
entry.compression_method,
entry.uncompressed_size,
lr.reader(),
writer,
);
_ = crc32;
return;
}
return error.EntryNotFound;
}
var it = try std.zip.Iterator(@TypeOf(stream)).init(stream);
var list = std.ArrayList(u8).init(gpa);
defer list.deinit();
const writer = list.writer();
try readZipEntry(&it, "java/lang/Object.class", writer);
std.debug.print("{}\n", .{list.items.len});
list.clearRetainingCapacity();
try readZipEntry(&it, "java/lang/String.class", writer);
std.debug.print("{}\n", .{list.items.len});
list.clearRetainingCapacity();