我想删除位于文件中间的数据,因为文件很大,我想避免重写整个文件。要移动我正在尝试的数据:从数据结束(字节位置)到文件结束->到数据开始(字节位置),然后截断文件到文件大小-数据大小。
我有这个代码,但我不能让它在同一时间读取和写入同一个文件…
' Read from end of data in file to byte position of start of data in file
Using inFile As New System.IO.FileStream(NAME, IO.FileMode.Open, IO.FileAccess.Read)
Using outFile As New System.IO.FileStream(NAME, IO.FileMode.Open, IO.FileAccess.Write)
inFile.Seek((START_POS + DATA_SIZE), IO.SeekOrigin.Begin)
outFile.Seek(START_POS, IO.SeekOrigin.Begin)
Do
If FILESIZE - CURRENT_TOTAL_READ < BUFFER_SIZE Then
ReDim BUFFER((FILESIZE - 1) - CURRENT_TOTAL_READ)
End If
BYTES_READ = inFile.Read(BUFFER, 0, BUFFER.Length)
If BYTES_READ > 0 Then
outFile.Write(BUFFER, 0, BYTES_READ)
CURRENT_TOTAL_READ += BYTES_READ
End If
Loop While BYTES_READ > 0 AndAlso CURRENT_TOTAL_READ < (DATA_SIZE- 1)
End Using
End Using
TOTAL_PROCESSED_DATA += CURRENT_TOTAL_READ
' truncate file to file size - data size
TRUNCATE(NAME, (FILESIZE - DATA_SIZE))
您可以使用一个文件流,并在每次读写之前设置其位置。
反对:
- 如果它出了问题(例如电源故障),你将有一个大烂摊子要清理
- 如果你使用的是硬盘驱动器,那就有点残忍了如果你没有合适的
BUFFERSIZE
话虽如此,下面的操作只需要几秒钟就可以在SSD上切掉1GB文件开头的一小部分,而在HDD上则不到十秒钟。
注意:我做了一个偶然的检查,它的工作正常,但有可能是一个off-by- 1错误在那里的某个地方。
Imports System.IO
Module Module1
Sub CreateTestData(filename As String)
If File.Exists(filename) Then
File.Delete(filename)
End If
' put AAAA....BBBB... etc at the start of the file for easy inspection
Using sw As New StreamWriter(filename)
For c = Asc("A") To Asc("D")
Dim s = New String(Chr(c), 1024)
sw.Write(s)
Next
End Using
' Make the file 1GB in size.
Using fs As New FileStream(filename, FileMode.Open, FileAccess.ReadWrite, FileShare.None)
fs.SetLength(1024 * 1024 * 1024)
End Using
End Sub
Sub CutMiddleOutOfFile(filename As String, cutPos As Int64, cutLength As Int64)
If cutPos < 0 OrElse cutLength < 0 Then
Throw New ArgumentException("Cut parameters must be positive.")
End If
'TODO: More argument checking regarding cutPos, cutLength, and the length of the file.
' Use a fairly large buffer
Const BUFFERSIZE As Integer = 1024 * 1024
' Let FileStream decide its own internal buffer size.
Using fs As New FileStream(filename, FileMode.Open, FileAccess.ReadWrite, FileShare.None)
Dim buffer(BUFFERSIZE) As Byte
Dim bytesRead As Integer = Integer.MaxValue
Dim currReadPos As Int64 = cutPos + cutLength
Dim currWritePos As Int64 = cutPos
While bytesRead > 0
fs.Position = currReadPos
bytesRead = fs.Read(buffer, 0, BUFFERSIZE)
If bytesRead > 0 Then
fs.Position = currWritePos
fs.Write(buffer, 0, bytesRead)
End If
currReadPos += bytesRead
currWritePos += bytesRead
End While
fs.SetLength(currWritePos)
End Using
End Sub
Sub Main()
Dim filename = "D:tempa.dat"
CreateTestData(filename)
CutMiddleOutOfFile(filename, 2048, 1024)
Console.WriteLine("Done.")
Console.ReadLine()
End Sub
End Module