I've a csv file with the following structure:
a; b; c,c c; d
When I try to process it, it says offset 2 and 3 are undefined. Took me a while to realize it is caused by the , and have no idea how to solve this. If I remove the , everything runs fine.
Here's my processing function:
function process_csv($file) {
$file = fopen($file, "r");
$data = array();
while (!feof($file)) {
$csvdata = fgetcsv($file);
$data[] = explode(';', $csvdata[0]);
}
fclose($file);
return $data;
}
Tried fgetcsv($file); as fgetcsv($file, '"'); but didn't help.
Your problem is, that fgetcsv uses , as delimiter by default. If you change it to ; you don't need to explode.
function process_csv($file) {
$file = fopen($file, "r");
$data = array();
while (!feof($file)) {
$data[] = fgetcsv($file, null, ';');
}
fclose($file);
return $data;
}
Related
$my_content = "This is the first line\n
This is the second line\n
This is the third line\n";
$my_filename = "save.txt";
function file_writer(string $file_to_write, string $content_to_write){
$file = fopen($file_to_write, "w") or die("Unable to open file");
file_put_contents($file_to_write, $content_to_write);
fclose($file);
}
file_writer($my_filename, $my_content);
function file_reader(string $file_to_read, int $num_lines) {
$file = fopen($file_to_read, "r");
while(! feof($file))
{
$line = fgets($file);
echo $line;
}
}
**file_reader($my_filename, 3);**
Try this:
function file_reader(string $file_to_read, int $num_lines) {
$file = fopen($file_to_read, "r");
$c = 0;
while(! feof($file) && $c != $num_lines)
{
$c = $c+1;
$line = fgets($file);
echo $line;
}
}
Your other problem is that you have newlines after newlines.
$my_content = "This is the first line\nThis is the second line\nThis is the third line\n";
function file_reader(string $file_to_read, int $num_lines) {
$file = fopen($file_to_read, "r");
$currLineNo = 1;
while(!feof($file) && (currLineNo < $num_lines))
{
$line = fgets($file);
echo $line;
$currLineNo += 1;
}
}
Havent tried the code myself. This is roughly way you can stop the loop at arbitrary line number.
I want to write a function as a lot of this code is repeated but I am having trouble passing the name of the file and the mode as a parameter to the function.
name = array();
dob = array();
address = array();
data = array();
#get name data
$handle = fopen('data/name.txt', 'r');
while (!feof($handle)) {
$data = explode(':',fgets($handle, 1024));
$name[] = $data[1];
}
fclose($handle);
#get dob data
$handle = fopen('data/dob.txt', 'r');
while (!feof($handle)) {
$data = explode(':',fgets($handle, 1024));
$dob[] = $data[1];
}
fclose($handle);
#get address data
$handle = fopen('data/address.txt', 'r');
while (!feof($handle)) {
$data = explode(':',fgets($handle, 1024));
$address[] = $data[1];
}
fclose($handle);
This is what I've written so far as a function.
function get_data($file, $mode, $array) {
$handle = fopen("'" . $file . "'", "'" . $mode . "'");
while (!feof($handle)) {
$data = explode(':',fgets($handle, 1024));
$array[] = $data[0];
}
So I want to be able to call the function on each file, such as;
get_data ('data/name.txt' , 'r', $name);
Your function is almost correct :) Just two mistakes
You didn't call fclose() inside your function
You tried to enclose a string twice, where one is enough
function get_data($file, $mode, $array) {
$handle = fopen("'" . $file . "'", "'" . $mode . "'");
# /\ these /\ and these are unnecessary
while (!feof($handle)) {
$data = explode(':',fgets($handle, 1024));
$array[] = $data[0];
}
Just calling fopen($file, $mode) is ok :)
If you would like to use your $array variable outside of your function, please remember to return it. If you add return $array; to the end of your function, you will be able to go:
$result = get_data('file.txt', 'r');
PS: There is already a similar function in PHP, file_get_contents(), perhaps you could use it? :)
To parse CSV files in php im using this function:
private function _csvToArray($url, $delimiter=',')
{
$csvData = file_get_contents($url);
$lines = explode(PHP_EOL, $csvData);
$array = array();
foreach ($lines as $line) {
$array[] = str_getcsv($line, $delimiter);
}
return $array;
}
The problem here is Im using EOL to determine where a line ends, if the CSV file have any field with any end of line chars im getting errors.
Example:
Product_Name, "Description"
Product_Name, "Description"
Product_Name, "Description"
Product_Name, "Description"
This works ok, but if I have something like this:
Product_Name, "Description_line_1
Description_line_2"
Product_Name, "Description_line_1
Description_line_2"
Product_Name, "Description_line_1
Description_line_2"
The script will fail, is there any way I can improve the script in order to consider this or is better to use a regular expression to fix first the CSV before calling the sript?
If you want to save writing to a temporary file yourself you can use the memory stream.
private function _csvToArray($url, $delimiter=',')
{
$fp = fopen('php://memory', 'r+');
fwrite($fp, file_get_contents($url));
fseek($fp, 0);
$array = array();
while ($row = fgetcsv($fp, 0, $delimiter)) {
$array[] = $row;
}
fclose($fp);
return $array;
}
fgetcsv can handle EOL in fields if the field data is between enclosure characters.
private function _csvToArray($url, $delimiter=',', $enclosure='"')
{
$handle = fopen($url, 'r');
$array = array();
while($row = fgetcsv($handle, 0, $delimiter, $enclosure))
{
$array[] = $row;
}
fclose($handle);
return $array;
}
Something like this should work (havent properly tested the code):
$csv = array_map('str_getcsv', file($url), ',', '"');
I had an old code lying around which fixed this once for me... But remember... it's from way way back;
$url = 'file.csv';
$csv = array();
$csvContents = file_get_contents($url);
$lines = explode('"'."\n", trim($csvContents));
foreach($lines as $lineNumber => $line) {
$csv[$lineNumber] = array();
$fields = explode(',', $line);
foreach($fields as $field) {
$csv[$lineNumber][] = ltrim(rtrim($field, '"'), '"');
}
}
So after encountering the memory limits I copied the following code.
It worked great. My only issue now is in the context of processing a csv file, the structure limits based on the size of chunk, but this would mean it could cut a row mid way through.
What could I do to ensure when a chunk is made, that it ends up to the /n.
I'm interested to know what others do.
I changed the limit to based on a certain amount of lines to read instead of the size limit. Instead of using fread, i used fgets to get the whole line.
Once again, this is all derived from the code linked in the question.
<?php
function file_get_contents_chunked($file,$chunk_size,$callback)
{
try
{
$handle = fopen($file, "r");
$i = 0;
$x = 0;
$chunk = array();
while (!feof($handle)) {
while ($row = fgets($handle)) {
// can parse further $row by usingstr_getcsv
$x ++;
$chunk[] = $row;
if ($x == $chunk_size) {
call_user_func_array($callback, array($chunk, &$handle, $i));
unset($chunk);
$x = 0;
}
}
}
fclose($handle);
}
catch(Exception $e)
{
trigger_error("file_get_contents_chunked::" . $e->getMessage(),E_USER_NOTICE);
return false;
}
return true;
}
?>
//Fixed for what I actually intended, limit by x amount of lines
You can first try setting the memory limit with :
ini_set('memory_limit', '32MB');
Then, to read a line at once :
$handle = fopen("inputfile.csv", "r");
if ($handle) {
while (($line = fgets($handle)) !== false) {
// process the line read.
}
} else {
// error opening the file.
}
fclose($handle);
Based on your code example, this would give :
function file_get_contents_chunked($file,$chunk_size,$callback)
{
$handle = fopen($file, "r");
$i = 0;
if ($handle) {
while (($line = fgets($handle)) !== false) {
call_user_func_array($callback,array($line,&$handle,$i));
$i++;
}
} else {
return false;
}
fclose($handle);
return true;
}
Note that $chunk_size parameter is not needed anymore... so you can remove it if you want.
You can also use this function to read a sav file line by line :
fgetcsv(file,length,separator,enclosure);
Example 1
<?php
$file = fopen("contacts.csv","r");
print_r(fgetcsv($file));
fclose($file);
?>
The CSV file:
Kai Jim, Refsnes, Stavanger, Norway
Hege, Refsnes, Stavanger, Norway
The output of the code above will be:
Array
(
[0] => Kai Jim
[1] => Refsnes
[2] => Stavanger
[3] => Norway
)
I have a text file here which I need to be able to convert into rows to extract the second, third, fourth, and fifth values from.
The first 7 values of each row are tab delimited, then there is a newline, then the final three values are tab delimited.
I removed the interrupting newlines so that each row is fully tab delimited.
<?php
$file="140724.txt";
$fopen = fopen($file, "r");
$fread = fread($fopen,filesize("$file"));
fclose($fopen);
$remove = "\n";
split = explode($remove, $fread);
foreach ($split as $string)
{
echo "$string<br><br>";
}
?>
Which produces this.
I'm not sure where to progress from this point. I'm teaching myself PHP and am still quite new to it, so I don't even know if where I've started from is a good place. My instinct is to write the previous output to a new textfile, then create another block of code similar to the first but exploding based on tabs, this time.
Help?
You can process this file in one go like this:
<?php
$file="140724.txt";
$fopen = fopen($file, 'r');
$fread = fread($fopen,filesize($file));
fclose($fopen);
$remove = "\n";
$split = explode($remove, $fread);
$array[] = null;
$tab = "\t";
foreach ($split as $string)
{
$row = explode($tab, $string);
array_push($array,$row);
}
echo "<pre>";
print_r($array);
echo "</pre>";
?>
The result will be a jagged array:
You will need to clean up the 1st and the last element.
That is structured data, delimited by tabs. You can use fgetcsv() to read that data into an array. For an example see the PHP documentation.
<?php
$myfile = fopen("test.txt", "r") or die("Unable to open file!");
// Output one line until end-of-file
while(!feof($myfile)) {
$text[] = fgets($myfile);
}
fclose($myfile);
print_r($text);
?>
There is another answer here which converts file/raw strings into an associative array. It is really very handy in such cases.
function tab_to_array($src='', $delimiter=',', $is_file = true)
{
if($is_file && (!file_exists($src) || !is_readable($src)))
return FALSE;
$header = NULL;
$data = array();
if($is_file){
if (($handle = fopen($src, 'r')) !== FALSE)
{
while (($row = fgetcsv($handle, 1000, $delimiter)) !== FALSE)
{
if(!$header)
$header = $row;
else
$data[] = array_combine($header, $row);
}
fclose($handle);
}
}
else{
$strArr = explode("\n",$src);
foreach($strArr as $dataRow){
if($row = explode($delimiter,$dataRow))
{
if(!$header)
$header = $row;
else
$data[] = array_combine($header, $row);
}
}
}
return $data;
}
/**
* Example for file
*/
print_r(tab_to_array('example.csv'));
/**
* Example for raw string
*/
$str = "name number
Lorem 11
ipsum 22";
print_r(tab_to_array($str, "\t", false));