C#: Prepending to Beginning of a File

C#: Prepending to beginning of a file

Adding to the beginning of a file (prepending as opposed to appending) is generally not a supported operation. Your #1 options is fine. If you can't write a temp file, you can pull the entire file into memory, preprend your data to the byte array and then overwrite it back out (this is only really feasible if your files are small and you don't have to have a bunch in memory at once because prepending the array is not necessarily easy without a copy either).

how to write to beginning of file with Stream Writer?

You are almost there:

        string path = Directory.GetCurrentDirectory() + "\\test.txt";
string str;
using (StreamReader sreader = new StreamReader(path)) {
str = sreader.ReadToEnd();
}

File.Delete(path);

using (StreamWriter swriter = new StreamWriter(path, false))
{
str = "example text" + Environment.NewLine + str;
swriter.Write(str);
}

C# prepending bytes to the beginning of a file?

This is about the most succinct way I could personally think of, but doesn't avoid loops like you wanted:

int numberOfBytes = 100;
byte newByte = 0x1;

using ( var newFile = new FileStream( @"C:\newfile.dat", FileMode.CreateNew, FileAccess.Write ) )
{
for ( var i = 0; i < numberOfBytes; i++ )
{
newFile.WriteByte( newByte );
}
using ( var oldFile = new FileStream( @"C:\oldfile.dat", FileMode.Open, FileAccess.Read ) )
{
oldFile.CopyTo(newFile);
}
}

// Rename and delete files, or whatever you want to do

It could also use some error handling, but you get the idea.

how to insert row in first line of text file?

Similar to the previous answers, but this illustrates how to do what you want to do while minimizing memory consumption. There is no way around reading through the entire file you want to modify, even if you open it in a read/write stream, because you can't "insert" data.

static void WriteABC(string filename)
{
string tempfile = Path.GetTempFileName();
using (var writer = new StreamWriter(tempfile))
using (var reader = new StreamReader(filename))
{
writer.WriteLine("A,B,C");
while (!reader.EndOfStream)
writer.WriteLine(reader.ReadLine());
}
File.Copy(tempfile, filename, true);
}

How can I prepend a line to the beginning of a file?

You can't do this directly in any programming language. See some other questions on the same topic in C#, Python, NodeJs, PHP, Bash and C.

There are several solutions with different trade-offs:

  1. Copy the entire file into memory, write the data you want, and then write the rest of the file after it. If the file is large, this might be a bad solution because of the amount of memory it will use, but might be suitable for small files, because it is simple to implement.

  2. Use a buffer, the same size as the text you want to prepend. Copy chunks of the file at a time into memory and then overwrite it with the previous chunk. In this way, you can shuffle the contents of the file along, with the new text at the start. This is likely to be slower than the other approaches, but will not require a large memory allocation. It could also be the best choice when the process doesn't have permission to delete the file. But be careful: If the process is interrupted, this approach could leave the file in a corrupted state.

  3. Write the new data to a temporary file and then append the contents of the original. Then delete the original and rename the temporary file. This is a good solution because it delegates the heavy lifting to the operating system, and the original data is backed up so will not be corrupted if the process is interrupted.

From searching on Stack Overflow, the third solution seems to be the most popular answer for other languages, e.g. in Bash. This is likely to be because it is fast, safe and can often be implemented in just a few lines of code.

A quick Rust version looks something like this:

extern crate mktemp;
use mktemp::Temp;
use std::{fs, io, io::Write, fs::File, path::Path};

fn prepend_file<P: AsRef<Path>>(data: &[u8], file_path: &P) -> io::Result<()> {
// Create a temporary file
let mut tmp_path = Temp::new_file()?;
// Stop the temp file being automatically deleted when the variable
// is dropped, by releasing it.
tmp_path.release();
// Open temp file for writing
let mut tmp = File::create(&tmp_path)?;
// Open source file for reading
let mut src = File::open(&file_path)?;
// Write the data to prepend
tmp.write_all(&data)?;
// Copy the rest of the source file
io::copy(&mut src, &mut tmp)?;
fs::remove_file(&file_path)?;
fs::rename(&tmp_path, &file_path)?;
Ok(())
}

Usage:

fn main() -> io::Result<()> {
let file_path = Path::new("file.txt");
let data = "Data to add to the beginning of the file\n";
prepend_file(data.as_bytes(), &file_path)?;
Ok(())
}

Append a text file starting from a certain location in the source text file

First of all, 100 Mb is not out of the range of reading in the entire file contents into a string and then using the in memory functions to go faster. What's important is that manipulating large strings like that may be slow.

Try this:

string originalContents = File.ReadAllText("original.txt");
string insertContents = File.ReadAllText("append.txt");
int index = originalContents .IndexOf("match");
if (index == -1) return;
FileStream stream = new FileStream("original.txt", FileMode.Open);
stream.Position = index;
byte[] insertBytes = Encoding.ASCII.GetBytes(insertContents);
stream.Write(insertBytes);
byte[] endBytes = Encoding.ASCII.GetBytes(originalContents.Substring(index));
stream.Write(endBytes);

Prepending information in a text file

your first problem is you are writing to a different file than you're reading from.

your second problem is you're not reading the file in line by line, like you want.

You want:

var path = @"C:\Users\User\Desktop\New folder\DHStest.txt";

var lines = File.ReadAllLines(path);
File.WriteAllLines(path, lines.Select(x => x.PadLeft(31, '0')));

read all the lines, then write them back out with the padding.



Related Topics



Leave a reply



Submit