ejemplo - get info file c#
.NET FileInfo.LastWriteTime & FileInfo.LastAccessTime son incorrectos (7)
¿Ha intentado llamar a Refresh()
justo antes de acceder a la propiedad (para evitar obtener un valor en caché)? Si eso no funciona, ¿has visto lo que muestra Explorer al mismo tiempo? Si Explorer muestra la información incorrecta, probablemente sea algo que realmente no pueda resolver, es posible que la información solo se actualice cuando el identificador de archivo está cerrado, por ejemplo.
Cuando llamo FileInfo(path).LastAccessTime
o FileInfo(path).LastWriteTime
en un archivo que está en proceso de ser escrito devuelve la hora en que se creó el archivo, no la última vez que se escribió (es decir, ahora) .
¿Hay alguna manera de obtener esta información?
Edit: A todas las respuestas hasta ahora. No había probado Refresh()
pero eso tampoco lo hace. Me devolvieron la hora en que se comenzó a escribir el archivo. Lo mismo ocurre con el método estático y la creación de una nueva instancia de FileInfo
.
Codymanix podría tener la respuesta, pero no estoy ejecutando Windows Server (usando Windows 7), y no sé cuál es la configuración para probar.
Edición 2: ¿A nadie le parece interesante que esta función no parezca funcionar?
A partir de Windows Vista, el último tiempo de acceso no se actualiza de forma predeterminada. Esto es para mejorar el rendimiento del sistema de archivos. Puedes encontrar los detalles aquí:
Para volver a habilitar el último tiempo de acceso en la computadora, puede ejecutar el siguiente comando:
Comportamiento fsutil deshabilitar accesaclato 0
Como James ha señalado, LastAccessTime no se actualiza .
El LastWriteTime también ha sufrido un giro desde Vista. Cuando el proceso tiene el archivo aún abierto y otro proceso verifica el LastWriteTime, no verá el nuevo tiempo de escritura durante mucho tiempo, hasta que el proceso haya cerrado el archivo.
Como solución alternativa, puede abrir y cerrar el archivo desde su proceso externo. Una vez que haya hecho eso, puede intentar leer el LastWriteTime nuevamente, que es el valor actualizado.
Sistema de archivos de túnel:
Si una aplicación implementa algo así como un registrador rodante que cierra el archivo y luego le cambia el nombre a un nombre de archivo diferente, también tendrá problemas ya que el sistema operativo recuerda el tiempo de creación y el tamaño del archivo "antiguo", aunque usted creó un nuevo archivo. Esto incluye informes erróneos del tamaño del archivo, incluso si recreaste log.txt desde cero, que todavía tiene un tamaño de 0 bytes. Esta función se denomina Túnel del sistema de archivos del sistema operativo que todavía está presente en Windows 8.1. Un ejemplo de cómo solucionar este problema revisa RollingFlatFileTracelistener de Enterprise Library .
Puede ver los efectos de la tunelización del sistema de archivos en su propia máquina desde el shell cmd.
echo test > file1.txt
ren file1.txt file2.txt
Wait one minute
echo test > file1.txt
dir /tc file*.txt
...
05.07.2015 19:26 7 file1.txt
05.07.2015 19:26 7 file2.txt
El sistema de archivos es una máquina de estados. Mantener los estados correctamente sincronizados es difícil si le importa el rendimiento y la corrección.
Obviamente, este extraño síndrome de tunelización todavía es utilizado por aplicaciones que, por ejemplo, guardan automáticamente un archivo y lo mueven a una ubicación de guardado y luego lo vuelven a crear en la misma ubicación. Para estas aplicaciones tiene sentido darle al archivo una nueva fecha de creación, ya que solo se ha copiado. Algunos instaladores también realizan estos trucos para mover los archivos temporalmente a una ubicación diferente y volver a escribir el contenido más adelante para superar algunos archivos existentes. Verifique si hay algunos ganchos de instalación.
Desde MSDN:
Cuando se llama por primera vez, FileSystemInfo llama a Actualizar y devuelve la información almacenada en caché en las API para obtener atributos, etc. En las llamadas subsiguientes, debe llamar a Actualizar para obtener la última copia de la información.
Si su aplicación es la que escribe, creo que tendrá que "tocar" el archivo estableciendo la propiedad LastWriteTime entre cada búfer de datos que escriba. Algunos psuedocode:
while(bytesWritten < totalBytes)
{
bytesWritten += br.Write(buffer);
myFileInfo.LastWriteTime = DateTime.Now;
}
No estoy seguro de cuán severamente afectará esto al rendimiento de escritura.
Hay una configuración en Windows que a veces se establece especialmente en los sistemas de servidor para que los tiempos de acceso y modificación de los archivos no se configuren para un mejor rendimiento.
La respuesta de Tommy Carlier me hizo pensar ...
Una buena manera de visualizar las diferencias es ejecutar los dos fragmentos de código (acabo de usar LinqPAD) de forma similar a la vez que se ejecuta el Monitor de proceso de sysinternals.
while(true)
File.GetLastAccessTime([file path here]);
y
FileInfo bob = new FileInfo(path);
while(true){
string accessed = bob.LastAccessTime.ToString();
}
Si observa Process Monitor mientras ejecuta el primer fragmento de código, verá intentos repetidos y constantes de acceso al archivo para el proceso LinqPAD. El segundo fragmento hará un acceso inicial al archivo, para el cual verá la actividad en el monitor de proceso, y luego muy poco.
Sin embargo, si vas y modificas el archivo (acabo de abrir el archivo de texto que estaba monitoreando con FileInfo y añadí un carácter y guardé), verás una serie de intentos de acceso del proceso de LinqPAD al archivo en el monitor de proceso.
Esto ilustra el comportamiento no en caché y en caché de los dos enfoques diferentes respectivamente.
¿El enfoque no almacenado en caché llevará un agujero en el disco duro?
EDITAR
Me fui sintiéndome muy inteligente en mis pruebas y luego usé el comportamiento de almacenamiento en caché de FileInfo en mi servicio de Windows (básicamente para sentarme en un bucle y decir ''Ha cambiado el archivo ha cambiado el archivo ...'' antes de procesar)
Si bien este enfoque funcionó en mi caja de desarrollo, no funcionó en el entorno de producción, es decir, el proceso siguió ejecutándose independientemente de si el archivo había cambiado o no. Terminé cambiando mi enfoque de verificación y solo usé GetLastAccessTime como parte de él. No sé por qué se comportaría de manera diferente en el servidor de producción ... pero no estoy muy preocupado en este punto.
Los valores de FileInfo
solo se cargan una vez y luego se guardan en caché. Para obtener el valor actual, llame a Refresh()
antes de obtener una propiedad:
f.Refresh();
t = f.LastAccessTime;
Otra forma de obtener el valor actual es mediante el uso de métodos estáticos en la clase de File
:
t = File.GetLastAccessTime(path);