Чтение файла по одному байту за раз в обратном порядке
Привет, я пытаюсь прочитать файл по одному байту за раз в обратном порядке. До сих пор мне удалось только прочитать файл с начала и до конца и записать его в другой файл.
Мне нужно иметь возможность прочитать файл с конца до начала и распечатать его в другой файл.
Это то, что я до сих пор:
string fileName = Console.ReadLine();
using (FileStream file = new FileStream(fileName ,FileMode.Open , FileAccess.Read))
{
//file.Seek(endOfFile, SeekOrigin.End);
int bytes;
using (FileStream newFile = new FileStream("newsFile.txt" , FileMode.Create , FileAccess.Write))
{
while ((bytes = file.ReadByte()) >= 0)
{
Console.WriteLine(bytes.ToString());
newFile.WriteByte((byte)bytes);
}
}
}
Я знаю, что мне нужно использовать метод Seek в fileStream, и это приводит меня к концу файла. Я уже делал это в прокомментированном виде кода, но сейчас я не знаю, как читать файл петля.
Как я могу достичь этого?
4 ответа
string fileName = Console.ReadLine();
using (FileStream file = new FileStream(fileName, FileMode.Open, FileAccess.Read))
{
byte[] output = new byte[file.Length]; // reversed file
// read the file backwards using SeekOrigin.Current
//
long offset;
file.Seek(0, SeekOrigin.End);
for (offset = 0; offset < fs.Length; offset++)
{
file.Seek(-1, SeekOrigin.Current);
output[offset] = (byte)file.ReadByte();
file.Seek(-1, SeekOrigin.Current);
}
// write entire reversed file array to new file
//
File.WriteAllBytes("newsFile.txt", output);
}
Вы можете сделать это, читая по одному байту за раз, или вы можете прочитать больший буфер, записать его в выходной файл в обратном порядке и продолжать так до тех пор, пока не достигнете начала файла. Например:
string inputFilename = "inputFile.txt";
string outputFilename = "outputFile.txt";
using (ofile = File.OpenWrite(outputFilename))
{
using (ifile = File.OpenRead(inputFilename))
{
int bufferSize = 4096;
byte[] buffer = new byte[bufferSize];
long filePos = ifile.Length;
do
{
long newPos = Math.Max(0, filePos - bufferSize);
int bytesToRead = (int)(filePos - newPos);
ifile.Seek(newPos, SeekOrigin.Set);
int bytesRead = ifile.Read(buffer, 0, bytesToRead);
// write the buffer to the output file, in reverse
for (int i = bytesRead-1; i >= 0; --i)
{
ofile.WriteByte(buffer[i]);
}
filePos = newPos;
} while (filePos > 0);
}
}
Очевидная оптимизация - обратный буфер после того, как вы его прочитали, а затем записали его одним целым фрагментом в выходной файл.
И если вы знаете, что файл поместится в память, это действительно просто:
var buffer = File.ReadAllBytes(inputFilename);
// now, reverse the buffer
int i = 0;
int j = buffer.Length-1;
while (i < j)
{
byte b = buffer[i];
buffer[i] = buffer[j];
buffer[j] = b;
++i;
--j;
}
// and write it
File.WriteAllBytes(outputFilename, buffer);
Если файл небольшой (умещается в вашей оперативной памяти), то это сработает:
public static IEnumerable<byte> Reverse(string inputFilename)
{
var bytes = File.ReadAllBytes(inputFilename);
Array.Reverse(bytes);
foreach (var b in bytes)
{
yield return b;
}
}
Применение:
foreach (var b in Reverse("smallfile.dat"))
{
}
Если файл большой (больше, чем ваша оперативная память), то это будет работать:
using (var inputFile = File.OpenRead("bigfile.dat"))
using (var inputFileReversed = new ReverseStream(inputFile))
using (var binaryReader = new BinaryReader(inputFileReversed))
{
while (binaryReader.BaseStream.Position != binaryReader.BaseStream.Length)
{
var b = binaryReader.ReadByte();
}
}
Он использует
ReverseStream
класс, который можно найти здесь.