Rumah > Soal Jawab > teks badan
P粉1186987402023-08-09 12:56:44
Jika fail yang anda ingin baca ialah fail "mudah" dengan hanya baris baharu sebagai pembatas, membaca dari belakang ke hadapan akan menjadi agak mudah. Walau bagaimanapun, CSV ialah format yang lebih kompleks, dengan pembatas medan dan baris, tanda petikan (petikan) dan aksara melarikan diri. Anda mungkin menjumpai data seperti
id,name,value 1,foo,"hello world" 2,bar,"hello world" 3, baz,"""hello world"""
Ini adalah CSV yang sangat sah, tetapi kebanyakan penyelesaian yang dicadangkan pada masa ini di forum akan menghadapi masalah membaca data secara terbalik.
Kaedah yang paling boleh dipercayai adalah dengan terlebih dahulu membaca data dari permulaan fail dan kemudian menggunakan maklumat ini untuk membaca data secara terbalik. Versi paling mudah adalah dengan hanya meletakkan segala-galanya ke dalam tatasusunan dan kemudian membaca tatasusunan secara terbalik, seperti ini:
$f = fopen("./data/data-esp8266-$idluf-$currentdata.csv", "r"); fgets($f); $lines = []; while (($lines[] = fgetcsv($f)) !== false) {} for( $i=count($lines)-1; $i>=0; --$i ) { $line = lines[$i]; $row = $line[0]; // Dobbiamo ottenere la riga effettiva (è il primo elemento in un array di 1 elemento) $cells = explode(";",$row); echo "<tr>\n"; foreach ($cells as $cell) { echo "<td><a style='text-decoration:none;color:#fff;' class='tooltip' data-tool=' $cell'>" . htmlspecialchars($cell) . "</a></td>\n"; } echo "</tr>\n"; } fclose($f);
Tetapi jika anda berurusan dengan fail yang besar, anda mungkin menghadapi had memori kerana semua data perlu disimpan.
Alternatifnya ialah membaca fail sekali dan kemudian hanya menyimpan fail mengimbangi pada permulaan rekod dan kemudian melelang ke belakang sekali lagi menggunakan pengimbangan tersebut.
function csv_reverse($handle, ...$csv_options) { $offsets = []; do { $offsets[] = ftell($handle); } while($row = fgetcsv($handle, ...$csv_options)); array_pop($offsets); // last offset is EOF for( $i=count($offsets)-1; $i>=0; --$i ) { fseek($handle, $offsets[$i]); yield fgetcsv($handle, ...$csv_options); } } $f = fopen("./data/data-esp8266-$idluf-$currentdata.csv", "r"); fgets($f); // assuming that this discards the header row $lines = []; while (($lines[] = fgetcsv($f)) !== false) {} foreach( csv_reverse($f) as $line ) { // same as above } fclose($f);
Terdapat pertukaran bahawa fail perlu dilalui dua kali, tetapi jika terdapat kekangan memori, maka ini perlu dilakukan.
Dengan semua pepatah ini, pilihan yang lebih baik ialah meletakkan data dalam pangkalan data, di mana pangkalan data boleh menyusun semula data dengan mudah jika boleh. Kod ini sudah melaksanakan semula fungsi berkaitan pangkalan data sedikit sebanyak, tetapi ia lebih teruk.
P粉5133162212023-08-09 10:41:12
Sebagai alternatif, anda juga boleh menggunakan gelung for
<?php $lines = file("./data/data-esp8266-$idluf-$currentdata.csv", FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); // 将循环倒序遍历lines数组 for ($i = count($lines)-1; $i >= 0; $i--) { $row = $lines[$i]; $cells = explode(";", $row); echo "<tr>\n"; foreach ($cells as $cell) { echo "<td><a style='text-decoration:none;color:#fff;' class='tooltip' data-tool=' $cell'>" . htmlspecialchars($cell) . "</a></td>\n"; } echo "</tr>\n"; } ?>
Kaedah ini sepatutnya lebih pantas daripada kaedah lain berdasarkan array_reverse() fungsi