P粉1186987402023-08-09 12:56:44
If the file you want to read is a "simple" file with just newlines as delimiters, reading from back to front will be quite simple. However, CSV is a more complex format, with field and row delimiters, quotation marks (quotes), and escape characters. You may encounter data such as
id,name,value 1,foo,"hello world" 2,bar,"hello world" 3, baz,"""hello world"""
This is a perfectly valid CSV, but most of the solutions currently proposed on forums will have problems reading the data in reverse.
The most reliable method is to first read the data from the beginning of the file, and then use this information to read the data in reverse direction. The simplest version is to just put everything into an array and then read the array in reverse, for example:
$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);
But if you are processing a large file, you may run into memory constraints as all the data needs to be stored.
An alternative is to read the file once, then store only the file offsets at the beginning of the record, and then iterate backwards again using those offsets.
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);
There is a trade-off that the file must be traversed twice, but if there are memory constraints, then this has to be done.
With all this said, a better option is to put the data in a database where the database can easily reorder the data if possible. This code already reimplements database-related functionality to some extent, but it's even worse.
P粉5133162212023-08-09 10:41:12
Alternatively, you can also use a for loop
<?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"; } ?>
This method should be faster than other methods based on the function array_reverse()