2017-04-08 206 views
-1

設計方法,我有一個格式文件具有以下內容爲EBCDIC轉換

FIELD NO.,FIELD NAME,STARTING POSITION,ENDING POSITION,LENGTH,INDICATOR 
1,SEQ_NO,1,11,11,N 
2,CTR_REC_ID,12,14,3,N 
3,CTR_SEQ_AMT,15,23,9,A 
4,CTR_CONTRACT_NO,24,46,23,N 
5,CTR_CONTRACT_AMT,47,59,13,A 
6,CTR_TRACK_NO,60,62,3,N 

該文件提供了有關每個字段的起始位置,結束位置和長度的詳細信息。

我的腳本讀取格式文件並將內容存儲到數組中。然後逐行讀取源文件,當格式文件中的指示符爲時A將EBCDIC字符轉換爲合適的ASCII字符。

下面是一個示例源文件,其索引顯示了字符位置和格式文件中列出的字段。它不是數據文件的一部分。

  1   2   3   4   5   6   7 
123456789
[   ][ ][  ][      ][   ][ ] 
  5|CTR00002173{09C00000000001   000000000201AE00  
     22|CTR00002243A52C00000000007   000000002358JF00 
     24|CTR00008456J52C00000000008   000000002465{F00 

作爲每格式文件,所述第一線的CTR_SEQ_AMT值爲00002173{{必須轉換爲0並用空格替換前導零並將其作爲十進制值(十進制(9,2))。

最終輸出將是這樣的:

 5|CTR 217.3009C00000000001     20.11E00 
    22|CTR 224.3152C00000000007    -235.85F00 
    24|CTR -845.6552C00000000008     246.50F00 

{ - > 0,A - > 1,J - >圖5(十進制值轉換爲負)。

我已經得到了上面的輸出使用Perl,但我的腳本的性能是不好的。

我的源文件可以有一百萬條記錄。根據我的腳本,我有2個循環:一個讀取格式文件並將數據存儲到數組中,另一個讀取逐行讀取源文件並進行轉換。所以如果一個格式文件有10個字段需要轉換,我的代碼會循環10次。

代替具有兩個環的,我可以具有單個環,用於讀取的格式文件,並且當一個場的指示器是A中的所有行同時對於特定的字段執行以下操作:

  • 將前導零替換爲空白
  • 將EBCDIC字符轉換爲ASCII字符
  • 將其作爲十進制值。

目前我的代碼有以下行來執行上述3個步驟。下面這行代碼從源文件開始。

$f_cnt = $start_pos - 1; 
$dec_cnt = $array_length[$cnt] - 2; 
$field = substr("$line", $end_pos -1, 1); 

if ($field eq '{') { 
    print "replacing { \n"; 
    $x = substr($line, $f_cnt, $dec_cnt); 
    $x =~ s/^(0*)/' ' x length($1)/e; 
    substr($line, $f_cnt, $dec_cnt, "$x."); 
    substr($line, $end_pos, 1, "0") ; 
} 
+1

我覺得這說明很難理解。源文件開頭的5,22,24是什麼?源文件中的指標在哪裏 - 它似乎在格式文件中? –

+0

不好意思。混淆了。在源文件數據上面加了管道知道每個字段的位置。管道不是源文件數據的一部分。現在,如果我們檢查格式文件,第一個字段是SEQ_NO,它有11個字符,從1開始到源文件中的第11位.INDICATOR格式爲file.We需要讀取格式文件以瞭解源文件中的每個字段詳細信息。格式文件中CTR_CONTRACT_AMT字段的指示符是A,表示需要轉換。我希望此說明清楚您的疑問@ Mark Setchell – user1768029

+1

它仍然沒有道理!如果你有10個字段要轉換,你只需在開始時讀**一次**格式文件,然後當你讀取數據文件的每一行時,你進行全部10次轉換並寫入相應的輸出行。您不必在內存中存儲多行,因爲您從不需要任何其他行來處理當前行,因此它不會成爲內存問題。 –

回答

0

一些優化後,我有:

my %ebcdic_fields; 

while (my $line = <DATA>) { 
    my (undef, undef, $start, undef, $length, $indicator) = split /,/, $line; 
    next if $indicator !~ m/^A/; 
    $ebcdic_fields{$start-1} = $length - 2; 
} 

while (my $line = <>) { 
    while (my ($start, $length) = each %ebcdic_fields) { 
     my $fpos = $start + $length + 1; 
     my $before = substr ($line, $start, $length); 
     my $format = substr ($line, $fpos, 1); 
     my $trimed_before = $before + 0; # keep at least one 0 before the dot 
     if ($format ge 'J' and $format ne '{') { 
      substr ($line, $fpos, 1) =~ tr/}JKLMNOPQR//; 
      substr ($line, $start, $length) = ' ' x ($length - length($trimed_before) - 2) . '-' . $trimed_before . '.'; 
     } else { 
      substr ($line, $fpos, 1) =~ tr/{ABCDEFGHI//; 
      substr ($line, $start, $length) = ' ' x ($length - length($trimed_before) - 1) . $trimed_before . '.'; 
     } 
    } 
    print $line; 
} 
__DATA__ 
1,SEQ_NO,1,11,11,N 
2,CTR_REC_ID,12,14,3,N 
3,CTR_SEQ_AMT,15,23,9,A 
4,CTR_CONTRACT_NO,24,46,23,N 
5,CTR_CONTRACT_AMT,47,59,13,A 
6,CTR_TRACK_NO,60,62,3,N 

可悲的是,我已經實現了最快的是這樣的:

my %ebcdic_fields; 

while (my $line = <DATA>) { 
    my (undef, undef, $start, undef, $length, $indicator) = split /,/, $line; 
    next if $indicator !~ m/^A/; 
    $ebcdic_fields{$start-1} = $length - 2; 
} 

while (my $line = <>) { 
    while (my ($start, $length) = each %ebcdic_fields) { 
     my $format = substr ($line, $start + $length + 1, 1); 
     my $trimed_before = (substr ($line, $start, $length) + 0); # keep at least one 0 before the dot 
     if ($format eq '{') { 
      substr ($line, $start, $length+2) = ' ' x ($length - length($trimed_before) - 1) . $trimed_before . '.' . substr ($line, $start + $length, 1) . '0'; 
     } elsif ($format eq 'A') { 
      substr ($line, $start, $length+2) = ' ' x ($length - length($trimed_before) - 1) . $trimed_before . '.' . substr ($line, $start + $length, 1) . '1'; 
     } elsif ($format eq 'B') { 
      substr ($line, $start, $length+2) = ' ' x ($length - length($trimed_before) - 1) . $trimed_before . '.' . substr ($line, $start + $length, 1) . '2'; 
     } elsif ($format eq 'C') { 
      substr ($line, $start, $length+2) = ' ' x ($length - length($trimed_before) - 1) . $trimed_before . '.' . substr ($line, $start + $length, 1) . '3'; 
     } elsif ($format eq 'D') { 
      substr ($line, $start, $length+2) = ' ' x ($length - length($trimed_before) - 1) . $trimed_before . '.' . substr ($line, $start + $length, 1) . '4'; 
     } elsif ($format eq 'E') { 
      substr ($line, $start, $length+2) = ' ' x ($length - length($trimed_before) - 1) . $trimed_before . '.' . substr ($line, $start + $length, 1) . '5'; 
     } elsif ($format eq 'F') { 
      substr ($line, $start, $length+2) = ' ' x ($length - length($trimed_before) - 1) . $trimed_before . '.' . substr ($line, $start + $length, 1) . '6'; 
     } elsif ($format eq 'G') { 
      substr ($line, $start, $length+2) = ' ' x ($length - length($trimed_before) - 1) . $trimed_before . '.' . substr ($line, $start + $length, 1) . '7'; 
     } elsif ($format eq 'H') { 
      substr ($line, $start, $length+2) = ' ' x ($length - length($trimed_before) - 1) . $trimed_before . '.' . substr ($line, $start + $length, 1) . '8'; 
     } elsif ($format eq 'I') { 
      substr ($line, $start, $length+2) = ' ' x ($length - length($trimed_before) - 1) . $trimed_before . '.' . substr ($line, $start + $length, 1) . '9'; 
     } elsif ($format eq '}') { 
      substr ($line, $start, $length+2) = ' ' x ($length - length($trimed_before) - 2) . '-' . $trimed_before . '.' . substr ($line, $start + $length, 1) . '0'; 
     } elsif ($format eq 'J') { 
      substr ($line, $start, $length+2) = ' ' x ($length - length($trimed_before) - 2) . '-' . $trimed_before . '.' . substr ($line, $start + $length, 1) . '1'; 
     } elsif ($format eq 'K') { 
      substr ($line, $start, $length+2) = ' ' x ($length - length($trimed_before) - 2) . '-' . $trimed_before . '.' . substr ($line, $start + $length, 1) . '2'; 
     } elsif ($format eq 'L') { 
      substr ($line, $start, $length+2) = ' ' x ($length - length($trimed_before) - 2) . '-' . $trimed_before . '.' . substr ($line, $start + $length, 1) . '3'; 
     } elsif ($format eq 'M') { 
      substr ($line, $start, $length+2) = ' ' x ($length - length($trimed_before) - 2) . '-' . $trimed_before . '.' . substr ($line, $start + $length, 1) . '4'; 
     } elsif ($format eq 'N') { 
      substr ($line, $start, $length+2) = ' ' x ($length - length($trimed_before) - 2) . '-' . $trimed_before . '.' . substr ($line, $start + $length, 1) . '5'; 
     } elsif ($format eq 'O') { 
      substr ($line, $start, $length+2) = ' ' x ($length - length($trimed_before) - 2) . '-' . $trimed_before . '.' . substr ($line, $start + $length, 1) . '6'; 
     } elsif ($format eq 'P') { 
      substr ($line, $start, $length+2) = ' ' x ($length - length($trimed_before) - 2) . '-' . $trimed_before . '.' . substr ($line, $start + $length, 1) . '7'; 
     } elsif ($format eq 'Q') { 
      substr ($line, $start, $length+2) = ' ' x ($length - length($trimed_before) - 2) . '-' . $trimed_before . '.' . substr ($line, $start + $length, 1) . '8'; 
     } elsif ($format eq 'R') { 
      substr ($line, $start, $length+2) = ' ' x ($length - length($trimed_before) - 2) . '-' . $trimed_before . '.' . substr ($line, $start + $length, 1) . '9'; 
     } 
    } 
    print $line; 
}