Tuvimos una discusión aquí en el trabajo sobre por qué fread y fwrite toman un tamaño por miembro y cuentan y devuelven el número de miembros leídos / escritos en lugar de simplemente tomar un búfer y un tamaño. El único uso que se nos puede ocurrir es si desea leer / escribir una matriz de estructuras que no son divisibles por la alineación de la plataforma y, por lo tanto, se han rellenado, pero que no pueden ser tan comunes como para justificar esta elección. en diseño.
Desde FREAD (3) :
La función fread () lee nmemb elementos de datos, cada tamaño en bytes, del flujo al que apunta el flujo, almacenándolos en la ubicación dada por ptr.
La función fwrite () escribe nmemb elementos de datos, cada tamaño en bytes, en el flujo al que apunta el flujo, obteniéndolos de la ubicación dada por ptr.
fread () y fwrite () devuelven el número de elementos leídos o escritos correctamente (es decir, no el número de caracteres). Si se produce un error o se llega al final del archivo, el valor devuelto es un recuento corto de elementos (o cero).
Respuestas:
Se basa en cómo se implementa fread .
La Especificación Única de UNIX dice
fgetc también tiene esta nota:
Por supuesto, esto es anterior a las sofisticadas codificaciones de caracteres de bytes variables como UTF-8.
El SUS señala que esto en realidad se toma de los documentos ISO C.
fuente
La diferencia en fread (buf, 1000, 1, stream) y fread (buf, 1, 1000, stream) es que, en el primer caso, solo obtiene un fragmento de 1000 bytes o nuthin, si el archivo es más pequeño y en el En segundo caso, todo lo que hay en el archivo es menor y hasta 1000 bytes.
fuente
Esto es pura especulación, sin embargo, en el pasado (algunos todavía existen) muchos sistemas de archivos no eran simples flujos de bytes en un disco duro.
Muchos sistemas de archivos se basaban en registros, por lo que para satisfacer dichos sistemas de manera eficiente, deberá especificar el número de elementos ("registros"), permitiendo que fwrite / fread opere en el almacenamiento como registros, no solo como flujos de bytes.
fuente
Aquí, déjame arreglar esas funciones:
En cuanto a la justificación de los parámetros de
fread()
/fwrite()
, perdí mi copia de K&R hace mucho tiempo, así que solo puedo adivinar. Creo que una respuesta probable es que Kernighan y Ritchie simplemente pensaron que la realización de E / S binarias se haría de forma más natural en matrices de objetos. Además, es posible que hayan pensado que la E / S en bloque sería más rápida / fácil de implementar o lo que sea en algunas arquitecturas.Aunque el estándar C especifica eso
fread()
yfwrite()
debe implementarse en términos defgetc()
yfputc()
, recuerde que el estándar entró en existencia mucho después de que K&R definiera C y que las cosas especificadas en el estándar podrían no haber estado en las ideas originales de los diseñadores. Incluso es posible que las cosas que se dicen en "El lenguaje de programación C" de K&R no sean las mismas que cuando se diseñó el lenguaje por primera vez.Finalmente, esto es lo que PJ Plauger tiene que decir
fread()
en "The Standard C Library":Básicamente, está diciendo que
fread()
la interfaz está rota. Porquefwrite()
señala que, "los errores de escritura son generalmente raros, por lo que esto no es un defecto importante", una afirmación con la que no estaría de acuerdo.fuente
fread(buf, size*n, 1, stream);
si las lecturas incompletas son una condición de error, es más sencillo disponerfread
que simplemente devuelva 0 o 1 en lugar de la cantidad de bytes leídos. Luego, puede hacer cosas como enif (!fread(...))
lugar de tener que comparar el resultado con la cantidad solicitada de bytes (que requiere código C adicional y código de máquina adicional).Probablemente se remonta a la forma en que se implementó la E / S de archivo. (en el pasado) Podría haber sido más rápido escribir / leer archivos en bloques que escribir todo a la vez.
fuente
Tener argumentos separados para el tamaño y el recuento podría ser ventajoso en una implementación que puede evitar leer registros parciales. Si se usaran lecturas de un solo byte de algo como una tubería, incluso si se usaran datos de formato fijo, se tendría que permitir la posibilidad de que un registro se divida en dos lecturas. En cambio, si pudiera solicitar, por ejemplo, una lectura sin bloqueo de hasta 40 registros de 10 bytes cada uno cuando hay 293 bytes disponibles, y hacer que el sistema devuelva 290 bytes (29 registros completos) dejando 3 bytes listos para la siguiente lectura, eso sería será mucho más conveniente.
No sé hasta qué punto las implementaciones de fread pueden manejar tal semántica, pero ciertamente podrían ser útiles en implementaciones que podrían prometer respaldarlas.
fuente
fread(buffer, 10000, 2, stdin)
y el usuario escribe newline-ctrl-D después de escribir 18,000 bytes, sería bueno si la función pudiera devolver los primeros 10,000 bytes mientras deja los 8,000 restantes pendientes para futuras solicitudes de lectura más pequeñas, pero ¿están ahí? ¿Alguna implementación donde eso sucedería? ¿Dónde se almacenarían los 8.000 bytes en espera de esas solicitudes futuras?size
más de 1, bueno ... Para el registro, también puede haber ioctls u otras tonterías que puedes aplicar a la transmisión para hacerlo comportarse de manera diferente, no he profundizado tanto.fread
trabajo que describió en tales transmisiones sería útil si hubiera alguna forma de identificar las transmisiones que funcionan de esa manera.Creo que es porque C carece de sobrecarga de funciones. Si hubiera alguno, el tamaño sería redundante. Pero en C no puede determinar el tamaño de un elemento de matriz, debe especificar uno.
Considera esto:
Si fwrite acepta el número de bytes, puede escribir lo siguiente:
Pero es simplemente ineficiente. Tendrá un tamaño de (int) veces más llamadas al sistema.
Otro punto que debe tenerse en cuenta es que normalmente no desea que una parte de un elemento de matriz se escriba en un archivo. Quieres el entero entero o nada. fwrite devuelve una serie de elementos escritos con éxito. Entonces, si descubre que solo se escriben 2 bytes bajos de un elemento, ¿qué haría?
En algunos sistemas (debido a la alineación) no puede acceder a un byte de un entero sin crear una copia y cambiar.
fuente