How to Prepend File to Beginning

How do I prepend file to beginning?

The file_get_contents solution is inefficient for large files. This solution may take longer, depending on the amount of data that needs to be prepended (more is actually better), but it won't eat up memory.

<?php

$cache_new = "Prepend this"; // this gets prepended
$file = "file.dat"; // the file to which $cache_new gets prepended

$handle = fopen($file, "r+");
$len = strlen($cache_new);
$final_len = filesize($file) + $len;
$cache_old = fread($handle, $len);
rewind($handle);
$i = 1;
while (ftell($handle) < $final_len) {
fwrite($handle, $cache_new);
$cache_new = $cache_old;
$cache_old = fread($handle, $len);
fseek($handle, $i * $len);
$i++;
}
?>

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(())
}

Unix command to prepend text to a file

sed -i.old '1s;^;to be prepended;' inFile
  • -i writes the change in place and take a backup if any extension is given. (In this case, .old)
  • 1s;^;to be prepended; substitutes the beginning of the first line by the given replacement string, using ; as a command delimiter.

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

a one-line awk command should do the trick also:

awk '{print "prefix" $0}' 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 insert a text at the beginning of a file?

sed can operate on an address:

$ sed -i '1s/^/<added text> /' file

What is this magical 1s you see on every answer here? Line addressing!.

Want to add <added text> on the first 10 lines?

$ sed -i '1,10s/^/<added text> /' file

Or you can use Command Grouping:

$ { echo -n '<added text> '; cat file; } >file.new
$ mv file{.new,}

Prepend line to beginning of a file

In modes 'a' or 'a+', any writing is done at the end of the file, even if at the current moment when the write() function is triggered the file's pointer is not at the end of the file: the pointer is moved to the end of file before any writing. You can do what you want in two manners.

1st way, can be used if there are no issues to load the file into memory:

def line_prepender(filename, line):
with open(filename, 'r+') as f:
content = f.read()
f.seek(0, 0)
f.write(line.rstrip('\r\n') + '\n' + content)

2nd way:

def line_pre_adder(filename, line_to_prepend):
f = fileinput.input(filename, inplace=1)
for xline in f:
if f.isfirstline():
print line_to_prepend.rstrip('\r\n') + '\n' + xline,
else:
print xline,

I don't know how this method works under the hood and if it can be employed on big big file. The argument 1 passed to input is what allows to rewrite a line in place; the following lines must be moved forwards or backwards in order that the inplace operation takes place, but I don't know the mechanism

Prepend ! to the beginning of the first line of a file

You sent an array to Set-Content with $b,$a. Each array item will be given its own line as you have seen. It would displayed the same way on the prompt if executed.

As long as the file is not too big read it in as one string and add the character in.

$path = 'hh_Regulars3.csv'
"!" + (Get-Content $path -Raw) | Set-Content $path

If you only have PowerShell 2.0 then Out-String would work in place of -Raw

"!" + (Get-Content $path | Out-String) | Set-Content $path

The brackets are important to be sure the file is read in before it goes to through the pipeline. It allows us to both read and write on the same pipeline.

If the file is larger look into using StreamReaders and StreamWriters. This would also have to be used if the trailing new line, created by the Add-Content and Set-Content, is not warranted.



Related Topics



Leave a reply



Submit