Chào mừng đến với Diễn đàn lập trình - Cộng đồng lập trình.
Kết quả 1 đến 2 của 2
  1. #1
    Ngày tham gia
    Sep 2015
    Bài viết
    0

    Cách sử dụng nhiều biến BufferReader đọc cùng 1 file?

    em có thử nghiệm 1 chút xử lý file với BufferReader:
    Mã:
    package locfile;
    
    import java.io.BufferedReader;
    import java.io.FileReader;
    import java.io.FileWriter;
    import java.io.IOException;
    
    public class Locfile {
    
        public static void main(String[] args) throws IOException{
            FileReader fr = new FileReader("D:\\fix.txt");
            FileWriter fw = new FileWriter(".//thongbaofiletrung.txt");
            BufferedReader br = new BufferedReader(fr);
        //    BufferedReader br1 = new BufferedReader(fr);
            String s,r;
            int count1=0;
            while ((s = br.readLine())!=null) {
                count1++;
         //       while((r=br1.readLine())!=null)
               System.out.print(String.valueOf(count1)+"
    ");
             
            
            fw.close();
        }
        
        }
    }
    với file fix.txt có 6 dòng thì đoạn code trên in ra 6 dòng từ 1 đến 6

    tuy nhiên em khi em bỏ 2 cái comment ở trên,với mong muốn nó sẽ chạy 2 vòng file lồng nhau thì thực tế lại chỉ in ra 5 dòng toàn số 1,tức là việc khai báo đối tượng br1 và br ko có ý nghĩa,br1 đọc đến dòng nào thì br cũng đến dòng đó,
    em cứ nghĩ khai báo 2 Đối tượng bufferreader riêng biệt như vậy thì nó phải chạy độc lập chứ nhỉ??
    và làm sao để có thể dùng nhiều đối tượng bufferreader để đọc file linh hoạt,chứ cả 1 chương trình dùng 1 cái thực sự rất bất tiện

    thêm nữa em có vài thắc mắc muốn mọi người cho giải pháp:
    +việc sử dụng bufferread đọc theo từng dòng thấy rất tiện lợi,nhưng khi muốn quay lại các vị trí khác ví dụ như là muốn cho nó đọc lại từ đầu file hoặc quay lại cái dòng vừa đọc trước đó chẳng hạn thì lại rất khó khăn (phải sử dụng mark và reset),có cách nào để reset cái stream của nó đễ dàng ko?
    +khai báo br.mark(int) thì cái biến int đó có ý nghĩa gì,xem 1 số ví dụ thấy hầu hết nó chọn bằng 0,nhưng lúc làm e thấy chọn bằng 0 luôn bị báo lỗi nên toàn chọn những số to to kiểu 10000 thì ok ,mặc dù chả hiểu bản chất là sao cả
    +Nếu muốn đọc và ghi trực tiếp lên file luôn thì có thể dùng cái gì?

  2. #2
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    Mình có một số ý:

    1. Bạn đã sai khi nghĩ rằng br đọc đến đâu thì br1 đọc đến đó.
    2. Tuy 2 đối tượng nhưng nó dùng chung 1 luồng (Stream).
    3. Quay lại vị trí trước đó dã đọc thì như bạn nói là dùng phương thức mark() và reset() (markSupport()). Hoặc tạo luồng đọc lại từ đầu.
    4. Tham số duy nhất của phương thức mark là readAheadLimit.
    5. Nếu đọc và ghi vào cùng 1 tập tin thì bạn nên ghi vào tập tin tạm trước.

    Mở rộng:
    1. Hiểu sai
    Do cả br và br1 đều dùng chung 1 luồng nên khi br đọc 1 dòng thì số dòng của luồng còn lại là 5. Khi đến br1 đọc nó chỉ có thể đọc 5 dòng còn lại.
    Nhưng sai lại chỉ in ra 5 số 1 mà không phải từ 1 đến 5?
    Bạn đã hiểu sai nữa. Khi vào vòng lặp thứ nhất (đọc br) thì nó tiếp tục vòng lặp thứ 2 khi count1 = 1 (count1 = 0; count1++). Trong vòng lặp thứu 2 nó cứ đọc mãi cho đến khi hét 5 dòng còn lại mà không thoát vòng 2 để chạy ngược ra vòng 1. Điều này có nghĩa là nó không chạy được đến count1++; một lần nữa. Trường count1 vẫn bằng 1.
    Khi đọc hết 5 dòng thì nó thoát vòng 2 chạy ra vòng 1, và vòng 1 cũng kết thúc vì luồng đã không còn dòng nào để đọc (br.readLine() = null). Kết thúc cả 2 vòng lặp khi count1 = 1.

    2. Chung luồng
    Mình lấy ví dụ thế này. Ngày xưa, có một số nhà làm 2 nhà tắm cạnh nhau, dùng chung 1 bồn nước. Nếu bồn có 6 lít. Nhà 1 lấy 1 lít để tắm nhà 2 chỉ có thể lấy tối đa 5 lít còn lại. Cái bồn nước ở đây xem như là luồng đọc tập tin (FileReader).
    Nếu bạn muốn đọc đọc lập với nhau thì nên làm 2 nhà tắm có 2 bồn nước.

    3. Trở lại
    Như bạn và mình cũng thế, dùng phương thức mark() để đánh dấu và reset() để trở lại vị trí đánh dấu. Nhưng trong trường hợp bạn không biết trước được vị trí mình muốn đánh dấu là ở đâu thì có lẽ nên tạo lại luồng mới rồi dùng phương thức skip() bỏ qua một số byte để đến vị trí mình muốn.

    4. Đánh dấu
    Tham số duy nhất của phương thức skip() là readAheadLimit có nghĩa là Giới hạn đọc tiếp. Giới hạn đọc só lượng byte tiếp theo trong lúc đánh dấu này. Theo suy đoán của mình, có thể có dùng đến bộ đệm nên nó cần tham số đầu vào này để khởi tạo bộ đệm.
    Nếu quá trình đọc vượt quá giới hạn thì sẽ xảy ra ngoại lệ. Đồng thời nếu tham số này lớn hơn độ lớn của luồng (kich thước tập tin) thì cũng xảy ra ngoại lệ.

    5. Xung đột
    Việc đọc và ghi cùng 1 lúc có thể gây xung đột dữ liệu rất cao.
    Bạn nên đọc từ 1 tập tin và ghi vào tập tin tạm rất nhiều chương trình hiện nay dùng cách đó để bảo toàn dữ liệu.
    VD:
    Đọc từ tập tin Data.dat. Ghi vào tập tin tạm khác, như là @Data.dat (hoặc tên ghì thì tùy). Sao khi ghi xong thì dùng các phương thức:
    + Xóa tập tin Data.dat gôc.
    + Đổi tên tập tin @Data.dat sang Data.dat.

 

 

Quyền viết bài

  • Bạn Không thể gửi Chủ đề mới
  • Bạn Không thể Gửi trả lời
  • Bạn Không thể Gửi file đính kèm
  • Bạn Không thể Sửa bài viết của mình
  •