ファイルソートのサンプル
ファイルソートのサンプルを以下に示します。
$rtndata = &FileSort( 'sort.dat', ',', 1000, 1, 0 ) ;
・
・
・
・
#-----------------------------------------------------------------------#
# ファイルソート
# パラメータ: $fn …ファイル名
# $sep …レコード内の項目の区切り文字
# $blocksize …1ブロック内のレコード数
# @keytbl …ソートキーテーブル(カンマ区切りのキー位置/0〜)
# リターン : …1:正常
# 0:エラー
# 出力用変数: $FS_Sep …レコード内の項目の区切り文字(ソートサブルーチンへの受け渡し用)
# @FS_KeyTbl …キーテーブル(ソートサブルーチンへの受け渡し用)
#-----------------------------------------------------------------------#
sub FileSort
{
local( $fn, $sep, $blocksize, @keytbl ) = @_ ;
local( $i, $tmpfn1, $tmpfn2, @tmpbuf, @seektbl, @cnttbl, $tmprec, @tmptbl ) ;
local( @tmp0, @tmp1, $cmp01 ) ;
local( $rtn ) = 0 ;
$FS_Sep = $sep ;
@FS_KeyTbl = @keytbl ;
$tmpfn1 = $fn . '.tmp1' ;
$tmpfn2 = $fn . '.tmp2' ;
@seektbl = () ;
@cnttbl = () ;
while (1)
{
if ( ! open( FSIN , $fn ) ) { last ; }
if ( ! open( FSOUT1, ">$tmpfn1" ) ) { last ; }
if ( ! open( FSOUT2, ">$tmpfn2" ) ) { last ; }
while (1)
{
if ( eof(FSIN) ) { last ; }
push( @seektbl, tell( FSOUT1 ) ) ;
@tmpbuf = () ;
for ( $i=0; $i<$blocksize; $i++ )
{
$tmpbuf[$i] = ;
if ( eof(FSIN) ) { last ; }
}
@tmpbuf = sort FSortSub @tmpbuf ;
print FSOUT1 @tmpbuf ;
push( @cnttbl, $#tmpbuf + 1 ) ;
}
close( FSIN ) ;
if ( $#cnttbl == 0 )
{
print FSOUT2 @tmpbuf ;
}
else
{
if ( ! open( FSOUT1, "$tmpfn1" ) ) { last ; }
@tmptbl = () ;
@tmpbuf = () ;
for ( $i=0; $i<=$#cnttbl; $i++ )
{
if ( $cnttbl[$i] > 0 )
{
seek( FSOUT1, $seektbl[$i], 0 ) ;
$tmprec = ;
$tmprec =~ s/\n/$sep$i\n/ ;
push( @tmptbl, $tmprec ) ;
$seektbl[$i] = tell( FSOUT1 ) ;
$cnttbl[$i] -- ;
}
}
@tmptbl = sort FSortSub @tmptbl ;
while ( $#tmptbl >= 0 )
{
$tmprec = shift( @tmptbl ) ;
$tmprec =~ s/$sep(\d+)\n/\n/ ;
$i = $1 ;
push( @tmpbuf, $tmprec ) ;
if ( $#tmpbuf + 1 >= $blocksize )
{
print FSOUT2 @tmpbuf ;
@tmpbuf = () ;
}
if ( $cnttbl[$i] > 0 )
{
seek( FSOUT1, $seektbl[$i], 0 ) ;
$tmprec = ;
$tmprec =~ s/\n/$sep$i\n/ ;
unshift( @tmptbl, $tmprec ) ;
$seektbl[$i] = tell( FSOUT1 ) ;
$cnttbl[$i] -- ;
}
if ( $#tmptbl >= 1 )
{
@tmp0 = split( /$sep/, $tmptbl[0] ) ;
@tmp1 = split( /$sep/, $tmptbl[1] ) ;
for ( $i=0; $i<=$#FS_KeyTbl; $i++ )
{
$cmp01 = $tmp0[ $keytbl[$i] ] cmp $tmp1[ $keytbl[$i] ] ;
if ( $cmp01 != 0 ) { last; }
}
if ( $cmp01 > 0 )
{
@tmptbl = sort FSortSub @tmptbl ;
}
}
}
close( FSOUT1 ) ;
if ( $#tmpbuf >= 0 ) { print FSOUT2 @tmpbuf ; }
}
close( FSOUT2 ) ;
unlink( $fn ) ;
rename( $tmpfn2, $fn ) ;
$rtn = 1 ;
last ;
}
close( FSIN ) ;
close( FSOUT1 ) ;
close( FSOUT2 ) ;
unlink( $tmpfn1 ) ;
unlink( $tmpfn2 ) ;
$rtn ;
}
#-----------------------------------------------------------------------#
# ファイルソート用ソートサブルーチン
# パラメータ: $a,$b …比較レコード
# 入力用変数: $FS_Sep …レコード内の項目の区切り文字(ソートサブルーチンへの受け渡し用)
# @FS_KeyTbl …キーテーブル(ソートサブルーチンへの受け渡し用)
# リターン : … 0: $a=$b
# 1: $a>$b
# -1: $a<$b
#-----------------------------------------------------------------------#
sub FSortSub
{
local( @tmpA ) = split( /$FS_Sep/, $a ) ;
local( @tmpB ) = split( /$FS_Sep/, $b ) ;
local( $i ) ;
local( $rtn ) = 0 ;
for ( $i=0; $i<=$#FS_KeyTbl; $i++ )
{
$rtn = $tmpA[ $FS_KeyTbl[$i] ] cmp $tmpB[ $FS_KeyTbl[$i] ] ;
if ( $rtn != 0 ) { last; }
}
$rtn ;
}