views:

67

answers:

2

I'm running ActivePerl 5.8.8 on WinXP. I'd like to output an XML file as UTF-8 with UNIX line endings.

I've looked at the perldoc for binmode, but am unsure of the exact syntax (if I'm not barking up the wrong tree). The following doesn't do it (forgive my Perl - it's a learning process!):

sub SaveFile
{
    my($FileName, $Contents) = @_;

    my $File = "SAVE";
    unless( open($File, ">:utf-8 :unix", $FileName) )
    {
        die("Cannot open $FileName");
    }
    print $File @$Contents;

    close($File);
}
+1  A: 

I think you need something like this.

use strict;
use warnings;

sub save_file {
    my ($file_name, $content) = @_;
    open my $fh, ">", $file_name or die $!;
    binmode $fh, ':utf8 :unix';
    print $fh @$content;
    close $fh;
}

# For example.
save_file('foo.txt', [ map "$_\n", qw(foo bar baz)]);

For typical use of the 3-argument form of open, you want the file handle variable to be undefined before calling open. See the docs for details.

FM
This outputs UTF-8 but not UNIX line endings in my XP environment.
Umber Ferrule
@Umber Ferrule Not sure what the problem is. It works for me on XP, including Unix newlines. Here's a dump of the file: `666f 6f0a 6261 720a 6261 7a0a`.
FM
+2  A: 

If $Contents does not already have \n characters, print will not add them for you. You must do that yourself.

There's a couple other things that might be problematic; here's how to fix them and why.

IO Layers

To enable utf8 output, you need to use :utf8, not :utf-8. In addition, you should not have spaces in your IO layers, so it should look like `">:utf8:unix".

Open

To open a file, you can declare the 'my $fh' in line; no need to initialize it to a string to start. It's okay, this is good practice. In addition, using or is the preferred way to catch open errors.

Changed around, your code looks like this now:

sub SaveFile
{
    my($FileName, $Contents) = @_;

    open my $File, ">:utf8:unix", $FileName
        or die "Cannot open $FileName";
    print $File map { "$_\n" } @$Contents;

    close($File);
}

map lets you transform your input array by adding the newlines to each line before it prints them, and does it in order.

Good luck!

Robert P
That works great - thanks very much for your tips too!
Umber Ferrule