c# - que - metodo flush()
Creo que es seguro usar una declaración simple de uso , que cierra el flujo después de la llamada a GetBytes () ;
public static byte[] GetBytes(string fileName)
{
byte[] buffer = new byte[4096];
using (FileStream fs = new FileStream(fileName))
using (MemoryStream ms = new MemoryStream())
{
fs.BlockCopy(ms, buffer, 4096); // extension method for the Stream class
fs.Close();
return ms.ToByteArray();
}
}
Envuelva el FileStream
en un BufferedStream
y cierre el flujo de archivos antes del flujo en búfer.
var fs = new FileStream(...);
var bs = new BufferedStream(fs, buffersize);
bs.Write(datatosend, 0, length);
fs.Close();
try {
bs.Close();
}
catch (IOException) {
}
He estado rastreando un error recientemente introducido que parece indicar que .NET 4 no elimina de forma confiable los cambios en el disco cuando se elimina la secuencia (a diferencia de .NET 2.0 y 3.5, que siempre lo hizo de manera confiable).
La clase FileStream de .NET 4 ha sido fuertemente modificada en .NET 4, y mientras que los métodos de Flush * () se han reescrito, parece que se ha olvidado una atención similar para .Dispose ().
Esto está resultando en archivos incompletos.
MSDN no está 100% limpio, pero Jon Skeet está diciendo "Flush", así que hazlo antes de cerrar / eliminar. No dolerá, ¿verdad?
De FileStream. Método de cierre :
Todos los datos escritos previamente en el búfer se copian en el archivo antes de que se cierre la secuencia del archivo, por lo que no es necesario llamar a Flush antes de invocar Close. Después de una llamada a Cerrar, cualquier operación en la secuencia de archivos puede generar excepciones. Después de haber llamado a Close una vez, no hace nada si se llama nuevamente
La disposición no es tan clara:
Este método elimina el flujo, escribiendo cualquier cambio en el almacén de respaldo y cerrando el flujo para liberar recursos.
Observación: los comentaristas pueden estar en lo cierto, no está claro al 100% del Flush:
Reemplace el Flush en las secuencias que implementan un búfer. Utilice este método para mover cualquier información de un búfer subyacente a su destino, borrar el búfer o ambos. Dependiendo del estado del objeto, es posible que deba modificar la posición actual dentro de la secuencia (por ejemplo, si la secuencia subyacente admite la búsqueda). Para información adicional ver CanSeek.
Cuando use la clase StreamWriter o BinaryWriter, no descargue el objeto Stream base. En su lugar, use el método Flush o Close de la clase, que se asegura de que los datos se vacíen primero en el flujo subyacente y luego se escriban en el archivo.
Pruebas:
var textBytes = Encoding.ASCII.GetBytes("Test123");
using (var fileTest = System.IO.File.Open(@"c:/temp/fileNoCloseNoFlush.txt", FileMode.CreateNew))
{
fileTest.Write(textBytes,0,textBytes.Length);
}
using (var fileTest = System.IO.File.Open(@"c:/temp/fileCloseNoFlush.txt", FileMode.CreateNew))
{
fileTest.Write(textBytes, 0, textBytes.Length);
fileTest.Close();
}
using (var fileTest = System.IO.File.Open(@"c:/temp/fileFlushNoClose.txt", FileMode.CreateNew))
{
fileTest.Write(textBytes, 0, textBytes.Length);
fileTest.Flush();
}
using (var fileTest = System.IO.File.Open(@"c:/temp/fileCloseAndFlush.txt", FileMode.CreateNew))
{
fileTest.Write(textBytes, 0, textBytes.Length);
fileTest.Flush();
fileTest.Close();
}
¿Qué puedo decir? ... todos los archivos tienen el texto, ¿es posible que esto sea solo muy poca información?
Prueba2
var rnd = new Random();
var size = 1024*1024*10;
var randomBytes = new byte[size];
rnd.NextBytes(randomBytes);
using (var fileTest = System.IO.File.Open(@"c:/temp/fileNoCloseNoFlush.bin", FileMode.CreateNew))
{
fileTest.Write(randomBytes, 0, randomBytes.Length);
}
using (var fileTest = System.IO.File.Open(@"c:/temp/fileCloseNoFlush.bin", FileMode.CreateNew))
{
fileTest.Write(randomBytes, 0, randomBytes.Length);
fileTest.Close();
}
using (var fileTest = System.IO.File.Open(@"c:/temp/fileFlushNoClose.bin", FileMode.CreateNew))
{
fileTest.Write(randomBytes, 0, randomBytes.Length);
fileTest.Flush();
}
using (var fileTest = System.IO.File.Open(@"c:/temp/fileCloseAndFlush.bin", FileMode.CreateNew))
{
fileTest.Write(randomBytes, 0, randomBytes.Length);
fileTest.Flush();
fileTest.Close();
}
Y nuevamente, cada archivo tiene sus bytes ... para mí, parece que está haciendo lo que leí en MSDN: no importa si llama a Flush o Close antes de deshacerse ... ¿alguna idea sobre eso?
No tiene que llamar a Flush()
en Close()/Dispose()
, FileStream
lo hará por usted como puede ver en su código fuente :
http://referencesource.microsoft.com/#mscorlib/system/io/filestream.cs,e23a38af5d11ddd3
[System.Security.SecuritySafeCritical] // auto-generated
protected override void Dispose(bool disposing)
{
// Nothing will be done differently based on whether we are
// disposing vs. finalizing. This is taking advantage of the
// weak ordering between normal finalizable objects & critical
// finalizable objects, which I included in the SafeHandle
// design for FileStream, which would often "just work" when
// finalized.
try {
if (_handle != null && !_handle.IsClosed) {
// Flush data to disk iff we were writing. After
// thinking about this, we also don''t need to flush
// our read position, regardless of whether the handle
// was exposed to the user. They probably would NOT
// want us to do this.
if (_writePos > 0) {
FlushWrite(!disposing); // <- Note this
}
}
}
finally {
if (_handle != null && !_handle.IsClosed)
_handle.Dispose();
_canRead = false;
_canWrite = false;
_canSeek = false;
// Don''t set the buffer to null, to avoid a NullReferenceException
// when users have a race condition in their code (ie, they call
// Close when calling another method on Stream like Read).
//_buffer = null;
base.Dispose(disposing);
}
}
Usar Flush () es digno dentro de grandes Loops. cuando tienes que leer y escribir un archivo grande dentro de un bucle. En otro caso, el búfer o la computadora son lo suficientemente grandes, y no importa cerrar () sin hacer un Flush () antes.
Ejemplo: TIENE QUE LEER UN GRAN ARCHIVO (en un formato) Y ESCRIBIRLO EN .txt
StreamWriter sw = .... // using StreamWriter
// you read the File ...
// and now you want to write each line for this big File using WriteLine ();
for ( .....) // this is a big Loop because the File is big and has many Lines
{
sw.WriteLine ( *whatever i read* ); //we write here somrewhere ex. one .txt anywhere
sw.Flush(); // each time the sw.flush() is called, the sw.WriteLine is executed
}
sw.Close();
Aquí es muy importante usar Flush (); de lo contrario, de lo contrario, writeLine se guarda en el búfer y no lo escribe hasta que el búfer sea frull o hasta que el programa alcance sw.close ();
Espero que esto ayude un poco a entender la función de Flush.
Ya que ha dicho que entendió que cerrar y desechar se llama método de descarga si no fue llamado explícitamente por el código de usuario, creo que (al cerrar sin descarga) realmente desea tener la posibilidad de descartar los cambios realizados en un FileStream
, si necesario.
Si eso es correcto, usar un FileStream
solo no ayudará. Deberá cargar este archivo en un MemoryStream
(o una matriz, dependiendo de cómo modifique su contenido), y luego decidir si desea guardar los cambios o no una vez que haya terminado.
Un problema con esto es el tamaño del archivo, obviamente. FileStream
utiliza buffers de escritura de tamaño limitado para acelerar las operaciones, pero una vez que se agotan, los cambios deben eliminarse. Debido a los límites de memoria de .NET, solo puede esperar cargar archivos más pequeños en la memoria, si necesita mantenerlos por completo.
Una alternativa más fácil sería hacer una copia en disco de su archivo y trabajar en él usando un FileStream
simple. Cuando haya terminado, si necesita descartar los cambios, simplemente elimine el archivo temporal; de lo contrario, reemplace el original con una copia modificada.