8

Excelで生成されたCSVファイルから次のようなXMLドキュメントにコンテンツをインポートしています。

$csv = fopen($csvfile, r);
$words = array();

while (($pair = fgetcsv($csv)) !== FALSE) {
    array_push($words, array('en' => $pair[0], 'de' => $pair[1]));
}

挿入されたデータは英語/ドイツ語の表現です。

これらの値をXML構造に挿入し、次のようにXMLを出力します。

$dictionary = new SimpleXMLElement('<dictionary></dictionary>');
//do things
$dom = dom_import_simplexml($dictionary) -> ownerDocument;
$dom -> formatOutput = true;

header('Content-encoding: utf-8'); //<3 UTF-8
header('Content-type: text/xml'); //Headers set to correct mime-type for XML output!!!!

echo $dom -> saveXML();

これは正常に機能していますが、1つの非常に奇妙な問題が発生しています。文字列の最初の文字がウムラウト(ÖsterreichまたはのようにÄgypten)の場合、文字は省略され、結果としてgyptenまたはになりsterreichます。ウムラウトが文字列()の真ん中にある場合、Russische Föderation正しく転送されます。同じことが、または何かのようなものにßé当てはまります。

すべてのファイルはUTF-8でエンコードされ、UTF-8で提供されます。

これは私にはかなり奇妙でバグのように思えますが、何かが足りないかもしれません。この辺りには賢い人がたくさんいます。

4

5 に答える 5

4

さて、これはのバグのようfgetcsvです。

現在、CSVデータを自分で処理しています(少し面倒です)が、機能しており、エンコードの問題はまったくありません。

これは(まだ最適化されていないバージョンの)私が行っていることです:

$rawCSV = file_get_contents($csvfile);

$lines = preg_split ('/$\R?^/m', $rawCSV); //split on line breaks in all operating systems: http://stackoverflow.com/a/7498886/797194

foreach ($lines as $line) {
    array_push($words, getCSVValues($line));
}

これはここgetCSVValuesから来ており、次のようなCSV行を処理するために必要です(カンマ!):

"I'm a string, what should I do when I need commas?",Howdy there

次のようになります。

function getCSVValues($string, $separator=","){

    $elements = explode($separator, $string);

    for ($i = 0; $i < count($elements); $i++) {
        $nquotes = substr_count($elements[$i], '"');
        if ($nquotes %2 == 1) {
            for ($j = $i+1; $j < count($elements); $j++) {
                if (substr_count($elements[$j], '"') %2 == 1) { // Look for an odd-number of quotes
                    // Put the quoted string's pieces back together again
                    array_splice($elements, $i, $j-$i+1,
                        implode($separator, array_slice($elements, $i, $j-$i+1)));
                    break;
                }
            }
        }
        if ($nquotes > 0) {
            // Remove first and last quotes, then merge pairs of quotes
            $qstr =& $elements[$i];
            $qstr = substr_replace($qstr, '', strpos($qstr, '"'), 1);
            $qstr = substr_replace($qstr, '', strrpos($qstr, '"'), 1);
            $qstr = str_replace('""', '"', $qstr);
        }
    }
    return $elements;

}

かなりの回避策がありますが、問題なく動作しているようです。

編集:

これにはファイルされたバグもあります。明らかにこれはロケール設定に依存します。

于 2012-09-13T08:20:58.617 に答える
3

文字列がExcelからのものである場合(文字列の先頭にある場合に文字øが消えるという問題がありました)...これで修正されました:

setlocale(LC_ALL、'en_US.ISO-8859-1');

于 2013-06-28T09:06:32.933 に答える
2

真ん中の他のウムラウトが正常に見える場合、これは基本エンコーディングの問題ではありません。行の先頭で発生するという事実は、おそらく改行マークとの非互換性を示しています。おそらく、CSVは別の改行エンコーディングで生成されました。

これは、異なるOS間でファイルを移動するときに発生します。

  • Windows :(\r\n文字13および10)
  • Linux :(\n文字10)
  • Mac OS :(\r文字13)

私があなたなら、確実に改行マークを確認します。

Linuxの場合:hexdump -C filename | moreそしてドキュメントを調べます。

sedその場合は、式を使用して改行マークを変更できます。

お役に立てば幸いです。

于 2012-09-13T05:29:23.657 に答える
2

少し簡単な回避策(しかしかなり汚い):

//1. replace delimiter in input string with delimiter + some constant
$dataLine = str_replace($this->fieldDelimiter, $this->fieldDelimiter . $this->bugFixer, $dataLine);

//2. parse
$parsedLine = str_getcsv($dataLine, $this->fieldDelimiter);

//3. remove the constant from resulting strings.
foreach ($parsedLine as $i => $parsedField)
{
    $parsedLine[$i] = str_replace($this->bugFixer, '', $parsedField);
}
于 2013-05-20T16:24:51.713 に答える
0

ある種のutf8_encode()問題である可能性があります。ドキュメントページのこのコメントは、すでにエンコードされているときにUmlautをエンコードすると、問題が発生する可能性があることを示しているようです。

たぶん、データがすでにutf-8でエンコードされているかどうかをテストしてくださいmb_detect_encoding()

于 2012-09-13T02:15:17.907 に答える