Pad a file with zeros

12

1

Your task today will be to take an existing file and append zeros to it until it reaches a certain size.

You must write a program or function which takes the name of a file in the current directory f and a number of bytes b. While maintaining the original content of f, you must write zeroes (null bytes, not ascii 0s) to the end so that its new size is b bytes.

You may assume that f only has alphanumeric ascii in its name, that you have full permissions over it, that it initially is not larger than b, but may be as large as b, and that there is infinite free disk space.

You may not assume f is nonempty, or that it does not already contain null bytes.

Other existing files should not be modified and new files should not exist after execution ends.

Test Cases

Contents of f | b  | Resulting contents of f
12345         | 10 | 1234500000
0             | 3  | 000
[empty]       | 2  | 00
[empty]       | 0  | [empty]
123           | 3  | 123

Pavel

Posted 2017-06-09T17:53:22.630

Reputation: 8 585

@totallyhuman it initially is not larget than b – Adám – 2017-06-09T17:56:16.373

Can we take the contents of the file as input and output the modified contents? – Shaggy – 2017-06-09T18:21:19.993

May we use libraries? – Adám – 2017-06-09T18:35:09.027

1@Phoenix The problem is that Dennis put the library in a far away folder (not my choice). Can I count as if it was available in the search path? – Adám – 2017-06-09T18:40:19.703

Can we assume the file will not already contain null bytes? – Dom Hastings – 2017-06-09T19:37:14.097

Answers

20

Bash + coreutils, 13

truncate -s$@

Input from the command-line - the first parameter is the file size and the second is the filename.

From man truncate:

If a FILE is shorter, it is extended and the extended part (hole) reads as zero bytes.

Try it online.

Digital Trauma

Posted 2017-06-09T17:53:22.630

Reputation: 64 644

1Can truncate extend too? – Adám – 2017-06-09T18:19:21.677

11A man who knows his mans in a manly man indeed. – Magic Octopus Urn – 2017-06-09T18:25:04.357

I wonder if it works on a FAT partition, where the truncate syscall fails. – Matteo Italia – 2017-06-10T13:59:09.907

1My implementation of the same idea would have been dd bs=1 of=$1 seek=$2<&- (which prints an error message that can be ignored). Yours is far shorter. Nice. – hvd – 2017-06-10T18:08:21.057

@hvd yep I figured dd could probably do this – Digital Trauma – 2017-06-11T00:01:47.503

4

Groovy, 54 47 43 41 bytes

{a,b->(c=new File(a))<<'\0'*(b-c.size())}

-6 thanks to manatwork's idea of removing the loop; that was my original idea, don't know why I thought it wouldn't work and opted for a loop... It definitely works, just tested it.

Ungolfed:

{
    a,b->                    // Two inputs: a is the File name, b is the desired size.
    File c = new File(a)     // Make and store the file.
    c << '\0'*(b-c.size())   // Append the difference between b and c.size() in nullbytes.
}
                             // Usually a close would be required, but, in Groovy,
                             // because private data isn't so protected, if a File
                             // Object goes out of scope, the attached Stream is 
                             // automatically flushed to disk.

Magic Octopus Urn

Posted 2017-06-09T17:53:22.630

Reputation: 19 422

1Wouldn't be shorter loopless? {a,b->c=new File(a);c<<('\0'*(b-c.size()))} – manatwork – 2017-06-09T18:18:18.143

@manatwork yeah! And it can actually be even better than that. – Magic Octopus Urn – 2017-06-09T18:19:36.640

@manatwork nevermind, same bytecount for (c=new File(a)) due to required parenthesis. – Magic Octopus Urn – 2017-06-09T18:23:37.717

1No idea why I put parenthesis around the entire value to append. Not needed. – manatwork – 2017-06-09T18:25:52.623

@manatwork Groovy is pretty temperamental about the parenthesis, can't blame you haha. – Magic Octopus Urn – 2017-06-09T18:30:57.890

3

APL (Dyalog), 33 17 bytes

⎕⎕NRESIZE⍞⎕NTIE¯1

Try it online!

Adám

Posted 2017-06-09T17:53:22.630

Reputation: 37 779

What's ∇Extend? – Pavel – 2017-06-09T18:08:08.797

@Phoenix Just the name of the program so it can be called. Here is a version without naming the program.

– Adám – 2017-06-09T18:16:14.910

3

Python 2, 59 57 54 bytes

-5 bytes thanks to chepner

def g(n,b):f=open(n,'a');f.write('\0'*b);f.truncate(b)

Rod

Posted 2017-06-09T17:53:22.630

Reputation: 17 588

1@totallyhuman \x00 is a null byte. – Pavel – 2017-06-09T18:19:24.060

1@totallyhuman no, it is more like a flag thing (to disallow interactino with closed files) – Rod – 2017-06-09T18:19:52.360

1@Rod I love interactino! Best child-friendly interactive game ever – caird coinheringaahing – 2017-06-09T18:25:59.893

You can use \0 in place of \x00. – chepner – 2017-06-09T21:50:48.560

You can save another three bytes by overextending, then truncating: def g(n,b):f=open(n,'a');f.write('\0'*b);f.truncate(b). – chepner – 2017-06-09T22:05:02.133

Can you do f=open(n,'a').write('\0'*b)? – Comrade SparklePony – 2017-06-10T17:03:56.007

@ComradeSparklePony yeah, but it would return None – Rod – 2017-06-11T00:05:50.723

3

PHP, 66 bytes

for($p=fopen($f=$argv[1],a);filesize($f)<$argv[2];)fputs($p,"\0");

Takes input from command line arguments; run with -nr.


These 55 bytes might, but most probably will not, work:

fseek($p=fopen($argv[1],"w+"),$argv[2]);fputs($p,"\0");

Titus

Posted 2017-06-09T17:53:22.630

Reputation: 13 814

2

Java (Oracle JRE), 55 bytes

f->b->new java.io.RandomAccessFile(f,"rw").setLength(b)

The spec of setLength(int) says that the appended bytes are undefined, but practically the Oracle JRE appends only the 0 byte (that's why I specified it).

The resource is automatically closed by the JVM so we don't need to do it ourself.

Test

public class Pcg125661 {
  interface F {
    B f(String f);
  }
  interface B {
    void b(int b) throws java.io.IOException;
  }
  public static void main(String[] args) throws java.io.IOException {
    F a = f->b->new java.io.RandomAccessFile(f,"rw").setLength(b);
    a.f("a").b(100);
  }
}

Olivier Grégoire

Posted 2017-06-09T17:53:22.630

Reputation: 10 647

1

AHK, 48 bytes

FileGetSize,s,%1%
2-=s
Loop,%2%
FileAppend,0,%1%

1 and 2 are the first two parameters in an AHK script.
FileGetSize works in bytes by default.
It's not exciting, but it's simple: Get the size, subtract it from the desired size, and add that many zeroes.

Engineer Toast

Posted 2017-06-09T17:53:22.630

Reputation: 5 769

1

Perl 6, 40 bytes

{$_=$^a.IO;.open(:a).put("\0"x($^b-.s))}

$^a and $^b are the parameters to the function--the file name and the length, respectively.

Sean

Posted 2017-06-09T17:53:22.630

Reputation: 4 136

1

Python 2, 68 bytes

def g(f,b):
 with open(f,'r+')as c:c.write('\x00'*(b-len(c.read())))

Try it online! (When printing the file's content, the code replaces null bytes with ASCII 0's for visibility.)

totallyhuman

Posted 2017-06-09T17:53:22.630

Reputation: 15 378

1I think this writes ASCII zeroes and not null bytes – Pavel – 2017-06-09T18:18:53.303

Ah... the word zeroes was misleading... – totallyhuman – 2017-06-09T18:20:08.867

Well, it does say in large letters in the challenge itself. – Pavel – 2017-06-09T18:20:57.870

Can you use a literal \x00 in the string (not an escape sequence)? – CalculatorFeline – 2017-06-09T19:09:27.637

2You can't use a literal null byte, but \0 is shorter. – xnor – 2017-06-10T06:26:07.513

1

PowerShell, 69 bytes

param($f,$s)@(gc $f -en by)+,[byte]0*($s-(gi $f).length)|sc $f -en by
#     ^ filename
#        ^desired size
#                 ^ get content as byte stream
#           ^force it to an array even if there's 0 or 1 byte
#                          ^append a byte array of nulls..
#                                       ^..desired size - file size
#                            write to file with -encoding byte ^

$f for the file, $s for the destination size, save as .ps1 and run

.\Add-NullBytesToFile.ps1 .\test.txt 10

It's a shell, so there should be a really small loop adding 1 byte with >> output redirection and append, right? Well, no, because >> only outputs UCS2-LE multibyte encoding so there's no way to add a single byte to a file with it .. unless you're using PSv5.1 and you can change that but that makes it too long to be competitive:

$PSDefaultParameterValues['Out-File:Encoding']='utf8';while((gi $f).length-lt$c){[byte]0>>$f}

Maybe there's a .Net Framework approach? There should be, but I can't make it actually write any bytes, or error. But it's longer anyway:

param($f,$s)[io.file]::WriteAllBytes($f,[byte[]](,0)*($c-(gi $f).length), $True)

TessellatingHeckler

Posted 2017-06-09T17:53:22.630

Reputation: 2 412

1

Mathematica 50 Bytes

Import/Export

Export[#,Import[#,c="Byte"]~Join~Table[0,{#2}],c]&

Usage

%["test1", 5]

Kelly Lowder

Posted 2017-06-09T17:53:22.630

Reputation: 3 225

1

C, 56 bytes

fseek(f,0,2);int i;for(;ftell(f)<b;)putc(0,f);fclose(f);

The program finds the file's size, and how many bytes to append. The file then adds fs - b extra bytes to the end.

Garhoogin

Posted 2017-06-09T17:53:22.630

Reputation: 29

1Welcom to PPCG! This is a [tag:code-golf] challenge, so your objective is to make your program as small as possible. You should start by removing unnecesary whitespace. – Pavel – 2017-06-10T05:39:05.967

4In addition, your program seems to assume that the inputs are already stored in the values f and b, which isn't allowed. You must include i/o into your program, which can be from ARGV, console input, or arguments to a function. – Pavel – 2017-06-10T05:41:03.307

Thank you, I thought that the variables were assumed to be set already. My bad. – Garhoogin – 2017-06-10T06:06:41.350

1

q, 29 bytes

Function which takes file name in format :/foo/bar.baz and length as an integer.

{hopen[x](0|y-hcount x)#0x00}

Example:

{hopen[x](0|y-hcount x)#0x00}[`:test.txt;100]

skeevey

Posted 2017-06-09T17:53:22.630

Reputation: 4 139

1

C#, 90 bytes

using System.IO;s=>n=>File.AppendAllText(s,new string('\0',(int)new FileInfo(s).Length-n))

TheLethalCoder

Posted 2017-06-09T17:53:22.630

Reputation: 6 930