2012-08-08 14 views
7

Ich schreibe ein Modul, das Transaktionsdatensätze im BankOne-Format exportieren soll.Sonderzeichen, die str_pad in PHP abwerfen?

Here is the specification of the format

Here is an example file

Die Felder sind in bestimmten Bereichen auf der Linie setzen und Aufzeichnungen durch neue Zeilen getrennt sind. Es müssen viele Leerzeichen hinzugefügt werden, um sicherzustellen, dass die Felder an bestimmten Punkten in der Zeile beginnen und enden.

Ich schrieb eine Funktion in PHP für diese. Es nimmt die Felder als Parameter auf und sollte einen korrekt formatierten Datensatz zurückgeben.

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"; 
} 

Es scheint, als beabsichtigt zu arbeiten, aber wenn ich an der Ausgabedatei sah ich diese gefunden (scrollen bis zum Ende):

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 

Die Datei aus einer Datenbank gezogen 900 Datensätze enthält, die alle von ihnen sind korrekt formatiert, außer VÃctor Nagales. Nach diesem Vornamen ist jedes zweite Feld noch drei Leerzeichen von dem, wo es sein soll. Das einzige Anomale an diesem Datensatz scheint das 'Ã' im Vornamen zu sein.

Die Funktion soll die Zeichenfolge nach jedem Feld, das sie verarbeitet, auf die richtige Länge auffüllen, aber irgendwie wird es auf dieser einen Zeile getäuscht?

Kann mir jemand sagen, was hier vor sich geht?

EDIT: Ich habe gerade festgestellt, dass alle importierten Dateien dieses Formats nicht einmal spezielle UTF-8-Zeichen unterstützt. Deshalb habe ich diese Zeile zu meinem Code hinzugefügt:

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

Das à kommt aus wie folgt: ~ A-. Nicht ideal, aber zumindest ist die Datei jetzt richtig formatiert.

+0

Es ist höchstwahrscheinlich ein Multibyte String Problem (siehe die 'mb_str *' Funktionen). – Crontab

+0

Meine Vermutung ist, dass es "weil" vier Bytes lang ist, und "str_pad" zählt Bytes statt logische Zeichen. –

Antwort

10

Dies geschieht, weil 'Ã' ein Multi-Byte-Zeichen (4 Byte lang) ist und str_pad Bytes statt logische Zeichen zählt.

Aus diesem Grund fehlen Ihnen drei Leerzeichen. str_pad zählt 'Ã' als 4 Einzelbyte-Zeichen anstelle von einem Multi-Byte-Zeichen.

Probieren Sie diese Funktion aus (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); 
} 
?> 
+0

Vielen Dank für Ihre Antwort.Ich habe die Funktion, die Sie mir gegeben haben, ausprobiert, scheint aber immer noch in derselben Zeile zu stolpern. Ich habe auch substr auf mb_substr umgeschaltet. – Peronix

+0

Hmm, seltsam. Ich habe die Funktion nicht persönlich getestet, aber ich dachte, dass es funktionieren würde. Was ist die Ausgabe von 'mb_strlen' vs.' strlen' in Ihrer Unicode-Eingabezeichenfolge? Erkennt es das Multi-Byte-Zeichen richtig? –

+0

mb_strlen ("Víctor") und strlen ("Víctor") beide Return int (9) =/ – Peronix

6

Gordon-Lösung Verwenden Sie nur den Codierungstyp zu dem mb_strlen hinzufügen müssen, und es wird die Bytes richtig (zumindest für mich gearbeitet)

Hier ist die Funktion, die ich verwendet, zählen:

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); 
} 

Kredit für die Idee here

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); 
} 
+1

Können Sie Ihre Antwort erklären? – i3arnon

+0

Es erkennt automatisch, dass die Eingabezeichenfolge im zweiten Parameter von mb_strlen unter Verwendung von mb_detect_encoding eingegeben wird, sodass kein weiterer Parameter zum Funktionsaufruf hinzugefügt werden muss –