2012-05-28 18 views

Respuesta

7

Depende de lo que esté haciendo. Para leer y escribir secuencialmente archivos de texto, iostream es definitivamente el camino a seguir. Para cualquier cosa que implique seguridad transaccional o dispositivos no estándar, tendrá que acceder al sistema directamente (CreateFile o open). Incluso entonces, para la lectura secuencial y la escritura de texto, la mejor solución es definir su propio streambuf, y usarlo con iostream.

No puedo pensar en ningún contexto en el que sea preferible fopen.

+0

Quiero poder :) escribir y leer binario. solo para sistemas de Windows. Como escuché abrir y fopen no coincidir con createfile, esto es cierto? – Eveler

+1

@Eveler: si quieres plena potencia, lo más rápido que puedes hacer para procesar un archivo es abrirlo con 'CreateFile' y asignarlo a la memoria con' CreateFileMapping', como se ilustra en [esta publicación del blog] (http: //blogs.msdn.com/b/oldnewthing/archive/2005/05/13/417183.aspx), que es parte de una serie de optimización que comienza desde [estándar C++] (http://blogs.msdn.com/ b/oldnewthing/archive/2005/05/10/415991.aspx) y luego se mueve progresivamente a [Win32 optimized code] (http://blogs.msdn.com/b/oldnewthing/archive/2005/05/19/420038 .aspx). Pero en la mayoría de los casos, los estándares simples C y C++ están bien. –

+3

'fopen' es una función de nivel superior, reemplazada por' fstream :: open' en C++. 'CreateFile' y' open' son funciones de nivel de sistema, la primera en Windows, la segunda en Unix. No ofrecen exactamente lo mismo, ya que los sistemas admiten diferentes características de forma diferente. –

1

En la mayoría de los casos, será mejor utilizar fopen en C o ofstream en C++. CreateFile ofrece cierto control adicional sobre el uso compartido y el almacenamiento en caché, pero no brinda funcionalidad de formateo.

+1

Así que escribe un 'streambuf' que usa' CreateFile' de la manera que necesita usarlo, y obtiene las ventajas de ambos. –

+0

Siempre me he preguntado por qué es tan engorroso enchufar una nueva fuente o destino en IOstreams. En todo caso, C++ hace que sea fácil declarar una clase abstracta pura para un escritor/lector de datos ... –

4

A menos que necesite las características proporcionadas por las funciones de archivos de Windows (por ejemplo, que se superponen/O), entonces mi sugerencia va, ya sea con iostreams en C++ o FILE (fopen y amigos) en C.

Además de ser más portátil , también puede usar entrada/salida formateada para archivos de texto, y para C++ es fácil sobrecargar los operadores de salida/entrada para sus clases.

+2

También es fácil derivar de 'std :: streambuf' y para algunas de las características" especiales "(integridad transaccional, dispositivos especiales) , etc.) –

2

A menos que absoulutely necesita la funcionalidad adicional proporcionada por las funciones de la API del sistema operativo (como CreateFile) me recomendaría el uso de las funciones de la librería estándar (como fopen o ofstream). De esta manera, su programa será más portátil.

La única ventaja real de utilizar CreateFile que puedo pensar es E/S solapada y quizás derechos de acceso más finos.

+2

Createfile puede abrir una ruta de archivo de más de 260 caracteres de longitud. – Eveler

+0

¡Bastante justo! +1 – cyco130

2

Si desea utilizar archivos de Windows mapeo de memoria se debe utilizar CreateFile (por ejemplo, la HANDLE pasado a CreateFileMapping API es el valor de retorno de CreateFile). Además, CreateFile ofrece mayores opciones de personalización que la API de archivo estándar C y C++.

Sin embargo, si desea escribir código portable, o si no necesita características específicas de Windows, las API de archivo estándar C y C++ están bien. En algunas pruebas, al procesar datos de gran tamaño, noté cierta sobrecarga de rendimiento de flujos de E/S de C++ vs. API de archivos en C sin formato; si te encuentras en casos como este, simplemente puedes ajustar la API de archivo C sin procesar en alguna clase C++ RAII, y aún así usarla en código C++.

+0

Necesito grandes archivos de datos de 4GB a 10GB + y el mapeo de mem también lo usaré. – Eveler

+0

Por lo tanto, si necesita mapeo de memoria puede usar llamadas directas a la API Win32 y envolverlas en clases C++ RAII. –

0

copié mi respuesta de

fopen or CreateFile in Windows

que estaba cerrado por alguna razón, que se me escapa ...

  1. No hay manera definida por fopen() para devolver el error del sistema código.Puede haber una forma indefinida de acceder a errno, pero esto podría ser idéntico o no al código de error del sistema.
  2. Además, no creo que haya una forma definida de acceder al identificador del sistema real (de tipo HANDLE) que a su vez podría querer utilizar para pasar a una de las muchas llamadas al sistema win64 que esperan tal identificador del sistema (p. ej. IO asignado a la memoria)
  3. Usando open() un entero representa el identificador del archivo, que no es el identificador del sistema (en Windows).
  4. fopen() no arroja una excepción en caso de error. Para tener algo de RAII necesitarás envolverlo en una clase.
  5. Enlazar CreateFile() en una clase, no es más caro que envolver fopen() o open() en una clase.
  6. Mediante la función de C++ (std :: ofstream, std :: ifstream) para escribir/leer a/de archivos adolece del mismo problema que fopen():
    • No tirar por defecto en caso de error. Para habilitar esta característica necesita llamar a algún método en lugar de poder usar algún argumento de constructor - significa que para RAII necesitaría derivar esta clase (para usarlo como miembro/clase base que se lanza por error) .
    • No está definido si uno puede recuperar el código de error del sistema de la excepción lanzada o si el mensaje devuelto por what() le dice algo sobre el error del sistema.
    • Al usar esta interfaz de transmisión no existe una interfaz realmente conectable para definir la fuente o el destino de lectura o escritura. La sobrecarga de la interfaz de flujo es bastante engorrosa y propensa a errores.
  7. Usando C como la programación (prestar atención a ignorar o códigos de retorno y escribir manualmente el código de limpieza) es la fuente de muchos males (recuerde corazón sangra?) ...

Conclusiones:

  1. escribe un contenedor de recursos para CreateFile()/CloseHandle(). El contenedor de recursos es una clase que realiza la acción en el constructor y la acción de deshacer en el destructor y arroja una excepción en caso de error. Existen muchos pares de llamadas al sistema en cada sistema operativo, pero especialmente en Win64.
  2. Escriba una clase de excepción de error de sistema (para utilizar para la clase anterior en caso de que CreateFile() falle y para todos los demás errores de sistema) o investigue qué está haciendo realmente la nueva clase system_exception (en C++ 0x) y si es suficiente
  3. escribir un envoltorio funcional para ReadFile() y WriteFile() que convierte un error del sistema en un objeto de excepción del sistema tirado ...
  4. definen potencialmente su propia interfaz para escribir en alguna parte y leer desde algún lugar por lo que se puede implementar otras cosas independientes del tipo de fuente/destino desde el que leer/escribir.
  5. Escribir una clase de caché que le permita almacenar en caché la lectura desde algún lugar o escribir en algún lugar también es un juego de niños. Por supuesto, la clase de caché no debe saber ni preocuparse por la fuente/destino desde el que está escribiendo/leyendo.

No tengas miedo de estas pequeñas tareas. En realidad sabrá qué está sucediendo en su código y estos pequeños fragmentos de código deberían ser insignificantes (en cantidad de líneas de código) en comparación con el código que lo llama. Además, si usa RAII para todo, el código que invoca estas clases de utilidad será considerablemente menor en comparación con cuando no se usa RAII y teniendo que usar dos o incluso más pasos de inicialización y mucho menos propenso a errores.Reemplazar estas clases de utilidad con clases de utilidad equivalentes para otro SO también es un juego de niños (usando open()/close()/read()/write() en UNIX).

Y por el bien de los milenios anteriores, ¡no lea las pautas de programación de google!

Cuestiones relacionadas