2012-05-28 37 views

Trả lời

7

Tùy thuộc vào những gì bạn đang làm. Đối với các tập tin văn bản đọc và ghi tuần tự, iostream chắc chắn là cách để đi. Đối với bất kỳ thứ gì liên quan đến bảo mật giao dịch hoặc thiết bị không chuẩn, bạn sẽ phải truy cập trực tiếp vào hệ thống (CreateFile hoặc open). Thậm chí sau đó, để đọc tuần tự và viết văn bản, giải pháp tốt nhất là xác định streambuf của riêng bạn và sử dụng nó với iostream.

Tôi không thể nghĩ ra bất kỳ ngữ cảnh nào mà fopen sẽ thích hợp hơn.

+0

Tôi muốn điện :) viết và đọc nhị phân. chỉ cho windows systems.As tôi nghe mở và fopen không phù hợp với createfile? điều này đúng không? – Eveler

+1

@Eveler: nếu bạn muốn toàn bộ sức mạnh, thì điều nhanh nhất bạn có thể làm để xử lý một tệp là mở nó bằng 'CreateFile' và ánh xạ nó vào bộ nhớ bằng' CreateFileMapping', như được minh họa trong [bài đăng trên blog] này (http: //blogs.msdn.com/b/oldnewthing/archive/2005/05/13/417183.aspx), là một phần của chuỗi tối ưu hóa bắt đầu từ [standard C++] (http://blogs.msdn.com/ b/oldnewthing/archive/2005/05/10/415991.aspx) và sau đó chuyển dần sang [Win32 tối ưu hóa mã] (http://blogs.msdn.com/b/oldnewthing/archive/2005/05/19/420038 .aspx). Nhưng trong hầu hết trường hợp, tiêu chuẩn đơn giản C và C++ là OK. –

+3

'fopen' là hàm mức cao hơn, được thay thế bằng' fstream :: open' trong C++. 'CreateFile' và' open' là các hàm mức hệ thống, hàm đầu tiên trong Windows, thứ hai trong Unix. Họ không cung cấp chính xác điều tương tự, vì các hệ thống hỗ trợ các tính năng khác nhau một cách khác nhau. –

1

Trong hầu hết các trường hợp, bạn sẽ sử dụng fopen trong C hoặc ofstream trong C++ tốt hơn. CreateFile cung cấp thêm một số quyền kiểm soát đối với việc chia sẻ và lưu vào bộ nhớ đệm nhưng không cung cấp chức năng định dạng.

+1

Vì vậy, bạn viết một 'streambuf' trong đó sử dụng' CreateFile' theo cách bạn cần sử dụng nó, và có được những lợi thế của cả hai. –

+0

Tôi đã luôn luôn tự hỏi, tại sao nó là như vậy cồng kềnh để cắm vào một nguồn mới hoặc điểm đến vào IOstreams. Nếu bất cứ điều gì, C++ giúp dễ dàng khai báo một lớp trừu tượng thuần túy cho một trình ghi dữ liệu/trình đọc ... –

4

Trừ khi bạn cần các tính năng được cung cấp bởi các chức năng tập tin Windows (ví dụ như chồng chéo I/O) sau đó đề nghị của tôi đang xảy ra với một trong hai iostreams trong C++ hoặc FILE (fopen và bạn bè) trong C.

Bên cạnh đó là nhiều di động , bạn cũng có thể sử dụng đầu vào/đầu ra được định dạng cho các tệp văn bản và cho C++ dễ dàng quá tải các toán tử đầu ra/đầu vào cho các lớp của bạn.

+2

Nó cũng dễ dàng lấy được từ 'std :: streambuf' và đối với một số tính năng" đặc biệt "(tính toàn vẹn giao dịch, thiết bị đặc biệt) , v.v.) –

2

Trừ khi bạn vô tình cần thêm chức năng được cung cấp bởi các chức năng OS API (như CreateFile) Tôi muốn sử dụng các chức năng thư viện chuẩn (như fopen hoặc ofstream). Bằng cách này chương trình của bạn sẽ được di động hơn.

Lợi thế thực sự duy nhất của việc sử dụng CreateFile mà tôi có thể nghĩ là chồng chéo I/O và có thể có quyền truy cập hạt mịn hơn.

+2

Createfile có thể mở đường dẫn tệp dài hơn 260 char. – Eveler

+0

Đủ công bằng! +1 – cyco130

2

Nếu bạn muốn sử dụng Windows tập tin bản đồ bộ nhớ bạn nên sử dụng CreateFile (ví dụ các HANDLE truyền cho CreateFileMapping API là giá trị trở lại của CreateFile). Hơn nữa, CreateFile cung cấp các tùy chọn tùy chỉnh cao hơn API tệp tiêu chuẩn C và C++.

Tuy nhiên, nếu bạn muốn viết mã di động hoặc nếu bạn không cần các tính năng dành riêng cho Windows, các API tệp chuẩn C và C++ đều tốt. Trong một số thử nghiệm, khi xử lý dữ liệu lớn, tôi đã lưu ý một số chi phí hoạt động của các luồng I/O C++ so với API tệp C thô; nếu bạn xảy ra trong các trường hợp như thế này, bạn có thể chỉ cần bọc API tệp C thô trong một số lớp C++ RAII và vẫn sử dụng nó trong mã C++.

+0

Tôi cần các tệp dữ liệu lớn từ 4GB đến 10GB + và ánh xạ mem tôi cũng sẽ sử dụng. – Eveler

+0

Vì vậy, nếu bạn cần ánh xạ bộ nhớ, bạn có thể sử dụng các cuộc gọi API Win32 trực tiếp và bọc chúng trong các lớp C++ RAII. –

0

tôi sao chép câu trả lời của tôi từ

fopen or CreateFile in Windows

mà đã được đóng cửa vì lý do đó thoát khỏi tôi ...

  1. Không có cách nào định nghĩa cho fopen() để trả lại lỗi hệ thống mã.Có thể có một cách không xác định để truy cập errno, nhưng điều này có thể hoặc có thể không giống với mã lỗi hệ thống.
  2. Ngoài ra, tôi không nghĩ rằng có một cách xác định để truy cập vào xử lý hệ thống thực (loại HANDLE) mà lần lượt bạn có thể muốn sử dụng để chuyển sang một trong nhiều cuộc gọi hệ thống win64 mà mong đợi như vậy hệ thống xử lý (ví dụ như bộ nhớ ánh xạ IO)
  3. Sử dụng open() một số nguyên đại diện cho xử lý tệp, không phải là xử lý hệ thống (trên cửa sổ).
  4. fopen() không ném ngoại lệ trong trường hợp xảy ra lỗi. Để có một số RAII bạn sẽ cần phải quấn nó vào một lớp học.
  5. Đưa gói CreateFile() vào một lớp, không đắt hơn gói fopen() hoặc mở() vào một lớp.
  6. Sử dụng C++ tính năng (std :: ofstream, std :: ifstream) để viết/đọc đến/từ các tập tin bị cùng một vấn đề như fopen():
    • Nó không ném theo mặc định trên lỗi. Để kích hoạt tính năng này, bạn cần gọi một số phương thức thay vì có thể sử dụng một số đối số hàm tạo - có nghĩa là đối với RAII, bạn sẽ cần phải lấy ra lớp này (để sử dụng nó như một lớp thành viên/cơ sở phát sinh lỗi) .
    • Không xác định được nếu có thể truy xuất mã lỗi hệ thống từ trường hợp ngoại lệ được ném hoặc nếu thư được trả về từ cái gì() cho bạn biết bất kỳ điều gì về lỗi hệ thống.
    • Sử dụng giao diện luồng này không có giao diện pluggable thực để xác định nguồn hoặc đích đọc hoặc ghi. Quá tải giao diện luồng khá cồng kềnh và dễ bị lỗi.
  7. Sử dụng C như lập trình (chú ý đến hoặc bỏ qua mã trở lại và tự viết mã ngẫu nhiên) là nguồn gốc của nhiều ác (nhớ trái tim chảy máu?) ...

Kết luận:

  1. viết trình bao bọc tài nguyên cho CreateFile()/CloseHandle(). Tài nguyên wrapper là một lớp, mà thực hiện các hành động trong constructor và undo-hành động trong destructor và ném một ngoại lệ trong trường hợp lỗi. Có rất nhiều cặp cuộc gọi hệ thống như vậy trong mọi hệ điều hành nhưng đặc biệt là trong Win64.
  2. Viết một lớp ngoại lệ lỗi hệ thống (được sử dụng cho lớp trên trong trường hợp CreateFile() không thành công và cho tất cả các lỗi hệ thống khác) hoặc điều tra, lớp system_exception mới (trong C++ 0x) thực sự đang làm gì và nếu nó là đủ.
  3. viết một wrapper chức năng cho ReadFile() và WriteFile() mà chuyển đổi một lỗi hệ thống vào một đối tượng hệ thống ném ngoại lệ ...
  4. có khả năng xác định giao diện của riêng bạn để ghi vào đâu đó và đọc từ một nơi nào đó mà bạn có thể thực hiện những thứ khác độc lập với loại nguồn/đích để đọc từ/ghi tới.
  5. Viết một lớp bộ nhớ cache cho phép bạn đọc bộ nhớ cache từ đâu đó hoặc viết ở đâu đó cũng là trò chơi trẻ em. Tất nhiên lớp bộ nhớ cache không nên biết và cũng không quan tâm đến nguồn/đích mà bạn đang viết/đọc từ đó.

Đừng lo lắng về những tác vụ nhỏ này. Bạn sẽ thực sự biết, những gì đang xảy ra trong mã của bạn và những đoạn mã nhỏ này sẽ không đáng kể (trong số lượng dòng mã) so với mã gọi nó. Ngoài ra nếu bạn đang sử dụng RAII cho tất cả mọi thứ, mã gọi vào các lớp tiện ích này sẽ ít hơn đáng kể so với khi không sử dụng RAII và phải sử dụng hai hoặc thậm chí nhiều bước khởi tạo hơn và ít xảy ra lỗi hơn đáng kể.Thay thế các lớp tiện ích này với các lớp tiện ích tương đương cho hệ điều hành khác cũng là cách chơi con (sử dụng mở()/close()/read()/write() trên UNIX).

Và vì lợi ích của thiên niên kỷ trước không đọc nguyên tắc lập trình của Google!

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