我需要将文件的前100个字节移动到文件末尾,然后保存该文件(Windows窗体应用程序)。然后我需要相反的过程(将最后的100个字节移回开头,然后再保存)。将文件的前100个字节移动到文件的末尾,然后再保存并再次保存
其中一些文件非常大(超过2GB),所以我不能使用file.readallbytes,因为我内存不足异常。
我试着玩文件流和使用filestream.position,但我无法包住我的头移动字节,然后保存该文件。
任何指导将不胜感激。
我需要将文件的前100个字节移动到文件末尾,然后保存该文件(Windows窗体应用程序)。然后我需要相反的过程(将最后的100个字节移回开头,然后再保存)。将文件的前100个字节移动到文件的末尾,然后再保存并再次保存
其中一些文件非常大(超过2GB),所以我不能使用file.readallbytes,因为我内存不足异常。
我试着玩文件流和使用filestream.position,但我无法包住我的头移动字节,然后保存该文件。
任何指导将不胜感激。
的关键是使用一个字节缓冲器,所以你仅在一次处理的文件的一小部分。这听起来像你有正确的方法,但一路上有一些陷阱。
下面是示出如何我接近它的一个示例:
public enum SwapType
{
FrontToBack,
BackToFront
}
public static class EndSwap
{
public static void DoSwap(string path, SwapType swapType)
{
if (path == null)
{
throw new ArgumentNullException("path",
"You must supply a path to the file.");
}
if (!File.Exists(path))
{
throw new FileNotFoundException("File not found.");
}
string tempPath = Path.GetTempFileName();
byte[] buffer = new byte[4096];
byte[] swapBytes = new byte[100];
using (FileStream inputFs = new FileStream(path, FileMode.Open,
FileAccess.Read))
using (FileStream outputFs = new FileStream(tempPath,
FileMode.Open, FileAccess.Write))
{
int bytesRead = -1;
if (swapType == SwapType.FrontToBack)
{
// We want to keep hold of the first 100 bytes of the file
// and output them after copying the rest of file
inputFs.Read(swapBytes, 0, 100);
}
else
{
// Read the last 100 bytes of the file
inputFs.Seek(-100, SeekOrigin.End);
inputFs.Read(swapBytes, 0, 100);
// Output them straight to the output file
outputFs.Write(swapBytes, 0, 100);
// Reposition to the beginning of the input file
inputFs.Seek(0, SeekOrigin.Begin);
}
// The number of bytes left to copy is 100 less than the file
// length
long bytesRemaining = inputFs.Length - 100;
// Copy the rest of the bytes
while (bytesRemaining > 0)
{
bytesRead = inputFs.Read(buffer, 0, buffer.Length);
// NB: the number of bytes read could be more than the
// number remaining
outputFs.Write(buffer, 0,
(int)Math.Min(bytesRead, bytesRemaining));
bytesRemaining -= bytesRead;
}
// Don't forget to append the start bytes if required
if (swapType == SwapType.FrontToBack)
{
outputFs.Write(swapBytes, 0, 100);
}
}
// Now swap the files themselves
File.Delete(path);
File.Move(tempPath, path);
// NB: could do File.Replace() if backup is needed
}
}
实例:
// Copy first 100 bytes to end
EndSwap.DoSwap(@"C:\Users\Dave\Downloads\MyTest.pdf", SwapType.FrontToBack);
// Copy those same 100 bytes back to the beginning again
EndSwap.DoSwap(@"C:\Users\Dave\Downloads\MyTest.pdf", SwapType.BackToFront);
最终的结果是相同的原始文件,当然。
这是完美的。我希望我可以将这两个答案都标记为正确的,但是由于您提供了如何将其恢复的完整方式,所以这个更好是因为我试图找出另一个答案的返回路径。谢谢。仍然为你们+1 +1) –
您不应将所有数据读入内存。通过使用FileStream,您可以读取多个数据块,例如每个1 KB,并将其存储在新文件中。从位置100开始,跳过第一个字节。重新整理完整文件后,在末尾添加跳过的字节。最后将新文件移动到旧文件的位置。通过提高maxBufferSize,您可以固定复制过程,但使用更多的内存。
要恢复更改,请从最后100个字节开始,然后从开始直到inputStream.Length - 100
。
string inputFile = "C:\\input.txt";
string tempFile = "C:\\input.txt";
int dataLength = 100;
int maxBufferSize = 1024;
using (var inputStream = new FileStream(inputFile, FileMode.Open, FileAccess.Read)) {
int length = (int)inputStream.Length;
int currentInputPosition = dataLength;
inputStream.Position = currentInputPosition;
using (var outputStream = new FileStream(tempFile, FileMode.Create, FileAccess.ReadWrite)) {
var bufferSize = Math.Min(maxBufferSize, length - currentInputPosition);
var buffer = new byte[bufferSize];
while (inputStream.Read(buffer, 0, bufferSize) > 0) {
currentInputPosition += bufferSize;
outputStream.Write(buffer, 0, buffer.Length);
}
buffer = new byte[dataLength];
inputStream.Position = 0;
inputStream.Read(buffer, 0, buffer.Length);
outputStream.Write(buffer, 0, buffer.Length);
}
}
File.Delete(inputFile);
File.Move(tempFile, inputFile);
非常感谢。尽管我对转换有点困惑。我从最后100开始,如下所示:int currentInputPosition = length - 100;并在我的while循环中将这些前100个字节写入新文件。我然后设置我的currentInputPosition = 0;从一开始就开始,但我不确定在哪里放置循环的边界来停止? –
这将涉及物理移动字节。所以你只要读取第101个字节并写入第1个字节即可。然后,第102个到第2个,...然后您将最初存储在某个数组中的前100个字节追加到最后并获得一个赢家啤酒。 – zerkms
我很好,只是使第一个100字节0的,如果这使得它更容易,然后将它们添加到文件的末尾。然后当发生相反的情况时,用结尾的实际值替换那些0字节并删除尾部的100 ... –