Perl:CSVファイルの読み込みと書き込み

 CSV関連のデータを取り扱う事になったのでCSVファイルのロードとセーブについて調べてみました。


※プログラム初心者のため、このページのプログラムソースは正常に動作しない事がありますご注意下さい。
(あっちこっちのサイトの情報を寄せ集めてるので思わぬ不具合があるかも)

 Perl中でCSV形式のデータをどんな感じで扱うのがベストかはわかりませんが、行単位で配列変数に保存する方法を採用しています。

使い方
・配列変数「@csv_line」に値を保存するので、グローバル変数またはlocal(@csv_line):でローカス変数の宣言をして下さい。
・読み込みは「&csv_load(ファイル名);」でファイルを@csv_lineに改行区切りで保存されます。
・書き込みは「&csv_save(ファイル名);」で@csv_lineの値がファイルに保存されます。

注意点
・前述のように 配列変数 @csv_line に値を格納しますので、スコープに注意。
・使用できるCSVファイルはカンマ区切り形式(ダブルクオーテーションなどの制御やヘッダ行の処理は行っていません。
・読み込み時のCSVファイルの改行コードは何でも(CRLF/CR/LF)可、最後に改行があっても無くても可能です。
・書き込み時のCSVファイルは改行はUNIX系OSの改行コード\n(CR)に統一、最後に改行あり。となります
・ファイルロックはしていませんので別途必要
・エラートラップは無いのでファイル名の指定など注意
・文字コードの処理はしていません。CGIの文字コードに依存します。

変更点
2013/09/01 「$r=~s/\x0D\x0A|\x0D/\x0A/g;」の処理が遅いので分割
2014/11/30 foreach () {$r.=$__;}だと大きいファイルを使った時、メモリ不足になる恐れがあるため while や for に変更

備忘録
・ファイルロックしてないのは「ロック>ロード>処理>セーブ>アンロック」が理想的なため、個々にロックを行うとマルチタスクの場合別のロードとセーブの間に別のプロセスからデータが書き換えられ、上書きや二重になったりするため。
・ファイル保存は書き込み中にフリーズする可能性があるため、別名で保存した後に正常に保存できたか確認してから本来のファイルと差し替えるのが望ましい。(もっと安全を考えるならバックアップしたり一定期間保持するような処理が必要)
・ダブルクオーテーションを意識していないのでデータとして区切り文字の「,」は使えません。

プログラム例

#-------------------------------------------------
# CSVファイルを専用配列変数(@csv_line)に読み込む。
#-------------------------------------------------
sub csv_load{	#0=filename
	my($r);

	#ファイルを全て読み込む
	open(IN,"< $_[0]");
	while () {$r.=$_}
	close(IN);

	#改行コードを整理(最後の改行は除去)し、改行コード区切りで配列に保存
	$r=~s/\x0D\x0A/\x0A/g;
	$r=~s/\x0D/\x0A/g;
	chomp($r);
	@csv_line=split(/\x0A/,$r);
}
#-------------------------------------------------
# CSVファイルを保存する:専用配列変数(@csv_line)から読み込む
#-------------------------------------------------
sub csv_save{	#0=filename
	my($i,$r);

	#改行コードを付加し $r に格納
	for ($i = 0; $i <= $#csv_line; $i++){
		$r.="$csv_line[$i]\n";
	}

	#ファイルに書き込む
	open(OUT,"> $_[0]");
	print OUT $r;
	close(OUT);
}
#-------------------------------------------------

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA