I tried in several ways to create something efficient, however no way was able to validate everything, which ended up making me have to opt for while
even with fgets
(or fgetcsv
).
This format you want is basically CSV, however this file format is not something so advanced, it is impossible to limit the number of columns in a "practical" way, an example of checking would be this:
<?php
function validaCSV($arquivo, $limite = 3, $delimitador = ';', $tamanho = 0)
{
$handle = fopen($arquivo, 'rb');
$valido = true;
if ($handle) {
while (feof($handle) === false) {
$data = fgetcsv($handle, $tamanho, $delimitador);
if ($data && count($data) !== $limite) {
$valido = false; //Seta false
break;
}
}
fclose($handle);
} else {
$valido = true;
}
return $valido;
}
Example of use (the expected column pattern is 3
):
var_dump(validaCSV('arquivo.txt')); //Checa se todas linhas tem 3 colunas
var_dump(validaCSV('arquivo.txt', 5)); //Checa se todas linhas tem 5 colunas
Will return true
if valid, otherwise return false
If you want to read the file should it be valid, use it like this:
To avoid memory spikes chance the file is invalid, I created two whiles, it is a little slower but will not consume both the server (in case of invalid files)
Note: in the example I used yield
so you can use inside a while
your own
function lerCSV($arquivo, $limite = 3, $delimitador = ';', $tamanho = 0)
{
$handle = fopen($arquivo, 'rb');
if ($handle) {
while (feof($handle) === false) {
$data = fgetcsv($handle, $tamanho, $delimitador);
if ($data && count($data) !== $limite) {
throw new Exception('O numero de colunas excedeu o limite de ' . $limite);
}
}
//Volta o ponteiro para o inicio do arquivo para poder usar novamente o while
rewind($handle);
while (feof($handle) === false) {
$data = fgetcsv($handle, $tamanho, $delimitador);
if ($data) { //Impede linhas vazias de retornarem false como valor
yield $data;
}
}
fclose($handle);
} else {
throw new Exception('Arquivo inválido: ' . $arquivo);
}
}
Example of use:
foreach(lerCSV('a.csv') as $linha) {
var_dump($linha);
}
Will issue Exception if the file is invalid/non-existent or if the line number is not the one determined in the function (default is 3
)
Extra (with SplFileObject
)
I was wondering about the file situation being open in case the yield
, because if there is a break;
in the foreach
may occur of file not being closed, however the SplFileObject
closes the file when class is "destroyed" (will occur __destruct
(internal) class), then at this time the file will be "released", as explained in this question:
The version with SPL was like this:
<?php
function SplLerCSV($arquivo, $limite = 3, $delimiter = ';', $enclosure = '"', $escape = '\\')
{
$file = new SplFileObject($arquivo);
$minCol = $limite - 1;
while ($file->eof() === false) {
$data = $file->fgetcsv($delimiter, $enclosure, $escape);
if (isset($data[$minCol]) && count($data) !== $limite) {
throw new Exception('O numero de colunas excedeu o limite de ' . $limite);
}
}
//Volta o ponteiro para o inicio do arquivo para poder usar novamente o while
$file->rewind();
while ($file->eof() === false) {
$data = $file->fgetcsv($delimiter, $enclosure, $escape);
if (isset($data[$minCol])) { //Impede linhas vazias de retornarem [ 0 => NULL ] como valor
yield $data;
}
}
}
//Usando
foreach (SplLerCSV('a.csv') as $value) {
var_dump($value);
}
You want to check the number of columns, is that it? For example, limit to 3, if all rows have 3, then it is valid, otherwise it is invalid
– Guilherme Nascimento
@Guilhermenascimento especially this ... at the time of uploading I need to check if the file respects that condition ( three columns ), neither more nor less !
– PululuK
But this upload is done via direct FTP or with PHP?
– Woss