Esto es porque truncate no cambia la posición de la secuencia.
Cuando read()
el archivo, mueve la posición hasta el final. Entonces write
sucesivos escribirán en el archivo desde esa posición. Sin embargo, cuando llama al flush()
, parece que no solo intenta escribir el búfer en el archivo, sino que también realiza una comprobación de errores y corrige la posición actual del archivo. Cuando se llama al Flush()
después del truncate(0)
, no escribe nada (el búfer está vacío), luego verifica el tamaño del archivo y coloca la posición en el primer lugar aplicable (que es 0
).
ACTUALIZACIÓN
función de archivo de Python no son sólo las envolturas alrededor de los equivalentes de la biblioteca estándar de C, pero sabiendo las funciones de C ayuda a saber lo que está sucediendo con mayor precisión.
Desde el ftruncate man page:
El valor del puntero buscar no se modifica por una llamada a ftruncate().
Desde el fflush man page:
Si los puntos de flujo a un flujo de entrada o un canal de actualización en el que la operación más reciente fue de entrada, esa corriente se vacía si es reubicable y no está ya al final -de-archivo. La descarga de una secuencia de entrada descarta cualquier entrada almacenada en el búfer y ajusta el puntero del archivo de modo que la siguiente operación de entrada acceda al byte después de la última lectura.
Esto significa que si pone flush
antes de truncate
no tiene ningún efecto. Lo revisé y fue así.
Pero para poner flush
después truncate
:
Si los puntos de flujo para un flujo de salida o un canal de actualización en el que la operación más reciente no era de entrada, fflush() hace que los datos no guardados de esa corriente sea escrito en el archivo, y los campos st_ctime y st_mtime del archivo subyacente están marcados para su actualización.
La página man no menciona el puntero de búsqueda al explicar flujos de salida con la última operación sin entrada. (Aquí la última operación es truncate
)
ACTUALIZACIÓN 2
he encontrado algo en el código fuente de Python: Python-3.2.2\Modules\_io\fileio.c:837
#ifdef HAVE_FTRUNCATE
static PyObject *
fileio_truncate(fileio *self, PyObject *args)
{
PyObject *posobj = NULL; /* the new size wanted by the user */
#ifndef MS_WINDOWS
Py_off_t pos;
#endif
...
#ifdef MS_WINDOWS
/* MS _chsize doesn't work if newsize doesn't fit in 32 bits,
so don't even try using it. */
{
PyObject *oldposobj, *tempposobj;
HANDLE hFile;
////// THIS LINE //////////////////////////////////////////////////////////////
/* we save the file pointer position */
oldposobj = portable_lseek(fd, NULL, 1);
if (oldposobj == NULL) {
Py_DECREF(posobj);
return NULL;
}
/* we then move to the truncation position */
...
/* Truncate. Note that this may grow the file! */
...
////// AND THIS LINE //////////////////////////////////////////////////////////
/* we restore the file pointer position in any case */
tempposobj = portable_lseek(fd, oldposobj, 0);
Py_DECREF(oldposobj);
if (tempposobj == NULL) {
Py_DECREF(posobj);
return NULL;
}
Py_DECREF(tempposobj);
}
#else
...
#endif /* HAVE_FTRUNCATE */
mirada a las dos líneas que he indicado (///// This Line /////
). Si su plataforma es Windows, está guardando la posición y devolviéndola después del truncado.
Para mi sorpresa, la mayoría de las funciones flush
dentro de las funciones de Python 3.2.2 o no hicieron nada o no llamaron a la función C fflush
en absoluto. La parte truncada 3.2.2 también estaba muy indocumentada. Sin embargo, encontré algo interesante en las fuentes de Python 2.7.2. En primer lugar, me encontré con esto en Python-2.7.2\Objects\fileobject.c:812
en truncate
aplicación:
/* Get current file position. If the file happens to be open for
* update and the last operation was an input operation, C doesn't
* define what the later fflush() will do, but we promise truncate()
* won't change the current position (and fflush() *does* change it
* then at least on Windows). The easiest thing is to capture
* current pos now and seek back to it at the end.
*/
Entonces, para resumir todo, creo que esto es una cosa totalmente dependientes de la plataforma. Comprobé el Python 3.2.2 predeterminado para Windows x64 y obtuve los mismos resultados que tú. No sé lo que sucede en * nixes.
Por lo que puedo decir, ejecutar 'truncate (0)' simplemente establece el tamaño del archivo en 0 bytes y mueve el puntero del archivo al inicio del búfer. Cuando escribe en la secuencia antes de la descarga, el estado del búfer no está definido. Cuando descarga, pueden aparecer datos basura de ese búfer. La regla general que aplicaría es que debe enjuagar cada vez que intente * eliminar * cualquier cosa, o cuando deba asegurarse de que el archivo se encuentre en un estado particular antes de continuar. – Polynomial
¿qué hay de cerrar el archivo? – joaquin
@El lavado polinómico no funciona, me equivoqué ... – Beginner