2012-12-20 22 views
6

Vì vậy, tôi đang cố gắng viết thư từ người dùng trên mạng nhắn tin đến một tệp. Tôi đang cố gắng để xây dựng chương trình này với thực hành java tốt và kỹ thuật IO tập tin thích hợp.Có nên lưu trữ nhiều văn bản được lưu trữ định kỳ vào bộ đệm trước khi lưu vào một tệp không?

Hiện tại, chương trình của tôi nhận ra ai đó đã đăng một tin nhắn, nhận tin nhắn và ghi ngay vào một tập tin. Tạo đối tượng file, tạo đối tượng writer, gắn thêm thông điệp, sau đó đóng file.Đây có vẻ như thực hành tốt nếu không có nhiều thông báo đến, nhưng nếu có một luồng hội thoại nhanh thì điều này có vẻ chậm và đòi hỏi nhiều các hành động không cần thiết vì tệp sẽ mở lại ngay lập tức.

Sau đó, tôi nghĩ rằng nếu tôi chỉ để lại tập tin mở và vừa viết các tin nhắn khi họ đến tập tin, sau đó đóng nó định kỳ. Đó là thực hành tốt? Để tệp mở trong thời gian dài? Ví dụ sau một giờ hoặc sau khi một số lượng dữ liệu đã được viết?

Bây giờ, tôi nghĩ mình nên lấy các tin nhắn, lưu trữ chúng trong một "bộ đệm" (như một mảng chuỗi), sau đó lưu mảng chuỗi vào một tệp khi "bộ đệm" đầy. Đây có phải là thực hành tốt hơn?

Vì vậy, tôi có hai câu hỏi:

1) Có thực hành tốt để lại một tập tin mở cho một khoảng thời gian dài (vài phút đến vài giờ) nếu bạn không sử dụng các tập tin?

2) Thực hành tốt cho "Cache" như tôi đang nói đến là gì? Là một mảng chuỗi tốt? Có cái gì tốt hơn tôi nên sử dụng? Bạn sẽ lưu trữ thông tin này như thế nào?

Trả lời

3

Theo ý kiến ​​của tôi, thực hành tốt nhất cho nhật ký (và tương tự) trong các ứng dụng máy chủ là để quyết định thời gian trễ chấp nhận được và gắn bó với nó. Ví dụ: nếu bạn đặt thời gian trễ là 5 giây, hãy viết mã để:

  • Nếu bạn viết gì đó vào nhật ký, nó sẽ 'thực sự' được viết trong vòng 5 giây.
  • Nếu một cái gì đó khác được viết trước 5 giây, nó chỉ được thêm vào bộ đệm (được viết khi hết thời gian).

Bằng cách đó, bạn chỉ làm tối đa một đĩa ghi mỗi 5 giây, nhưng chắc chắn là được viết. Điều này so sánh tốt với các cách tiếp cận khác:

  • Nếu bạn chuyển dữ liệu vào đĩa mọi lúc được viết, nhưng tăng tải và có 10.000 sự kiện mỗi giây thì bạn sẽ lãng phí thời gian I/O với 10.000 đĩa ghi mỗi giây.
  • Nếu bạn để Java/OS để quyết định thời điểm tuôn ra dữ liệu, nhưng tải rất thấp (ví dụ: vào giữa đêm), nhật ký thậm chí có thể bị lỗi thời. (Nếu có một sự kiện, không đủ lớn để lấp đầy bộ đệm, thì không có gì trong nhiều giờ.)

Gần đây, tôi chưa xem xét các API để xem có cách xây dựng chiến lược này không nhưng thật dễ dàng để viết mã. Bằng cách này, không cần phải tự lưu trữ đầu ra; bạn chỉ có thể sử dụng một BufferedOutputStream, và gọi đối tượng flush() bất cứ khi nào bạn muốn ghi nó vào đĩa. (Bằng cách đó, nó cũng sẽ tự động viết khi nó chạm vào giới hạn bộ đệm, nhưng có thể là OK nếu bạn chọn giới hạn một cách hợp lý.)

Về việc mở tệp, bạn có thể để tệp mở miễn là bạn thích (chỉ đóng nó khi bạn sẽ không viết cho nó nữa). Giả sử bạn không có hàng nghìn tệp đang mở và bạn không cần phải có nhiều ứng dụng ghi vào cùng một tệp, điều này không gây ra bất kỳ sự cố nào.

+0

> thực hành tốt nhất cho nhật ký (và tương tự) trong các ứng dụng máy chủ là để quyết định thời gian trễ có thể chấp nhận được và bám vào nó. Bạn có thể giải thích cách thực hiện điều đó không? Hoặc chỉ cho tôi theo hướng để tìm ra cách để làm điều này? Ngoài ra, một số thông tin thêm về cách sử dụng BuffereOutputStream sẽ là tốt đẹp. Tôi đang cố gắng sử dụng nó đúng cách. Có những lớp học khác nên tham gia không? Làm cách nào để tìm hiểu về việc sử dụng phương thức flush(). Đây cũng là một câu trả lời tuyệt vời cảm ơn bạn. – Bnannerz

+1

BufferedOutputStream khá dễ dàng; giống như nếu bạn có một FileOutputStream được gọi ra, chỉ cần làm mới BufferedOutputStream (ra) và sử dụng nó như bạn sẽ FileOutputStream. Có một BufferedWriter, nếu bạn đang sử dụng các nhà văn. Tham số thứ hai là mức độ lớn để tạo bộ đệm; mặc định là khá nhỏ nhưng cho đến nay tôi biết bạn có thể làm cho nó 8KB hoặc 64KB hoặc bất cứ điều gì bạn thích. – sam

+1

Giới thiệu về cách thực hiện điều thời gian - điều này khá đơn giản nhưng liên quan đến đồng thời, vì vậy bạn cần phải sử dụng từ khóa được đồng bộ hóa ở những nơi! Về cơ bản, có chức năng 'ghi vào tệp' của bạn để nó ghi vào luồng đầu ra được lưu vào bộ đệm. Kiểm tra xem bạn đã có bộ hẹn giờ 'tuôn ra' chưa. Nếu có, không làm gì; nếu không, hãy bắt đầu một chuỗi mới chỉ ngủ trong 5 giây (hoặc bất kỳ thứ gì), sau đó gọi tuôn ra trên luồng. (Gọi flush() sẽ xóa bộ đệm và thực sự ghi nó vào đĩa.) – sam

1

1) Thực hành tốt là để tệp mở trong một khoảng thời gian dài (vài phút đến vài giờ) nếu bạn không sử dụng tệp?

Tôi nghĩ điều này tùy thuộc vào số lượng thư đến chương trình của bạn và từng kích thước thư. Nếu bộ nhớ của bạn có thể đáp ứng với tính toán của bạn, bạn có thể nghĩ về nó. Nhưng tôi sẽ nghĩ rằng một bout để viết trên một cơ sở dữ liệu khi mỗi tin nhắn đến (có thể là một đốm màu). Ngoài ra, hãy nghĩ về những gì đã xảy ra nếu chương trình của bạn gặp sự cố khi bạn ghi vào tệp. Bạn có thể mất toàn bộ tin nhắn được lưu trữ trên bộ nhớ.

2) Thực hành tốt cho "Cache" như tôi đang nói đến là gì? Là một mảng chuỗi tốt? Có cái gì tốt hơn tôi nên sử dụng? Bạn sẽ lưu trữ thông tin này như thế nào?

Nếu bạn lưu trữ dữ liệu tạm thời trong mảng bộ nhớ là ok khi bạn biết kích thước. Nếu không, bạn có thể sử dụng ArrayList.

3

Thật tuyệt khi để tệp mở trong một thời gian dài. Nó chắc chắn tốt hơn nhiều so với việc mở và đóng cửa liên tục. Số lượng tài nguyên được tiêu thụ bởi một tệp mở duy nhất là không đáng kể; mối quan tâm duy nhất của bạn sẽ là nếu bạn có nhiều tệp mở (hàng trăm hoặc hàng nghìn). Tôi sẽ đề nghị bạn mở tập tin khi chương trình của bạn bắt đầu, và đóng nó khi nó kết thúc.

Nếu bạn sử dụng các công cụ thích hợp để kiểm tra các tệp đang mở do chương trình của bạn tổ chức hoặc các chương trình khác trên hệ thống của bạn, bạn sẽ thấy rằng tất cả các tệp đó đều chứa một số tệp (một vài đến hàng chục) mở cho toàn bộ thời gian hoạt động của chúng - bất kỳ tệp nào chứa mã của chương trình (tệp thực thi, thư viện được chia sẻ và tệp JAR cho các chương trình Java), vì các tệp này được mở và sau đó là ánh xạ bộ nhớ và thường ghi lại các tệp. Điều này là bình thường và an toàn.

Bây giờ, bạn sẽ cần phải flush luồng (hoặc nhà văn hoặc RandomAccessFile hoặc bất kỳ điều gì bạn sử dụng) trong thời gian này.Bạn nên làm điều này bất cứ khi nào bạn cần đảm bảo rằng tất cả dữ liệu được ghi đến thời điểm đó đã được ghi vào đĩa một cách an toàn; có thể sau mỗi tin nhắn hoặc sau một số lượng tin nhắn nhất định, lượng dữ liệu hoặc khoảng thời gian, như bạn thấy phù hợp.

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