我正在编写一个应该能够以BankOne格式导出交易记录的模块。
Here is the specification of the format
字段放在行的特定范围内,记录由新行分隔。需要添加大量空格以确保字段在行中的特定点开始和结束。
我为此在php中编写了一个函数。它将字段作为参数,并应返回格式正确的记录。
function record4($checknum='', $nameid='', $purpose='', $pledge='', $payment='',
$frequency='', $title='', $fname='', $lname='', $suffix='',
$address='', $postalcode='', $city='', $state='', $greeting='')
{
$fields = array(
'checknum' => array('length' => 8, 'start' => 37),
'nameid' => array('length' => 7, 'start' => 45),
'purpose' => array('length' => 5, 'start' => 52),
'pledge' => array('length' => 10, 'start' => 57),
'payment' => array('length' => 10, 'start' => 67),
'frequency' => array('length' => 1, 'start' => 77),
'title' => array('length' => 20, 'start' => 78),
'fname' => array('length' => 40, 'start' => 98),
'lname' => array('length' => 40, 'start' => 138),
'suffix' => array('length' => 20, 'start' => 178),
'address' => array('length' => 35, 'start' => 198),
'postalcode' => array('length' => 10, 'start' => 233),
'city' => array('length' => 28, 'start' => 243),
'state' => array('length' => 5, 'start' => 271),
'greeting' => array('length' => 40, 'start' => 276)
);
$str = '4';
foreach($fields as $field_name => $field)
{
if($$field_name)
{
$str = str_pad($str, $field['start']-1, ' ');
$str = $str.substr(trim((string)$$field_name), 0, $field['length']);
}
}
return $str."\n";
}
它似乎按预期工作,但当我查看输出文件时,我发现了这一点(滚动到结尾):
4 1 David Landrum
4 3 Hazel Baker
4 3 Jerome Zehnder
4 1 VÃctor Nadales
4 2 Philip Nauert
4 1 Jana Ortcutter
该文件包含从数据库中提取的900条记录,所有这些记录都已正确格式化,但VÃctorNadales除外。在第一个名字之后,每隔一个字段就是它应该在的三个空格。关于这个记录的唯一异常似乎是名字中的'Ã'。
该函数应该在它处理的每个字段之后将字符串填充到适当的长度,但它在这一行上以某种方式被愚弄了?
谁能告诉我这里发生了什么?
编辑:我刚刚意识到这种格式的任何导入文件甚至可能都不支持特殊的UTF-8字符。因此我将此行添加到我的代码中:$$field_name = iconv('UTF-8', 'ASCII//TRANSLIT', $$field_name);
comes看起来像这样:~A-。不理想,但至少现在文件格式正确。
答案 0 :(得分:10)
这种情况正在发生,因为'Ã'
是一个多字节字符(长度为4个字节),而str_pad
是计算字节而不是逻辑字符。
这就是为什么你缺少三个空格,str_pad
将'Ã'
计为4个单字节字符而不是一个多字节字符。
尝试此功能(credit here)。
<?
function mb_str_pad( $input, $pad_length, $pad_string = ' ', $pad_type = STR_PAD_RIGHT)
{
$diff = strlen( $input ) - mb_strlen( $input );
return str_pad( $input, $pad_length + $diff, $pad_string, $pad_type );
}
?>
答案 1 :(得分:6)
使用Gordon的解决方案,您只需将编码类型添加到mb_strlen
,它将正确计算字节数(至少它对我有用)
这是我使用的功能:
function mb_str_pad( $input, $pad_length, $pad_string = ' ', $pad_type = STR_PAD_RIGHT, $encoding="UTF-8") {
$diff = strlen( $input ) - mb_strlen($input, $encoding);
return str_pad( $input, $pad_length + $diff, $pad_string, $pad_type );
}
赞成这个想法here
答案 2 :(得分:2)
function mb_str_pad($input, $pad_length, $pad_string = ' ', $pad_type = STR_PAD_RIGHT) {
$diff = strlen($input) - mb_strlen($input,mb_detect_encoding($input));
return str_pad($input, $pad_length + $diff, $pad_string, $pad_type);
}