2012-09-05 39 views
7

Theo Java documentation, thông số readlimit của phương pháp đánh dấu trong máy chủ Lớp InputStream cho tập hợp "giới hạn tối đa byte có thể đọc trước khi vị trí đánh dấu trở thành không hợp lệ".. Tôi có tệp có tên sample.txt có nội dung là "xin chào". Và tôi đã viết mã này:Java: Giới hạn đánh dấu đầu vào

import java.io.*; 
public class InputStream{ 
public static void main (String[] args) throws IOException { 
    InputStream reader = new FileInputStream("sample.txt"); 
    BufferedInputStream bis = new BufferedInputStream(reader); 
    bis.mark(1); 
    bis.read(); 
    bis.read(); 
    bis.read(); 
    bis.read(); 
    bis.reset(); 
    System.out.println((char)bis.read()); 
} 
} 

Đầu ra là "h". Nhưng nếu tôi sau khi phương pháp đánh dấu phương pháp đọc nhiều hơn một byte, tôi có nên gặp lỗi cho lệnh gọi phương thức đặt lại không hợp lệ không?

Trả lời

5

Tôi sẽ đặt lỗi này xuống lỗi tài liệu.

Tài liệu không tham số cho BufferedInputStream là "Xem hợp đồng chung của phương thức đánh dấu của InputStream", điều này cho tôi biết rằng BufferedInputStream không hoạt động khác, mặc dù doc tham số.

Và hợp đồng nói chung, theo quy định của InputStream, là

Những lập luận readlimit nói input stream này để cho phép nhiều byte được đọc trước khi vị trí đánh dấu được hết hiệu lực [...] dòng là không bắt buộc phải nhớ bất kỳ dữ liệu nào nếu có nhiều byte đọc được đọc từ luồng

Nói cách khác, readlimit là một gợi ý; luồng là miễn phí để không hứa hẹn và phân phối quá mức.

+0

Bạn có biết bất kỳ việc triển khai InputStream nào để sử dụng để tạo lại kịch bản trong đó nếu tôi đọc nhiều byte hơn những gì được đặt bằng dấu() một ngoại lệ sẽ được ném không? –

1

Nhìn vào thực hiện BufferedInputStream, nó mô tả tầm quan trọng của vị trí đánh dấu trong JavaDocs (của bảo vệ markpos lĩnh vực):

[markpos là] giá trị của lĩnh vực pos tại thời điểm phương thức mark vừa được gọi.

Giá trị này luôn nằm trong khoảng -1 đến pos. Nếu không có vị trí được đánh dấu trong luồng đầu vào, trường này là -1. Nếu có vị trí được đánh dấu trong luồng đầu vào, thì buf[markpos] là byte đầu tiên được cung cấp dưới dạng đầu vào sau hoạt động reset. Nếu markpos không phải là -1 thì tất cả các byte từ vị trí buf[markpos] đến buf[pos-1] phải nằm trong mảng đệm (mặc dù chúng có thể được di chuyển đến vị trí khác trong mảng đệm, với điều chỉnh phù hợp với giá trị count, posmarkpos); chúng có thể không bị loại trừ trừ khi và cho đến khi sự khác biệt giữa posmarkpos vượt quá marklimit.

Hy vọng điều này sẽ hữu ích. Xem nhanh các định nghĩa của read, reset và phương pháp riêng tư fill trong lớp để xem tất cả các mối quan hệ đó kết hợp với nhau như thế nào.

Tóm lại, chỉ khi lớp truy xuất thêm dữ liệu để lấp đầy bộ đệm thì vị trí đánh dấu sẽ được tính đến. Nó sẽ bị vô hiệu hóa một cách chính xác nếu nhiều byte được đọc hơn so với cuộc gọi đến số mark được cho phép. Do đó, các cuộc gọi đến read sẽ không nhất thiết kích hoạt hành vi được quảng cáo trong các nhận xét JavaDoc công khai.

1

Điều này trông giống như một lỗi nhỏ. Nếu bạn giảm đệm sizey bạn sẽ nhận được một IOException

public static void main(String[] args) throws IOException { 
    InputStream reader = new ByteArrayInputStream(new byte[]{1, 2, 3, 4, 5, 6, 7, 8}); 
    BufferedInputStream bis = new BufferedInputStream(reader, 3); 
    bis.mark(1); 
    bis.read(); 
    bis.read(); 
    bis.read(); 
    bis.read(); 
    bis.reset(); 
    System.out.println((char)bis.read()); 
} 
2

Nếu bạn nhìn vào source, đặc biệt là phương pháp lấp đầy(), bạn có thể nhìn thấy (sau một thời gian!) Mà nó chỉ làm mất hiệu lực khi nó đánh dấu hoàn toàn có, nghĩa là nó khoan dung hơn so với tài liệu có thể gợi ý.

... 
else if (pos >= buffer.length) /* no room left in buffer */ 
    if (markpos > 0) { /* can throw away early part of the buffer */ 
    int sz = pos - markpos; 
    System.arraycopy(buffer, markpos, buffer, 0, sz); 
    pos = sz; 
    markpos = 0; 
    } else if (buffer.length >= marklimit) { 
    markpos = -1; /* buffer got too big, invalidate mark */ 
    pos = 0;  /* drop buffer contents */ 
    .... 

Kích thước bộ đệm mặc định tương đối lớn (8K), vì vậy việc vô hiệu sẽ không được kích hoạt trong ví dụ của bạn.

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