Stream_get_contents thành mảng php

Nếu ai đã từng tham gia các dự án outsource cho khách hàng Nhật Bản thì đều gặp bài toán thông tin phổ biến lấy dữ liệu từ cơ sở dữ liệu và xuất ra báo cáo

ID,従業員コード,氏名※,フリガナ
1,A01.,山,カミソヤマ ユニ
2,A02,上曽山 ゆに,ソ ユニ
3,A03,"上曽山\" 上曽山",ゆに
6 cho người dùng. Nghe rất đơn giản, ta chỉ cần sử dụng hàm có sẵn của
ID,従業員コード,氏名※,フリガナ
1,A01.,山,カミソヤマ ユニ
2,A02,上曽山 ゆに,ソ ユニ
3,A03,"上曽山\" 上曽山",ゆに
7

fputcsv [ resource $handle , array $fields [, string $delimiter = "," [, string $enclosure = '"' [, string $escape_char = "\\" ]]] ] : int

  • xử lý. Con trỏ tệp
  • lĩnh vực. Data array [dữ liệu hàng]
  • dấu phân cách. Ký tự ngăn cách các trường [Thường là dấu
    ID,従業員コード,氏名※,フリガナ
    1,A01.,山,カミソヤマ ユニ
    2,A02,上曽山 ゆに,ソ ユニ
    3,A03,"上曽山\" 上曽山",ゆに
    
    8 hoặc
    ID,従業員コード,氏名※,フリガナ
    1,A01.,山,カミソヤマ ユニ
    2,A02,上曽山 ゆに,ソ ユニ
    3,A03,"上曽山\" 上曽山",ゆに
    
    9]
  • bao vây. Ký tự sử dụng để kiểm tra xem một trường được bắt đầu và kết thúc
  • thoát_char. Escape ký tự [ko biết cách dịch nào cho hợp lý] để tắt cơ chế này, hãy đặt giá trị trống [“”]

    Ví dụ.

    ID,従業員コード,氏名※,フリガナ
    1,A01,山,"カミソヤマ ユニ"
    2,A02,上曽山 ゆに,"ソ ユニ"
    3,A03,"上曽山\" 上曽山",ゆに
    
    0

Mã hóa, bài toán muôn thuở

Đi tới các vấn đề phức tạp hơn

Chúng ta có nhận thêm yêu cầu là muốn chuyển đổi dữ liệu trong csv này từ bản gốc

ID,従業員コード,氏名※,フリガナ
1,A01,山,"カミソヤマ ユニ"
2,A02,上曽山 ゆに,"ソ ユニ"
3,A03,"上曽山\" 上曽山",ゆに
1 sang
ID,従業員コード,氏名※,フリガナ
1,A01,山,"カミソヤマ ユニ"
2,A02,上曽山 ゆに,"ソ ユニ"
3,A03,"上曽山\" 上曽山",ゆに
2 ~ WTF. 🎱

Lý do người Nhật vẫn sử dụng

ID,従業員コード,氏名※,フリガナ
1,A01,山,"カミソヤマ ユニ"
2,A02,上曽山 ゆに,"ソ ユニ"
3,A03,"上曽山\" 上曽山",ゆに
2 chỉ gói đơn giản gọn trong 1 từ khóa Legacy.
ID,従業員コード,氏名※,フリガナ
1,A01,山,"カミソヤマ ユニ"
2,A02,上曽山 ゆに,"ソ ユニ"
3,A03,"上曽山\" 上曽山",ゆに
2,
ID,従業員コード,氏名※,フリガナ
1,A01,山,"カミソヤマ ユニ"
2,A02,上曽山 ゆに,"ソ ユニ"
3,A03,"上曽山\" 上曽山",ゆに
5 đều là những mã hóa tiêu chuẩn được sử dụng trước khi mà
ID,従業員コード,氏名※,フリガナ
1,A01,山,"カミソヤマ ユニ"
2,A02,上曽山 ゆに,"ソ ユニ"
3,A03,"上曽山\" 上曽山",ゆに
1 trở nên phổ biến như ngày hôm nay. Ngoài ra còn một lý do nữa mình nghĩ cũng quan trọng khi mà
ID,従業員コード,氏名※,フリガナ
1,A01,山,"カミソヤマ ユニ"
2,A02,上曽山 ゆに,"ソ ユニ"
3,A03,"上曽山\" 上曽山",ゆに
2 chỉ cần sử dụng mã hóa
ID,従業員コード,氏名※,フリガナ
1,A01,山,"カミソヤマ ユニ"
2,A02,上曽山 ゆに,"ソ ユニ"
3,A03,"上曽山\" 上曽山",ゆに
8 trong khi
ID,従業員コード,氏名※,フリガナ
1,A01,山,"カミソヤマ ユニ"
2,A02,上曽山 ゆに,"ソ ユニ"
3,A03,"上曽山\" 上曽山",ゆに
1 cần tới
$stdout = fopen['php://stdout', 'w'];
fprintf[$stdout, "UTF-8 ソ: 0x%s\n", bin2hex['ソ']];
fprintf[$stdout, "UTF-8 十: 0x%s\n", bin2hex['十']];
fprintf[$stdout, "Shift-JIS ソ: 0x%s\n", bin2hex[mb_convert_encoding['ソ', 'SJIS', 'UTF-8']]];
fprintf[$stdout, "Shift-JIS 十: 0x%s\n", bin2hex[mb_convert_encoding['十', 'SJIS', 'UTF-8']]];
0 để mã hóa tiếng Nhật nói chung và
$stdout = fopen['php://stdout', 'w'];
fprintf[$stdout, "UTF-8 ソ: 0x%s\n", bin2hex['ソ']];
fprintf[$stdout, "UTF-8 十: 0x%s\n", bin2hex['十']];
fprintf[$stdout, "Shift-JIS ソ: 0x%s\n", bin2hex[mb_convert_encoding['ソ', 'SJIS', 'UTF-8']]];
fprintf[$stdout, "Shift-JIS 十: 0x%s\n", bin2hex[mb_convert_encoding['十', 'SJIS', 'UTF-8']]];
1 nói riêng 🎃

Ở đây mình có mã cơ sở như sau. Thay vì đọc dữ liệu từ cơ sở dữ liệu, chúng được hard code trong 1 mảng

function convert[$fields] {
    $result = [];
    foreach [$fields as $field] {
        $result[] = mb_convert_encoding[$field, 'SJIS', 'UTF-8'];
    }
    return $result;
}

function arr2csv[$rows] {
    $fp = fopen['php://temp', 'r+b'];
    foreach[$rows as $fields] {
        // Convert row data from UTF-8 to Shift-JS
        $fields = convert[$fields];
        fputcsv[$fp, $fields];
    }
    rewind[$fp];
    // Convert CRLF
    $tmp = str_replace[PHP_EOL, "\r\n", stream_get_contents[$fp]];
    fclose[$fp];
    return $tmp;
}

function writecsv[$filename] {
    // Header of csv
    $header = [
        'ID',
        '従業員コード', // Employee code
        '氏名※',       // Name
        'フリガナ',     // Furigana
    ];
    // Sample data from database
    $data = [
        [
            "id" => 1,
            "code" => "A01",
            "name" => "山",
            "furigana" => "カミソヤマ ユニ"
        ],
        [
            "id" => 2,
            "code" => "A02",
            "name" => "上曽山 ゆに",
            "furigana" => "ソ ユニ",
        ],
        [
            "id" => 3,
            "code" => "A03",
            "name" => '上曽山\\" 上曽山',
            "furigana" => "ゆに",
        ],
    ];
    // Prepend header
    array_unshift[$data, $header];
    // Open file to write stream data
    $f = fopen[$filename, 'w+'];
    fwrite[$f, arr2csv[$data]];
    fclose[$f];
}

writecsv["output.csv"];

  • Kỳ vọng

    ID,従業員コード,氏名※,フリガナ
    1,A01.,山,カミソヤマ ユニ
    2,A02,上曽山 ゆに,ソ ユニ
    3,A03,"上曽山\" 上曽山",ゆに
    

  • đầu ra

    ID,従業員コード,氏名※,フリガナ
    1,A01,山,"カミソヤマ ユニ"
    2,A02,上曽山 ゆに,"ソ ユニ"
    3,A03,"上曽山\" 上曽山",ゆに
    

    To idea will see the row number 1, column Furigana. Giá trị

    $stdout = fopen['php://stdout', 'w'];
    fprintf[$stdout, "UTF-8 ソ: 0x%s\n", bin2hex['ソ']];
    fprintf[$stdout, "UTF-8 十: 0x%s\n", bin2hex['十']];
    fprintf[$stdout, "Shift-JIS ソ: 0x%s\n", bin2hex[mb_convert_encoding['ソ', 'SJIS', 'UTF-8']]];
    fprintf[$stdout, "Shift-JIS 十: 0x%s\n", bin2hex[mb_convert_encoding['十', 'SJIS', 'UTF-8']]];
    
    2 được đặt trong dấu ấn
    $stdout = fopen['php://stdout', 'w'];
    fprintf[$stdout, "UTF-8 ソ: 0x%s\n", bin2hex['ソ']];
    fprintf[$stdout, "UTF-8 十: 0x%s\n", bin2hex['十']];
    fprintf[$stdout, "Shift-JIS ソ: 0x%s\n", bin2hex[mb_convert_encoding['ソ', 'SJIS', 'UTF-8']]];
    fprintf[$stdout, "Shift-JIS 十: 0x%s\n", bin2hex[mb_convert_encoding['十', 'SJIS', 'UTF-8']]];
    
    3, trở thành
    $stdout = fopen['php://stdout', 'w'];
    fprintf[$stdout, "UTF-8 ソ: 0x%s\n", bin2hex['ソ']];
    fprintf[$stdout, "UTF-8 十: 0x%s\n", bin2hex['十']];
    fprintf[$stdout, "Shift-JIS ソ: 0x%s\n", bin2hex[mb_convert_encoding['ソ', 'SJIS', 'UTF-8']]];
    fprintf[$stdout, "Shift-JIS 十: 0x%s\n", bin2hex[mb_convert_encoding['十', 'SJIS', 'UTF-8']]];
    
    4. Nếu chỉ xem trên các chương trình như Open Office, MS Excel sẽ rất khó phát hiện. Ở đây mình có 2 ảnh mở trên
    $stdout = fopen['php://stdout', 'w'];
    fprintf[$stdout, "UTF-8 ソ: 0x%s\n", bin2hex['ソ']];
    fprintf[$stdout, "UTF-8 十: 0x%s\n", bin2hex['十']];
    fprintf[$stdout, "Shift-JIS ソ: 0x%s\n", bin2hex[mb_convert_encoding['ソ', 'SJIS', 'UTF-8']]];
    fprintf[$stdout, "Shift-JIS 十: 0x%s\n", bin2hex[mb_convert_encoding['十', 'SJIS', 'UTF-8']]];
    
    5 và
    $stdout = fopen['php://stdout', 'w'];
    fprintf[$stdout, "UTF-8 ソ: 0x%s\n", bin2hex['ソ']];
    fprintf[$stdout, "UTF-8 十: 0x%s\n", bin2hex['十']];
    fprintf[$stdout, "Shift-JIS ソ: 0x%s\n", bin2hex[mb_convert_encoding['ソ', 'SJIS', 'UTF-8']]];
    fprintf[$stdout, "Shift-JIS 十: 0x%s\n", bin2hex[mb_convert_encoding['十', 'SJIS', 'UTF-8']]];
    
    6 sẽ biết điều đó.

Trong dữ liệu bên ngoài hàng cuối cùng chứa ký tự kép trích dẫn

$stdout = fopen['php://stdout', 'w'];
fprintf[$stdout, "UTF-8 ソ: 0x%s\n", bin2hex['ソ']];
fprintf[$stdout, "UTF-8 十: 0x%s\n", bin2hex['十']];
fprintf[$stdout, "Shift-JIS ソ: 0x%s\n", bin2hex[mb_convert_encoding['ソ', 'SJIS', 'UTF-8']]];
fprintf[$stdout, "Shift-JIS 十: 0x%s\n", bin2hex[mb_convert_encoding['十', 'SJIS', 'UTF-8']]];
3 ra thì các hàng ở trên nó hoàn toàn không chứa ký tự đó. Cần phải có lý do gì để quấn lại thế mà 😢

Sau khi thử loại trừ bằng cách xóa dần các ký tự bên trong giá trị của các trường, mình phát hiện thêm 1 điều

Giá trị trên mỗi hàng của csv chỉ bị xóa dấu ngoặc kép bổ sung thêm trong trường hợp có chứa ký tự 「ソ」、「十」 hoặc ký tự nào nữa không rõ ???

$stdout = fopen['php://stdout', 'w'];
fprintf[$stdout, "UTF-8 ソ: 0x%s\n", bin2hex['ソ']];
fprintf[$stdout, "UTF-8 十: 0x%s\n", bin2hex['十']];
fprintf[$stdout, "Shift-JIS ソ: 0x%s\n", bin2hex[mb_convert_encoding['ソ', 'SJIS', 'UTF-8']]];
fprintf[$stdout, "Shift-JIS 十: 0x%s\n", bin2hex[mb_convert_encoding['十', 'SJIS', 'UTF-8']]];

UTF-8 ソ: 0xe382bd
UTF-8 十: 0xe58d81
Shift-JIS ソ: 0x835c
Shift-JIS 十: 0x8f5c

Nhìn vào mã trên ta có thể thấy UTF-8 cần 3 byte trong khi Shift-JIS chỉ cần 2 byte cho các ký tự tiếng nhật. Tools

「ソ」=「0x8F5C」=「0x8F」+「0x5C」

「十」=「0x8f5c」=「0x8f」+「0x5c」

Sau khi đã cố gắng tìm kiếm nguyên nhân trên Google mà vẫn không cho kết quả tốt, thì quyết định cuối cùng là thử nghiệm hướng tới phương pháp

$stdout = fopen['php://stdout', 'w'];
fprintf[$stdout, "UTF-8 ソ: 0x%s\n", bin2hex['ソ']];
fprintf[$stdout, "UTF-8 十: 0x%s\n", bin2hex['十']];
fprintf[$stdout, "Shift-JIS ソ: 0x%s\n", bin2hex[mb_convert_encoding['ソ', 'SJIS', 'UTF-8']]];
fprintf[$stdout, "Shift-JIS 十: 0x%s\n", bin2hex[mb_convert_encoding['十', 'SJIS', 'UTF-8']]];
8 bên trong
$stdout = fopen['php://stdout', 'w'];
fprintf[$stdout, "UTF-8 ソ: 0x%s\n", bin2hex['ソ']];
fprintf[$stdout, "UTF-8 十: 0x%s\n", bin2hex['十']];
fprintf[$stdout, "Shift-JIS ソ: 0x%s\n", bin2hex[mb_convert_encoding['ソ', 'SJIS', 'UTF-8']]];
fprintf[$stdout, "Shift-JIS 十: 0x%s\n", bin2hex[mb_convert_encoding['十', 'SJIS', 'UTF-8']]];
9

  PHPAPI size_t php_fputcsv[php_stream *stream, zval *fields, char delimiter, char enclosure, int escape_char]
  {
    ...
    smart_str csvline = {0};

    ZEND_ASSERT[[escape_char >= 0 && escape_char = 0 && escape_char  1,
            "code" => "A01",
            "name" => "山",
            "furigana" => "カミソヤマ ユニ"
        ],
        [
            "id" => 2,
            "code" => "A02",
            "name" => "上曽山 ゆに",
            "furigana" => "ソ ユニ",
        ],
        [
            "id" => 3,
            "code" => "A03",
            "name" => '上曽山\\" 上曽山',
            "furigana" => "ゆに",
        ],
    ];
    // Prepend header
    array_unshift[$data, $header];
    // Open file to write stream data
    $f = fopen[$filename, 'w+'];
    fwrite[$f, arr2csv[$data]];
    fclose[$f];
}

writecsv["output.csv"];
0

Được rồi, đọc tới đây chắc chắn bạn đã hiểu nguyên lý hoạt động của phương thức

  PHPAPI size_t php_fputcsv[php_stream *stream, zval *fields, char delimiter, char enclosure, int escape_char]
  {
    ...
    smart_str csvline = {0};

    ZEND_ASSERT[[escape_char >= 0 && escape_char  "山",
            "furigana" => "カミソヤマ ユニ"
        ],
        [
            "id" => 2,
            "code" => "A02",
            "name" => "上曽山 ゆに",
            "furigana" => "ソ ユニ",
        ],
        [
            "id" => 3,
            "code" => "A03",
            "name" => '上曽山\\" 上曽山',
            "furigana" => "ゆに",
        ],
    ];
    // Prepend header
    array_unshift[$data, $header];
    // Open file to write stream data
    $f = fopen[$filename, 'w+'];
    fwrite[$f, arr2csv[$data]];
    fclose[$f];
}

writecsv["output.csv"];
1

  • đầu ra

    function convert[$fields] {
        $result = [];
        foreach [$fields as $field] {
            $result[] = mb_convert_encoding[$field, 'SJIS', 'UTF-8'];
        }
        return $result;
    }
    
    function arr2csv[$rows] {
        $fp = fopen['php://temp', 'r+b'];
        foreach[$rows as $fields] {
            // Convert row data from UTF-8 to Shift-JS
            $fields = convert[$fields];
            fputcsv[$fp, $fields];
        }
        rewind[$fp];
        // Convert CRLF
        $tmp = str_replace[PHP_EOL, "\r\n", stream_get_contents[$fp]];
        fclose[$fp];
        return $tmp;
    }
    
    function writecsv[$filename] {
        // Header of csv
        $header = [
            'ID',
            '従業員コード', // Employee code
            '氏名※',       // Name
            'フリガナ',     // Furigana
        ];
        // Sample data from database
        $data = [
            [
                "id" => 1,
                "code" => "A01",
                "name" => "山",
                "furigana" => "カミソヤマ ユニ"
            ],
            [
                "id" => 2,
                "code" => "A02",
                "name" => "上曽山 ゆに",
                "furigana" => "ソ ユニ",
            ],
            [
                "id" => 3,
                "code" => "A03",
                "name" => '上曽山\\" 上曽山',
                "furigana" => "ゆに",
            ],
        ];
        // Prepend header
        array_unshift[$data, $header];
        // Open file to write stream data
        $f = fopen[$filename, 'w+'];
        fwrite[$f, arr2csv[$data]];
        fclose[$f];
    }
    
    writecsv["output.csv"];
    
    2

Dấu gạch chéo ngược ký tự

  PHPAPI size_t php_fputcsv[php_stream *stream, zval *fields, char delimiter, char enclosure, int escape_char]
  {
    ...
    smart_str csvline = {0};

    ZEND_ASSERT[[escape_char >= 0 && escape_char = 0 && escape_char  1,
            "code" => "A01",
            "name" => "山",
            "furigana" => "カミソヤマ ユニ"
        ],
        [
            "id" => 2,
            "code" => "A02",
            "name" => "上曽山 ゆに",
            "furigana" => "ソ ユニ",
        ],
        [
            "id" => 3,
            "code" => "A03",
            "name" => '上曽山\\" 上曽山',
            "furigana" => "ゆに",
        ],
    ];
    // Prepend header
    array_unshift[$data, $header];
    // Open file to write stream data
    $f = fopen[$filename, 'w+'];
    fwrite[$f, arr2csv[$data]];
    fclose[$f];
}

writecsv["output.csv"];
3

  • Kỳ vọng

    ID,従業員コード,氏名※,フリガナ
    1,A01.,山,カミソヤマ ユニ
    2,A02,上曽山 ゆに,ソ ユニ
    3,A03,"上曽山\" 上曽山",ゆに
    

  • đầu ra

    ID,従業員コード,氏名※,フリガナ
    1,A01.,山,カミソヤマ ユニ
    2,A02,上曽山 ゆに,ソ ユニ
    3,A03,"上曽山\" 上曽山",ゆに
    

Xuất file đúng như mong đợi 👍 💯

Chuẩn RFC 4180 & Lỗi chưa được sửa

RFC 4180 một định dạng định dạng chuẩn cho tệp CSV được sử dụng để đọc CSV xuất trong rất nhiều ứng dụng, đơn cử như Bảng tính Google

If ta has 1 sheet with the content after

function convert[$fields] {
    $result = [];
    foreach [$fields as $field] {
        $result[] = mb_convert_encoding[$field, 'SJIS', 'UTF-8'];
    }
    return $result;
}

function arr2csv[$rows] {
    $fp = fopen['php://temp', 'r+b'];
    foreach[$rows as $fields] {
        // Convert row data from UTF-8 to Shift-JS
        $fields = convert[$fields];
        fputcsv[$fp, $fields];
    }
    rewind[$fp];
    // Convert CRLF
    $tmp = str_replace[PHP_EOL, "\r\n", stream_get_contents[$fp]];
    fclose[$fp];
    return $tmp;
}

function writecsv[$filename] {
    // Header of csv
    $header = [
        'ID',
        '従業員コード', // Employee code
        '氏名※',       // Name
        'フリガナ',     // Furigana
    ];
    // Sample data from database
    $data = [
        [
            "id" => 1,
            "code" => "A01",
            "name" => "山",
            "furigana" => "カミソヤマ ユニ"
        ],
        [
            "id" => 2,
            "code" => "A02",
            "name" => "上曽山 ゆに",
            "furigana" => "ソ ユニ",
        ],
        [
            "id" => 3,
            "code" => "A03",
            "name" => '上曽山\\" 上曽山',
            "furigana" => "ゆに",
        ],
    ];
    // Prepend header
    array_unshift[$data, $header];
    // Open file to write stream data
    $f = fopen[$filename, 'w+'];
    fwrite[$f, arr2csv[$data]];
    fclose[$f];
}

writecsv["output.csv"];
6

Thì khi chọn

/* enclose a field that contains a delimiter, an enclosure character, or a newline */
if [...
  [escape_char != PHP_CSV_NO_ESCAPE && FPUTCSV_FLD_CHK[escape_char]] ||
  ...
] {
7 ta sẽ lấy được nội dung file như sau

function convert[$fields] {
    $result = [];
    foreach [$fields as $field] {
        $result[] = mb_convert_encoding[$field, 'SJIS', 'UTF-8'];
    }
    return $result;
}

function arr2csv[$rows] {
    $fp = fopen['php://temp', 'r+b'];
    foreach[$rows as $fields] {
        // Convert row data from UTF-8 to Shift-JS
        $fields = convert[$fields];
        fputcsv[$fp, $fields];
    }
    rewind[$fp];
    // Convert CRLF
    $tmp = str_replace[PHP_EOL, "\r\n", stream_get_contents[$fp]];
    fclose[$fp];
    return $tmp;
}

function writecsv[$filename] {
    // Header of csv
    $header = [
        'ID',
        '従業員コード', // Employee code
        '氏名※',       // Name
        'フリガナ',     // Furigana
    ];
    // Sample data from database
    $data = [
        [
            "id" => 1,
            "code" => "A01",
            "name" => "山",
            "furigana" => "カミソヤマ ユニ"
        ],
        [
            "id" => 2,
            "code" => "A02",
            "name" => "上曽山 ゆに",
            "furigana" => "ソ ユニ",
        ],
        [
            "id" => 3,
            "code" => "A03",
            "name" => '上曽山\\" 上曽山',
            "furigana" => "ゆに",
        ],
    ];
    // Prepend header
    array_unshift[$data, $header];
    // Open file to write stream data
    $f = fopen[$filename, 'w+'];
    fwrite[$f, arr2csv[$data]];
    fclose[$f];
}

writecsv["output.csv"];
7

Try to use

ID,従業員コード,氏名※,フリガナ
1,A01.,山,カミソヤマ ユニ
2,A02,上曽山 ゆに,ソ ユニ
3,A03,"上曽山\" 上曽山",ゆに
7 read this file coi sao 😃

function convert[$fields] {
    $result = [];
    foreach [$fields as $field] {
        $result[] = mb_convert_encoding[$field, 'SJIS', 'UTF-8'];
    }
    return $result;
}

function arr2csv[$rows] {
    $fp = fopen['php://temp', 'r+b'];
    foreach[$rows as $fields] {
        // Convert row data from UTF-8 to Shift-JS
        $fields = convert[$fields];
        fputcsv[$fp, $fields];
    }
    rewind[$fp];
    // Convert CRLF
    $tmp = str_replace[PHP_EOL, "\r\n", stream_get_contents[$fp]];
    fclose[$fp];
    return $tmp;
}

function writecsv[$filename] {
    // Header of csv
    $header = [
        'ID',
        '従業員コード', // Employee code
        '氏名※',       // Name
        'フリガナ',     // Furigana
    ];
    // Sample data from database
    $data = [
        [
            "id" => 1,
            "code" => "A01",
            "name" => "山",
            "furigana" => "カミソヤマ ユニ"
        ],
        [
            "id" => 2,
            "code" => "A02",
            "name" => "上曽山 ゆに",
            "furigana" => "ソ ユニ",
        ],
        [
            "id" => 3,
            "code" => "A03",
            "name" => '上曽山\\" 上曽山',
            "furigana" => "ゆに",
        ],
    ];
    // Prepend header
    array_unshift[$data, $header];
    // Open file to write stream data
    $f = fopen[$filename, 'w+'];
    fwrite[$f, arr2csv[$data]];
    fclose[$f];
}

writecsv["output.csv"];
8

  • Kỳ vọng

    function convert[$fields] {
        $result = [];
        foreach [$fields as $field] {
            $result[] = mb_convert_encoding[$field, 'SJIS', 'UTF-8'];
        }
        return $result;
    }
    
    function arr2csv[$rows] {
        $fp = fopen['php://temp', 'r+b'];
        foreach[$rows as $fields] {
            // Convert row data from UTF-8 to Shift-JS
            $fields = convert[$fields];
            fputcsv[$fp, $fields];
        }
        rewind[$fp];
        // Convert CRLF
        $tmp = str_replace[PHP_EOL, "\r\n", stream_get_contents[$fp]];
        fclose[$fp];
        return $tmp;
    }
    
    function writecsv[$filename] {
        // Header of csv
        $header = [
            'ID',
            '従業員コード', // Employee code
            '氏名※',       // Name
            'フリガナ',     // Furigana
        ];
        // Sample data from database
        $data = [
            [
                "id" => 1,
                "code" => "A01",
                "name" => "山",
                "furigana" => "カミソヤマ ユニ"
            ],
            [
                "id" => 2,
                "code" => "A02",
                "name" => "上曽山 ゆに",
                "furigana" => "ソ ユニ",
            ],
            [
                "id" => 3,
                "code" => "A03",
                "name" => '上曽山\\" 上曽山',
                "furigana" => "ゆに",
            ],
        ];
        // Prepend header
        array_unshift[$data, $header];
        // Open file to write stream data
        $f = fopen[$filename, 'w+'];
        fwrite[$f, arr2csv[$data]];
        fclose[$f];
    }
    
    writecsv["output.csv"];
    
    9

  • đầu ra

    ID,従業員コード,氏名※,フリガナ
    1,A01.,山,カミソヤマ ユニ
    2,A02,上曽山 ゆに,ソ ユニ
    3,A03,"上曽山\" 上曽山",ゆに
    
    0

Nguyên nhân kết quả mong đợi không đúng như mong đợi là do hàm

/* enclose a field that contains a delimiter, an enclosure character, or a newline */
if [...
  [escape_char != PHP_CSV_NO_ESCAPE && FPUTCSV_FLD_CHK[escape_char]] ||
  ...
] {
9 của
ID,従業員コード,氏名※,フリガナ
1,A01.,山,カミソヤマ ユニ
2,A02,上曽山 ゆに,ソ ユニ
3,A03,"上曽山\" 上曽山",ゆに
7 đang được sử dụng sai tiêu chuẩn RFC 4180

Nếu dấu ngoặc kép được sử dụng để bao quanh các trường, thì dấu ngoặc kép xuất hiện bên trong trường phải được thoát ra bằng cách đặt trước nó bằng một dấu ngoặc kép khác

Edit edit back a time

ID,従業員コード,氏名※,フリガナ
1,A01.,山,カミソヤマ ユニ
2,A02,上曽山 ゆに,ソ ユニ
3,A03,"上曽山\" 上曽山",ゆに
1

  • Kỳ vọng

    function convert[$fields] {
        $result = [];
        foreach [$fields as $field] {
            $result[] = mb_convert_encoding[$field, 'SJIS', 'UTF-8'];
        }
        return $result;
    }
    
    function arr2csv[$rows] {
        $fp = fopen['php://temp', 'r+b'];
        foreach[$rows as $fields] {
            // Convert row data from UTF-8 to Shift-JS
            $fields = convert[$fields];
            fputcsv[$fp, $fields];
        }
        rewind[$fp];
        // Convert CRLF
        $tmp = str_replace[PHP_EOL, "\r\n", stream_get_contents[$fp]];
        fclose[$fp];
        return $tmp;
    }
    
    function writecsv[$filename] {
        // Header of csv
        $header = [
            'ID',
            '従業員コード', // Employee code
            '氏名※',       // Name
            'フリガナ',     // Furigana
        ];
        // Sample data from database
        $data = [
            [
                "id" => 1,
                "code" => "A01",
                "name" => "山",
                "furigana" => "カミソヤマ ユニ"
            ],
            [
                "id" => 2,
                "code" => "A02",
                "name" => "上曽山 ゆに",
                "furigana" => "ソ ユニ",
            ],
            [
                "id" => 3,
                "code" => "A03",
                "name" => '上曽山\\" 上曽山',
                "furigana" => "ゆに",
            ],
        ];
        // Prepend header
        array_unshift[$data, $header];
        // Open file to write stream data
        $f = fopen[$filename, 'w+'];
        fwrite[$f, arr2csv[$data]];
        fclose[$f];
    }
    
    writecsv["output.csv"];
    
    9

  • đầu ra

    function convert[$fields] {
        $result = [];
        foreach [$fields as $field] {
            $result[] = mb_convert_encoding[$field, 'SJIS', 'UTF-8'];
        }
        return $result;
    }
    
    function arr2csv[$rows] {
        $fp = fopen['php://temp', 'r+b'];
        foreach[$rows as $fields] {
            // Convert row data from UTF-8 to Shift-JS
            $fields = convert[$fields];
            fputcsv[$fp, $fields];
        }
        rewind[$fp];
        // Convert CRLF
        $tmp = str_replace[PHP_EOL, "\r\n", stream_get_contents[$fp]];
        fclose[$fp];
        return $tmp;
    }
    
    function writecsv[$filename] {
        // Header of csv
        $header = [
            'ID',
            '従業員コード', // Employee code
            '氏名※',       // Name
            'フリガナ',     // Furigana
        ];
        // Sample data from database
        $data = [
            [
                "id" => 1,
                "code" => "A01",
                "name" => "山",
                "furigana" => "カミソヤマ ユニ"
            ],
            [
                "id" => 2,
                "code" => "A02",
                "name" => "上曽山 ゆに",
                "furigana" => "ソ ユニ",
            ],
            [
                "id" => 3,
                "code" => "A03",
                "name" => '上曽山\\" 上曽山',
                "furigana" => "ゆに",
            ],
        ];
        // Prepend header
        array_unshift[$data, $header];
        // Open file to write stream data
        $f = fopen[$filename, 'w+'];
        fwrite[$f, arr2csv[$data]];
        fclose[$f];
    }
    
    writecsv["output.csv"];
    
    9

Tuy nhiên, khi sử dụng

/* enclose a field that contains a delimiter, an enclosure character, or a newline */
if [...
  [escape_char != PHP_CSV_NO_ESCAPE && FPUTCSV_FLD_CHK[escape_char]] ||
  ...
] {
9 với tiêu chuẩn RFC_4180 để ghi ra tệp csv rồi sau đó sử dụng
#define FPUTCSV_FLD_CHK[c] memchr[ZSTR_VAL[field_str], c, ZSTR_LEN[field_str]]
// ---> Return:
// A pointer to the first occurrence of value[c] in the block of memory pointed by ptr[field_str].
// If the value is not found, the function returns a null pointer.
2 để đọc lại tệp chính vừa được ghi thì kết quả lại không chính xác

ID,従業員コード,氏名※,フリガナ
1,A01.,山,カミソヤマ ユニ
2,A02,上曽山 ゆに,ソ ユニ
3,A03,"上曽山\" 上曽山",ゆに
4

  • đầu ra

    ID,従業員コード,氏名※,フリガナ
    1,A01.,山,カミソヤマ ユニ
    2,A02,上曽山 ゆに,ソ ユニ
    3,A03,"上曽山\" 上曽山",ゆに
    
    5

Kết quả đọc ra dễ thấy thì dữ liệu lại trở thành 2 hàng trong khi kỳ vọng là 1 hàng mà thôi 🙃

Đây là một lỗi tồn tại trong PHP, không thể sửa được. bạn không thể coi đây là vấn đề coi. 50686 Hiện tại mình cũng không biết sửa lỗi này kiểu gì 🤣

Chủ Đề