12

我正在编写一个应该能够以 BankOne 格式导出交易记录的模块。

这是格式的规范

这是一个示例文件

字段放在行上的特定范围内,记录由新行分隔。需要添加大量空格以确保字段在行中的特定点开始和结束。

为此,我在 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íctor Nadales。在这个名字之后,每隔一个字段就在它应该在的位置的左边三个空格处。这张唱片唯一的异常似乎是名字中的“Ô。

该函数应该在它处理的每个字段之后将字符串填充到适当的长度,但是它以某种方式在这一行上被愚弄了?

谁能告诉我这里发生了什么?

编辑:我刚刚意识到这种格式的任何导入文件甚至可能不支持特殊的 UTF-8 字符。因此,我将此行添加到我的代码中:

$$field_name = iconv('UTF-8', 'ASCII//TRANSLIT', $$field_name);

à 看起来像这样:~A-。不理想,但至少文件现在格式正确。

4

3 回答 3

14

发生这种情况是因为'Ã'它是一个多字节字符(4 个字节长),并且str_pad计算的是字节数而不是逻辑字符数。

这就是为什么您缺少三个空格,str_pad将其计'Ã'为 4 个单字节字符而不是一个多字节字符。

试试这个功能(信用在这里)。

<?
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 );
}
?>
于 2012-08-08T19:40:32.860 回答
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 );
}

归功于这里的想法

于 2013-05-13T00:50:20.883 回答
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);
}
于 2014-01-07T09:40:05.627 回答