【问题标题】:Save a row to csv format将一行保存为 csv 格式
【发布时间】:2017-08-11 07:07:48
【问题描述】:

我有一组来自数据库的行,我想将它们保存到 csv 文件中。
考虑到数据是没有任何奇怪字符的 ascii 字符,以下就足够了吗?

my $csv_row = join( ', ', @$row );  
# save csv_row to file    

我担心的是,这是否会创建任何工具都可以接受为 CSV 的行,例如不关心引用等。

更新:
这有什么区别吗?

my $csv = Text::CSV->new ( { binary => 1, eol    => "\n"} );
my $header = join (',', qw( COL_NAME1 COL_NAME2 COL_NAME3 COL_NAME4 ) );
$csv->print( $fh, [$header] );                                                                             
foreach my $row ( @data ) {  
  $csv->print($fh,  $row );    
}    

这给了我第一行:

" COL_NAME1,COL_NAME2,COL_NAME3,COL_NAME4"   

请注意双引号,其余行没有任何引号。
与我的普通join 有什么区别?我还需要binary 设置吗?

【问题讨论】:

  • @zdim:是的,实际上我想知道如果这种方法有效,我为什么要使用模块。可能是我应该有引号或我正在取消的东西,以确保它可以被任何程序接受为 CSV
  • @zdim:你的意思是使用 JSON 而不是 CSV?关于JSON_XS的建议我没看懂
  • 呃,非常抱歉……偏离了另一个评论。这是Text::CSV。我正在删除该评论。这正是一个可靠的模块有帮助的一件事(我认为你的格式很好,但我不确定)。
  • 至少,您在第一列的开头有一个额外的空间。另外,你怎么能确定永远不会有任何字符,如 " 或换行符或逗号?使用现有模块可能是更好的选择。另请注意,CSV 可能是最不标准的标准:并非所有应用程序都同意关于其格式,包括字段分隔符、行分隔符、编码、转义……如果可能,请选择另一种格式。
  • @jcaron:比如什么? JSON 使用起来很痛苦,例如在 Google 表格或 Excel 中。

标签: perl csv


【解决方案1】:

最安全的方法应该是使用逗号分隔符写入干净的记录。越简单越好,特别是在现实生活中有如此多变化的格式。如果需要,请对每个字段进行双引号。

使用该模块的真正优势在于读取“真实”数据。但是将它用于写作也是非常有意义的,对于 CSV 的统一方法。此外,选项可以以清晰的方式设置,并且该模块可以消除数据中的一些故障。

Text::CSV 文档告诉我们有关 binary 选项的信息

重要提示:默认行为是只接受范围从0x20(空格)到0x7E(波浪号)的ASCII 字符。这意味着字段不能包含换行符。如果您的数据包含嵌入在字段中的换行符、0x7E 上方的字符(波浪号)或二进制数据,您必须在对new 的调用中设置binary => 1 .为了涵盖最广泛的解析选项,您总是希望设置二进制。

我会说使用它。由于您编写了一个文件,这可能是选项,以及eol(或使用say 方法)。但是请浏览许多有用的选项并查看他们的defaults

至于您的标题,print 方法需要一个数组引用,其中每个字段都是一个元素,而不是带有逗号分隔字段的单个字符串。所以说是错的

my $header = join (',', qw(COL_NAME1 COL_NAME2 COL_NAME3 COL_NAME4));  # WRONG
$csv->print( $fh, [$header] );

因为$header 是一个单独的字符串,然后它成为[ ... ] 创建的(匿名)数组引用的唯一元素。因此它将这个字符串打印为行中的第一个字段,并且由于它在其中检测到分隔符, 本身,它也用双引号引起来。相反,你应该有

$csv->print($fh, [COL_NAME1 COL_NAME2 COL_NAME3 COL_NAME4]);

或者更好地将列名分配给@header,然后执行$csv->print($fh, \@header)

这也是为什么使用该模块进行写入的一个示例 - 如果逗号滑入数组的元素中,应该是单个字段,它可以通过双引号正确处理。


一个完整的例子

use warnings;
use strict;
use Text::CSV_XS;

my $csv = Text::CSV->new ( { binary => 1, eol => "\n" } ) 
    or die "Cannot use CSV: " . Text::CSV->error_diag();

my $file = 'output.csv';
open my $fh_out , '>', 'output.csv' or die "Can't open $file for writing: $!";

my @headers = qw( COL_NAME1 COL_NAME2 COL_NAME3 COL_NAME4 );
my @data = 1..4;

$csv->print($fh_out, \@headers);
$csv->print($fh_out, \@data);

close $fh_out;

什么产生了文件output.csv

COL_NAME1,COL_NAME2,COL_NAME3,COL_NAME4 1,2,3,4

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-18
    • 2018-11-26
    相关资源
    最近更新 更多