You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从资源目录中的Zip文件获取BufferedReader?

Reading Files Inside a Zip Resource as BufferedReader

Got it, let's work through this problem. Your current method works perfectly for regular resource files because it directly fetches their input streams via the classloader. But zip files are containers—you can't just grab the internal file's stream directly; you first need to open the zip archive, locate the specific entry you want, then wrap that entry's stream into a BufferedReader.

Here's a solution that extends your existing logic, supporting both regular resources and files inside zip archives:

We'll use a composite path format (like archive.zip!internal/file.txt) to distinguish zip resources from regular ones. This lets you use a single method for both cases.

import java.io.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

public class ResourceReader {
    private static final String DEFAULT_ENCODING = "UTF-8"; // Adjust to your project's encoding needs

    public static BufferedReader resourceReader(String resourcePath) throws IOException {
        // Check if the path points to a file inside a zip archive
        if (resourcePath.contains("!")) {
            String[] pathParts = resourcePath.split("!", 2);
            String zipResourcePath = pathParts[0];
            String internalFilePath = pathParts[1];

            // Clean up internal path (zip entries rarely start with a leading slash)
            if (internalFilePath.startsWith("/")) {
                internalFilePath = internalFilePath.substring(1);
            }

            // Get the input stream for the zip file itself (treated as a resource)
            InputStream zipInputStream = Thread.currentThread().getContextClassLoader()
                    .getResourceAsStream(zipResourcePath);
            if (zipInputStream == null) {
                throw new FileNotFoundException("Zip resource not found: " + zipResourcePath);
            }

            ZipInputStream zipEntryStream = new ZipInputStream(zipInputStream, DEFAULT_ENCODING);
            ZipEntry entry;

            // Traverse zip entries to find the target file
            while ((entry = zipEntryStream.getNextEntry()) != null) {
                if (entry.getName().equals(internalFilePath)) {
                    // Return BufferedReader wrapped around the entry's stream
                    // Note: Closing this BufferedReader will automatically close all underlying streams
                    return new BufferedReader(new InputStreamReader(zipEntryStream, DEFAULT_ENCODING));
                }
                // Close unused entries to free up resources
                zipEntryStream.closeEntry();
            }

            // If we reach here, the internal file wasn't found in the zip
            zipEntryStream.close();
            zipInputStream.close();
            throw new FileNotFoundException("Internal file '" + internalFilePath + "' not found in zip: " + zipResourcePath);
        } else {
            // Fallback to your original logic for regular non-zip resources
            InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(resourcePath);
            if (is == null) {
                throw new FileNotFoundException("Not found: " + resourcePath);
            }
            return new BufferedReader(new InputStreamReader(is, DEFAULT_ENCODING));
        }
    }
}

Key Details to Keep in Mind:

  • Path Format: Use ! to separate the zip resource path from the internal file path. Examples:
    • Regular resource: config/app.properties
    • File inside zip: archives/data.zip!documents/readme.txt
  • Stream Management: Always close the returned BufferedReader (preferably with try-with-resources) to avoid resource leaks:
    try (BufferedReader reader = ResourceReader.resourceReader("archives/data.zip!documents/readme.txt")) {
        String line;
        while ((line = reader.readLine()) != null) {
            // Process each line as needed
        }
    } catch (IOException e) {
        // Handle exception (log, rethrow, etc.)
    }
    
  • Zip Entry Paths: Zip entries use forward slashes (/) as path separators and almost never start with a leading slash. The method cleans up the internal path to match this convention automatically.
  • Performance: For large zip files, traversing all entries can be slow. If you know the exact path of the entry you need, this is still the best approach for resources (since resources are streams, not filesystem files, we can't use ZipFile for random access).

内容的提问来源于stack exchange,提问作者user697911

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 08:00:19