0

Why do I always get a array with one item of empty string for an empty .csv file?

$content = file('products.csv');

print_r($content);

result:

Array ( [0] => )

Can I return false so that I know there is nothing in the csv file?

Run
  • 54,938
  • 169
  • 450
  • 748
  • 2
    Try [`filesize()`](http://php.net/manual/en/function.filesize.php) - `if (filesize('products.csv') == 0)` – Funk Forty Niner Feb 27 '15 at 03:36
  • The [`file()`](http://php.net/file) function doesn't know CSV. There are options for skipping empty lines however. – mario Feb 27 '15 at 03:37
  • By adding some wrapping stuff... – sectus Feb 27 '15 at 03:37
  • You should also see http://stackoverflow.com/a/25638904/ - *"But even then, emptiness isn't an absolute, you might run into a fake-empty text-file which actually has a newline or a UTF-8 BOM."* - Not to mention some unicode characters which isn't mentioned in that Q&A. – Funk Forty Niner Feb 27 '15 at 03:43
  • 1
    You should use `fgetcsv()` to read CSV files instead of `file()`. – Ja͢ck Feb 27 '15 at 04:20

3 Answers3

4

This seems like ad-hoc behaviour particular to your taste (no problem with that at all). Which means, you should probably create a wrapper function for this.

function contentIsNotEmpty($content) {
   $isEmpty = empty($content) || (count($content) == 1 && empty($content[0]));
   return $isEmpty ? false : $content;
}

EDIT: Incorporated @scrowler's feedback, and Michael J. Mulligan's.

mcsilvio
  • 1,098
  • 1
  • 11
  • 20
  • 2
    Or better yet return false if its empty or return the contents if not e.g. `$contents = file($filename); return empty($contents) ? false : $contents;` – scrowler Feb 27 '15 at 03:43
  • Agreed. This is more in line with what the OP asked. – mcsilvio Feb 27 '15 at 03:43
  • @scrowler That will be invalid if the variable is an array with a single empty entry. The array is no longer empty due to the fact that it has an entry. http://ideone.com/uwnNHG – Mike Feb 27 '15 at 03:48
  • @MichaelJMulligan fair enough - `return (empty($contents) || empty($contents[key($contents)])) ? false : $contents;` – scrowler Feb 27 '15 at 08:46
  • @scrowler - What if only the first entry is empty, but there are 100 entries? – Mike Feb 27 '15 at 13:56
2

A single line test should get you the result:

$empty = empty($content) || (count($content) === 1 && empty($content[0]));

The following should avoid the "fake empty":

$empty = empty($content) || (count($content) === 1 && $content[0] === '');

If you need a re-usable function, and prefer, as you stated, to get an array or nothing, this may be helpful:

function get_file($file_name = null, $strict = false) {
    $return = null;
    if(!empty($file_name) && is_readable($file_name)) {
        $contents = file($file_name);
        if(
            !empty($contents)
            && (
                count($contents) > 1 
                || (
                    !empty($contents[0])
                    || ($strict && $contents[0] !== '')
                )
            )
        ) {
            $return = $contents;
        }
    }
    return $return;
}

I mean, we could get all kinds of creative and iterate over lines, etc. But I think you get the idea.

If you want to get a CSV file, I would suggest using a method like fgetcsv() (repurposed):

function getcsv($file_name, $headers = array(), $delimiter = ',', $enclosure = '"', $escape = "\\" ) {
    $contents = array();
    $get_headers = $headers === FALSE;
    $headers = is_array($headers) ? array_values($headers) : array();
    if(!empty($file_name) && is_readable($file_name)) {
        $row = 0;
        if (($handle = fopen($file_name, "r")) !== FALSE) {
            while (($data = fgetcsv($handle, 0, $delimiter, $enclosure, $escape)) !== FALSE) {
                if($get_headers && empty($headers)) {
                    $headers = $data;
                    continue;
                }
                foreach($data as $i => $col_value) {
                    $col_name = isset($headers[$i]) ? $headers[$i] : $i;
                    $contents[$row][$col_name] = $col_value;
                }
                $row++;
            }
            fclose($handle);
        }
    }

    return $contents;
}

Note, above is not tested, just a quick draft, and I am going to bed. I'll edit it tomorrow if need be.

Finally, if you are getting a single line, with white-space, and this validates as "empty" in your eyes, simple test it after a trim:

$empty_line = trim($content[$line_num]) == '';

Not sure what else to tell you. I think we have equipped you with quite a few tools and ways to validate this situation. Best of luck.

Mike
  • 1,968
  • 18
  • 35
  • thanks. but it does not work for me I'm afraid because for `var_dump($contentst[0]);` I always get `string ' ' (length=2)`... – Run Feb 27 '15 at 04:34
  • 1
    Added a check for white-space strings. – Mike Feb 27 '15 at 04:41
  • Only comment would be that you can only assume the first array key is going to be zero. `$contents[key($contents)]` would return the first entry in the array more safely – scrowler Feb 27 '15 at 08:47
  • It isn't an assumption, `file()` will only return an `array` with an index starting at 0, or `false`. – Mike Feb 27 '15 at 13:58
1

try this

$content = file('products.csv');
         if(!empty($content)){
          print_r();}{
        else{
           // Do something if no content
        }
Nooh
  • 1,548
  • 13
  • 21