概要
PHPのSplFileObjectのフラグがわかりにくかったので整理した。確認したバージョンは以下の通り。
- OS: Vagrant/VirtualBox/CentOS7
- PHP: 7.3.28
- Laravel: 6.20.29
フラグ詳細
\SplFileObject::READ_CSV
- 行読込の際、CSV列として解釈する。
\SplFileObject::READ_AHEAD
- 日本語・英語のどのサイトでもマニュアル記述そのままに”先読み/巻き戻しで読み込む”としか書いていない。
SKIP_EMPTY
などの処理のためにバッファリングして、処理が行われた場合に巻き戻すという意味か。 \SplFileObject::SKIP_EMPTY
- 空行が無視される。改行コードのみの行は空行とは認識されず削除対象とならないが、
DROP_NEW_LINE
と組み合わせることで空行がスキップされる。 \SplFileObject::DROP_NEW_LINE
- 改行文字が無視される。ダブルクォートで囲んだ項目中に改行文字がある場合も、改行文字が削除される。たとえば以下の様にフィールドの途中に改行を入れたり、空行がある場合、
DROP_NEW_LINE
により宮城県と仙台市の間の改行が除かれ、”宮城県仙台市”とつなげられる
12345678東北支店,"宮城県仙台市",022-111-1111関東支店,"埼玉県大宮市",048-222-2222中部支店,愛知県名古屋市,052-333-3333近畿支店,大阪府大阪市,06-4444-4444中国支店,広島県広島市,082-555-5555九州支店,福岡県福岡市,092-666-6666
テキストファイル読み込み時
概要
以下のようにテキストファイルを扱いたい場合。
- 改行コードは取り除きたい
- 空行は読み飛ばしたい
このような場合、SplFileObject
のインスタンスに対して以下のようにフラグ設定する。
1 2 3 4 5 6 |
$file = new \SplFileObject(storage_path('app/text_sample_utf8.txt')); $file->setFlags( \SplFileObject::READ_AHEAD | \SplFileObject::DROP_NEW_LINE | \SplFileObject::SKIP_EMPTY); |
改行コードは取り除きたいが空行は空行のままで残したい場合はDROP_NEW_LINE
のみ設定し、READ_AHEAD
はあってもなくてもよい。ただし最後の行の次に空行が付いてきてしまう。
テスト用ファイル
以下のテキストファイルで確認した。エンコーディングはUTF-8で最後の行や空行も含めて各行末のコードはLF
。
1 2 3 4 5 6 7 8 9 10 11 |
[vagrant@localhost laravel_bbs]$ cat storage/app/text_sample_utf8.txt The rain in Spain stays mainly in the plain. スペインの雨は主に広野に降る。 In Hartford, Hereford and Hampshire Hurricanes hardly ever happen. ハートフォード、ヘレフォードとハンプシャーでは ハリケーンはめったに起こらない。 [vagrant@localhost laravel_bbs]$ |
テスト用コード
- コントローラーでファイルを読み込み、行単位で配列に格納
dd()
で配列の内容を確認(return
は実行されない)setFlags()
の引数を変化させて結果を比較
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
public function textRead(Request $request) { $file = new \SplFileObject(storage_path('app/text_sample_utf8.txt')); $file->setFlags(...); $lines = []; foreach ($file as $line) { $lines[] = $line; } dd($lines); return 'welcome'; } |
結果
フラグ設定なしの場合
setFlags()
の行をコメントアウトし、フラグ設定なしで実行した場合。
- 改行コードが残る
- 最終行の後に空文字列(
""
)が付いてくる
1 2 3 4 5 6 7 8 9 10 11 12 |
rray:10 [▼ 0 => "The rain in Spain stays mainly in the plain.\n" 1 => "\n" 2 => "スペインの雨は主に広野に降る。\n" 3 => "\n" 4 => "In Hartford, Hereford and Hampshire\n" 5 => "Hurricanes hardly ever happen.\n" 6 => "\n" 7 => "ハートフォード、ヘレフォードとハンプシャーでは\n" 8 => "ハリケーンはめったに起こらない。\n" 9 => "" ] |
SKIP_EMPTYのみを設定した場合
- 改行コードが残る
- 最終行の後に
boolean
のfalse
が付いてくる
1 2 3 4 5 6 7 8 9 10 11 12 |
array:10 [▼ 0 => "The rain in Spain stays mainly in the plain.\n" 1 => "\n" 2 => "スペインの雨は主に広野に降る。\n" 3 => "\n" 4 => "In Hartford, Hereford and Hampshire\n" 5 => "Hurricanes hardly ever happen.\n" 6 => "\n" 7 => "ハートフォード、ヘレフォードとハンプシャーでは\n" 8 => "ハリケーンはめったに起こらない。\n" 9 => false ] |
DROP_NEW_LINEのみを設定した場合
- 改行コードは取り除かれる
- 改行のみの空行は空文字列になる
- 最終行の後に空文字列が付いてくる
1 2 3 4 5 6 7 8 9 10 11 12 |
array:10 [▼ 0 => "The rain in Spain stays mainly in the plain." 1 => "" 2 => "スペインの雨は主に広野に降る。" 3 => "" 4 => "In Hartford, Hereford and Hampshire" 5 => "Hurricanes hardly ever happen." 6 => "" 7 => "ハートフォード、ヘレフォードとハンプシャーでは" 8 => "ハリケーンはめったに起こらない。" 9 => "" ] |
SKIP_EMPTY | DROP_NEW_LINE
- 改行コードは取り除かれる
- 空行は取り除かれる
- 最終行の後に
boolean
のfalse
が付いてくる
1 2 3 4 5 6 7 8 9 |
array:7 [▼ 0 => "The rain in Spain stays mainly in the plain." 1 => "スペインの雨は主に広野に降る。" 2 => "In Hartford, Hereford and Hampshire" 3 => "Hurricanes hardly ever happen." 4 => "ハートフォード、ヘレフォードとハンプシャーでは" 5 => "ハリケーンはめったに起こらない。" 6 => false ] |
READ_AHEAD | SKIP_EMPTY
- 改行コードは残る
- 空行は残る
- 最終行の後には何も付かない
1 2 3 4 5 6 7 8 9 10 |
array:9 [▼ 0 => "The rain in Spain stays mainly in the plain.\n" 1 => "\n" 2 => "スペインの雨は主に広野に降る。\n" 3 => "\n" 4 => "In Hartford, Hereford and Hampshire\n" 5 => "Hurricanes hardly ever happen.\n" 6 => "\n" 7 => "ハートフォード、ヘレフォードとハンプシャーでは\n" 8 => "ハリケーンはめったに起こらない。\n" |
READ_AHEAD | DROP_NEW_LINE
- 改行コードは取り除かれる
- 改行のみの空行は空文字列になる
- 最終行の後に空文字列が付けられる
1 2 3 4 5 6 7 8 9 10 11 12 |
rray:10 [▼ 0 => "The rain in Spain stays mainly in the plain." 1 => "" 2 => "スペインの雨は主に広野に降る。" 3 => "" 4 => "In Hartford, Hereford and Hampshire" 5 => "Hurricanes hardly ever happen." 6 => "" 7 => "ハートフォード、ヘレフォードとハンプシャーでは" 8 => "ハリケーンはめったに起こらない。" 9 => "" ] |
READ_AHEAD | SKIP_EMPTY | DROP_NEW_LINE
- 改行コードは取り除かれる
- 改行のみの空行は取り除かれる
- 最終行の後には何も付かない
1 2 3 4 5 6 7 |
array:6 [▼ 0 => "The rain in Spain stays mainly in the plain." 1 => "スペインの雨は主に広野に降る。" 2 => "In Hartford, Hereford and Hampshire" 3 => "Hurricanes hardly ever happen." 4 => "ハートフォード、ヘレフォードとハンプシャーでは" 5 => "ハリケーンはめったに起こらない。" |
CSVファイル読み込み時
概要
以下のようにCSVファイルを読み込みたい場合。
- 空行はスキップしたい
- フィールド中の改行は取り除きたい
このような場合、SplFileObject
のインスタンスに対して以下のようにフラグ設定する。
1 2 3 4 5 6 7 |
$file = new \SplFileObject(storage_path('app/CSV_sample_utf8.txt')); $file->setFlags( \SplFileObject::READ_CSV | \SplFileObject::READ_AHEAD | \SplFileObject::DROP_NEW_LINE | \SplFileObject::SKIP_EMPTY); |
空行はスキップするがフィールド中の改行は残したい場合、フラグの設定だけでそのような結果を得ることはできないようである。
READ_CSV
のみ設定し、内容がnull
のデータを登録せずに飛ばしていくことになる。
テスト用ファイル
1 2 3 4 5 6 7 |
[vagrant@localhost laravel_bbs]$ cat storage/app/csv_sample_utf8.csv 東北支店,宮城県仙台市,022-111-1111 関東支店,"埼玉県 大宮市",048-222-2222 中部支店,愛知県名古屋市,052-333-3333 [vagrant@localhost laravel_bbs]$ |
テスト用コード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
public function csvRead() { $file = new \SplFileObject(storage_path('app/csv_sample_utf8.csv')); $file->setFlags(\SplFileObject::READ_CSV ...); $lines = []; foreach($file as $line) { $lines[] = $line; } dd($lines); ..... } |
結果
READ_CSVのみの場合
- 空行に対応して
null
の要素が残る - フィールド中の改行は残る
- 最終データの後に
null
の要素が付く
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
array:5 [▼ 0 => array:3 [▼ 0 => "東北支店" 1 => "宮城県仙台市" 2 => "022-111-1111" ] 1 => array:1 [▼ 0 => null ] 2 => array:3 [▼ 0 => "関東支店" 1 => """ 埼玉県 大宮市 """ 2 => "048-222-2222" ] 3 => array:3 [▼ 0 => "中部支店" 1 => "愛知県名古屋市" 2 => "052-333-3333" ] 4 => array:1 [▼ 0 => null ] ] |
SKIP_EMPTYを追加
- 空行に対応して
null
の要素が残る - フィールド中の改行は残る
- 最終データの後に
false
の要素が付く
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
array:5 [▼ 0 => array:3 [▼ 0 => "東北支店" 1 => "宮城県仙台市" 2 => "022-111-1111" ] 1 => array:1 [▼ 0 => null ] 2 => array:3 [▼ 0 => "関東支店" 1 => """ 埼玉県 大宮市 """ 2 => "048-222-2222" ] 3 => array:3 [▼ 0 => "中部支店" 1 => "愛知県名古屋市" 2 => "052-333-3333" ] 4 => false ] |
DROP_NEW_LINEを追加
- 空行に対応して
null
の要素が残る - フィールド中の改行は取り除かれる
- 最終データの後に
null
の要素が付く
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
array:5 [▼ 0 => array:3 [▼ 0 => "東北支店" 1 => "宮城県仙台市" 2 => "022-111-1111" ] 1 => array:1 [▼ 0 => null ] 2 => array:3 [▼ 0 => "関東支店" 1 => "埼玉県大宮市" 2 => "048-222-2222" ] 3 => array:3 [▼ 0 => "中部支店" 1 => "愛知県名古屋市" 2 => "052-333-3333" ] 4 => array:1 [▼ 0 => null ] ] |
SKIP_EMPTY | DROP_NEW_LINEを追加
- 空行は取り除かれる
- フィールド中の改行は取り除かれる
- 最終データの後に
false
の要素が付く
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
array:4 [▼ 0 => array:3 [▼ 0 => "東北支店" 1 => "宮城県仙台市" 2 => "022-111-1111" ] 1 => array:3 [▼ 0 => "関東支店" 1 => "埼玉県大宮市" 2 => "048-222-2222" ] 2 => array:3 [▼ 0 => "中部支店" 1 => "愛知県名古屋市" 2 => "052-333-3333" ] 3 => false ] |
READ_AHEAD | SKIP_EMPTYを追加
- 空行に対応して
null
の要素が残る - フィールド中の改行は残る
- 最終データの後には何も付かない
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
array:4 [▼ 0 => array:3 [▼ 0 => "東北支店" 1 => "宮城県仙台市" 2 => "022-111-1111" ] 1 => array:1 [▼ 0 => null ] 2 => array:3 [▼ 0 => "関東支店" 1 => """ 埼玉県 大宮市 """ 2 => "048-222-2222" ] 3 => array:3 [▼ 0 => "中部支店" 1 => "愛知県名古屋市" 2 => "052-333-3333" ] ] |
READ_AHEAD | DROP_NEW_LINEを追加
- 空行に対応して
null
の要素が残る - フィールド中の改行は取り除かれる
- 最終データの後に
null
の要素が付く
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
array:5 [▼ 0 => array:3 [▼ 0 => "東北支店" 1 => "宮城県仙台市" 2 => "022-111-1111" ] 1 => array:1 [▼ 0 => null ] 2 => array:3 [▼ 0 => "関東支店" 1 => "埼玉県大宮市" 2 => "048-222-2222" ] 3 => array:3 [▼ 0 => "中部支店" 1 => "愛知県名古屋市" 2 => "052-333-3333" ] 4 => array:1 [▼ 0 => null ] ] |
READ_AHEAD | SKIP_EMPTY | DROP_NEW_LINEを追加
- 空行は取り除かれる
- フィールド中の改行は取り除かれる
- 最終データの後には何も付かない
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
array:3 [▼ 0 => array:3 [▼ 0 => "東北支店" 1 => "宮城県仙台市" 2 => "022-111-1111" ] 1 => array:3 [▼ 0 => "関東支店" 1 => "埼玉県大宮市" 2 => "048-222-2222" ] 2 => array:3 [▼ 0 => "中部支店" 1 => "愛知県名古屋市" 2 => "052-333-3333" ] ] |