2009-12-16 36 views
6

Tôi biết phương thức getResourceAsStream() nhưng có sự cố với trình phân tích cú pháp đọc tệp, toàn bộ cấu trúc được triển khai để mong đợi một FileInputStream()getResourceAsStream() trả về luồng đầu vào không thể truyền. Có dễ dàng "sửa chữa" cho tình huống này?Làm cách nào để truy cập tệp txt trong một tệp jar bằng FileInputStream?

+1

Đây sẽ là lý do tại sao bạn nên viết mã cho giao diện chứ không phải triển khai. – Powerlord

+0

Bạn không nên truyền luồng đầu vào cho việc triển khai của chúng. Họ được cho là đã triển khai ống và bộ lọc. Đó là, một (tập tin) inputrteam đọc từ một tập tin, giải nén khác (GZipI.S.), Một ngắt dòng (bufferedI.S.), Khác ... và như vậy. Vì vậy, nếu chương trình của bạn mong đợi một dòng byte mong đợi một inputstream (bất kỳ I.S.) và sau đó cung cấp một số triển khai của nó. Nếu bạn muốn chuyển đổi luồng nối với nhau: ví dụ: GZipInputStream (new FileInputStream (path)) mới. – helios

Trả lời

20

Tài nguyên chứa trong tệp JAR không phải là tệp chính nó và không thể đọc được bằng cách sử dụng FileInputStream. Nếu bạn có mã hoàn toàn yêu cầu FileInputStream, thì bạn sẽ cần phải trích xuất dữ liệu bằng cách sử dụng getResourceAsStream(), sao chép dữ liệu đó vào tệp tạm thời, sau đó chuyển FileInputStream cho tệp tạm thời đó vào mã của bạn.

Tất nhiên, trong tương lai, không bao giờ viết mã để mong đợi việc triển khai cụ thể những thứ như InputStream, bạn sẽ luôn hối tiếc.

0

không tin phân tích cú pháp của bạn chỉ hoạt động trên FileInputStream nhưng không InputStream

nếu đó là trường hợp thực tế, và bạn phải sử dụng phân tích cú pháp

2 lựa chọn

  1. sử dụng bộ chuyển đổi mô hình để tạo CustomFileInputStream và ghi đè lên các phương thức tương ứng, nhiều chuyển hướng dữ liệu getResourceAsStream đến CustomFileInputStream

  2. lưu ur getResourceAsStream vào tệp tạm thời và phân tích cú pháp tệp tạm thời, sau đó xóa tệp khi hoàn thành

5

Gần đây tôi đã gặp phải vấn đề tương tự. Thư viện của bên thứ ba chúng tôi sử dụng lần đọc từ FileInputStream nhưng các tài nguyên có thể ở bất cứ đâu, trong JAR hoặc từ xa. Chúng tôi đã từng viết các tệp tạm thời nhưng có quá nhiều chi phí.

Một giải pháp tốt hơn là viết một FileInputStream kết thúc tốt đẹp InputStream. Đây là lớp chúng tôi sử dụng,

public class VirtualFileInputStream extends FileInputStream { 

    private InputStream stream; 

    public VirtualFileInputStream(InputStream stream) { 
     super(FileDescriptor.in); // This will never be used 
     this.stream = stream; 
    } 




    public int available() throws IOException { 
     throw new IllegalStateException("Unimplemented method called"); 
    } 


    public void close() throws IOException { 
     stream.close(); 
    } 


    public boolean equals(Object obj) { 
     return stream.equals(obj); 
    } 


    public FileChannel getChannel() { 
     throw new IllegalStateException("Unimplemented method called"); 
    } 


    public int hashCode() { 
     return stream.hashCode(); 
    } 


    public void mark(int readlimit) { 
     stream.mark(readlimit); 
    } 


    public boolean markSupported() { 
     return stream.markSupported(); 
    } 


    public int read() throws IOException { 
     return stream.read(); 
    } 


    public int read(byte[] b, int off, int len) throws IOException { 
     return stream.read(b, off, len); 
    } 


    public int read(byte[] b) throws IOException { 
     return stream.read(b); 
    } 


    public void reset() throws IOException { 
     stream.reset(); 
    } 


    public long skip(long n) throws IOException { 
     return stream.skip(n); 
    } 


    public String toString() { 
     return stream.toString(); 
    } 

} 
+1

+1 nhưng tôi gọi nó là FakeFileInputStream để nhấn mạnh sự cần thiết của những thứ giả mạo :) và khuyến khích không sử dụng triển khai FileInputStream cụ thể. – helios

Các vấn đề liên quan