Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

I have been seeing some of my input files stamped with:
^@^@^@^@ #at the end
I'm using the following code to try and remove them:
open my $fh, "+<$Conf[1]" || die "ERROR: Unable to open $Conf[1]\: $!\n"; # Set it to binary mode for Win32 files binmode $fh; my $size = 4096; seek $fh, -$size, 2; # Locate the end of the file while (1) { $cur_pos = tell $fh; read $fh, $buf, $size; last if $buf =~ m/\s+/s; seek $fh, -$size*2, 1; } $buf =~ m/(\s*)$/s; $cur_pos += $-[0] || 0; truncate $fh, ++$cur_pos if $cur_pos; close $fh;
This isn't working...Can anyone tell me why?

Replies are listed 'Best First'.
Re: How do I mark the end of a file?
by BrowserUk (Patriarch) on Apr 04, 2003 at 19:20 UTC

    The '^@'s you are seeing, presumable in some text editor, are most likely actually null bytes (ascii 0). In the same way that ascii 1 is sometimes represented as '^A' and ascii 3 as '^C'. That is to say, the editor or viewer you are using to inspect the file is performing a translation of 'invisible' ascii values below ascii 32 and representing them as a '^' followed by a visible character derived by adding 0x40 to the actual ascii value. Hence the two ascii chars ^@ are used to designate the original ascii 0 value.

    Ascii 0 does not match the regex \s+, so your code is failing to remove them. If you substitute (\0+) for (\s+) in your regex, your code will probably do what you want.


    Examine what is said, not who speaks.
    1) When a distinguished but elderly scientist states that something is possible, he is almost certainly right. When he states that something is impossible, he is very probably wrong.
    2) The only way of discovering the limits of the possible is to venture a little way past them into the impossible
    3) Any sufficiently advanced technology is indistinguishable from magic.
    Arthur C. Clarke.
(jeffa) Re: How do I mark the end of a file?
by jeffa (Bishop) on Apr 04, 2003 at 19:53 UTC
    The following code uses Tie::File to remove those pesky null byte characters on the last line. I am using Fcntl in this snippet because Tie::File will create a non-existant file by default. The mode O_RDWR is used to read and write to an existing file. Read the perldoc for perlopentut for more on modes. Anyway, here's the code:
    use Fcntl 'O_RDWR'; use Tie::File; my @file; my $file = shift || die "$0 <file>"; tie @file, 'Tie::File', $file, mode => O_RDWR or die $!; my $null = chr 0; $file[-1] =~ s/\Q$null\E//g;
    Hope this helps. :)

    jeffa

    L-LL-L--L-LL-L--L-LL-L--
    -R--R-RR-R--R-RR-R--R-RR
    B--B--B--B--B--B--B--B--
    H---H---H---H---H---H---
    (the triplet paradiddle with high-hat)
    
Re: How do I mark the end of a file?
by hardburn (Abbot) on Apr 04, 2003 at 18:45 UTC

    If you're only going to be running this a few times, you could slurp the entire file into memory (such as: local $/; my $data = <FH>), use s/// to get rid of the chars at the end, and write the data back to the file.

    ----
    I wanted to explore how Perl's closures can be manipulated, and ended up creating an object system by accident.
    -- Schemer

    Note: All code is untested, unless otherwise stated