I am converting a Delimited FLAT file to CSV and it has some data which as comma in between them. For eg the product name Iphone 6splus, 32 gb. Since this a description of the product and can have special characters also. How do i escape the comma as because of this fputcsv is considering this data as a new line. which is wrong. I am using
$handle = fopen("data.txt", "r");
$lines = [];
$row_count=0;
if (($handle = fopen("data.txt", "r")) !== FALSE) {
while (($data = fgetcsv($handle, 1000, "\t")) !== FALSE) {
if($row_count>0)
{
$lines[] = $data;
}
$row_count++;
}
fclose($handle);
}
$fp = fopen('example.csv', 'w');
foreach ($lines as $line) {
fputcsv($fp, split('\*\*', $line));
}
fclose($fp);
I need to escape the value before i start converting the data and store into csv
Enclose the field in quotes, e.g.
field1_value,field2_value,"field 3,value",field4, etc...
To encode a quote, use ", a single quote symbol in a field will be encoded as "", and the whole field will become """". So if you see the following in e.g. Excel:
---------------------------------------
| regular_value |,,,"| ,"", |""" |"|
---------------------------------------
the CSV file will contain:
regular_value,",,,""",","""",","""""""",""""
A comma is simply encapsulated using quotes, so , becomes ",".
A command and quote needs to be encapsulated and quoted, so "," becomes """,""".
Related
I want to use different delimiters while generating CSV. When I try comma then it works fine means all values show in different columns but when I try other delimiters like ; or | then it shows all values in one column. Following code is showing all column's data in one column.
$csv_filename = $this->saveFileToDirectory.$this->fileName;
$fp = fopen ($csv_filename, "w");
fputcsv($fp, $this->headerArr);
foreach ($this->data as $key => $value) {
if(is_array($value)) {
$csvData = $this->makeStringFromArr($value);
fputcsv($fp, explode(";",$csvData),";");
}
}
fclose($fp);
$csvData value is following
"GUARANTEED AVAILABILITY;GUARANTEED AVAILABILITY;GUARANTEED
AVAILABILITY;;my;GUARANTEED AVAILABILITY
;34.5;;BLUE;80463259;VERY_GOOD;H1078;N;sss;dummy value;GUARANTEED
AVAILABILITY;"14.50, 34.50Â ;°, ";GUARANTEED
AVAILABILITY;sdf"
If I replace following line then it does not show data in CSV
fputcsv($fp, $csvData,';');
Following is sample CSV
Any suggestion? What I am doing wrong or it is right and will be visible in one column when exported with other delimiters than comma?
Try this Code...
$file_handle = fopen('/var/www/demo.csv', 'w');
// save header for csv | if you want title for your column
// $header_title = ['column_1', 'column_2'];
// fputs($file_handle, implode(",", array_map("encodeFunc", $header_title)) . "\r\n");
$csv_data = ["valu1", "value12"];
fputs($file_handle, implode(",", array_map("encodeFunc", $csv_data)) . "\r\n");
fclose($file_handle);
function encodeFunc($value) {
///remove any ESCAPED double quotes within string.
$value = str_replace('\\"', '', $value);
//then force escape these same double quotes And Any UNESCAPED Ones.
$value = str_replace('"', '', $value);
//force wrap value in quotes and return
return '"' . $value . '"';
}
I want to split a TSV string. The structure is:
abc\tdef\tghi\tjklm
where \t is a tab character.
If I use preg_split to split such string $i
$field=preg_split("/\t/", $i);
$field[3] is jklm.
However, if I have another string
abc\tdef\t\t
$field[3] is not a valid index.
How can I force empty fields into $field, such that all $field arrays would have an equal number of indexes?
If your problem just for extracting Tab Separator Value data, you can use built
in php function (fgetcsv()). It is more stable than use our own function. Please try this
if (($handle = fopen("test.csv", "r")) !== FALSE) {
// extract csv using tab delimiter
while (($data = fgetcsv($handle, 1000, "\t")) !== FALSE) {
print_r($data);
}
fclose($handle);
}
Like this?
$str ="abc\tdef\t\t";
Var_dump(explode("\t", $str));
https://3v4l.org/7qOPJ
i have a small problem with my fwrite().
$txt=fopen("$directory","w");
if (($handle = fopen("$directory", "r")) !== FALSE) {
while (($data = fgetcsv($handle, 1000, ";")) !== FALSE) {
$num = count($data);
...
...
There are no problem if i write:
fwrite($txt, "Hello;");
fwrite($txt, "Test fwrite;");
The output in the .csv file is like this:
Hello | Test fwrite
The problem appears when I have a variable contains the delimiter character, but I do not want fwrite consider it as a delimiter.
I have try to use chr(59), but the problem is not solved.
For example:
$var = "hello;test;hello;";
fwrite($txt, "Test fwrite;");
fwrite($txt, "$var;");
fwrite($txt, "Hello;");
The output of i would like to have is:
Test fwrite | hello;test;hello | Hello
Is possible do this without change the character delimiter ( ; )??
Thanks!
Easier done via fputcsv.
If your field contains the delimeter character you have to enclose the value (by default with double quotes).
e.g.
"abc;def";"x";"y";"z"
I'm importing a CSV using the fgetcsv() function, which is working all good.
However, when I take a look at the data in the database, I see black diamonds with question marks. This isn't too much of an issue when echoing the data back out again, as they don't appear, but when I want to use one of the CSV fields as a MySQL date, it isn't recognised as a date and is stored as 0000-00-00.
e.g.
I think this issue is something to do with encoding of the CSV? Can anyone offer any advice?
Thanks!
Edit: if it helps here is my import script, and the encode type is ASCII according to mb_detect_encoding
<?php
include 'config.php';
include 'opendb.php';
ini_set("auto_detect_line_endings", true);
$row = 0;
$tmpName = $_FILES['csv']['tmp_name'];
if (($handle = fopen($tmpName, "r")) !== FALSE) {
$num = count($data);
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE)
{
$noQuotes = str_replace("\"", '', $data);
$originalDate = $noQuotes[1];
//$delivery_date = date('Y-m-d', strtotime($originalDate));
$parts = explode('/', $originalDate);
$delivery_date = $parts[2] . '-' . $parts[1] . '-' . $parts[0];
$row++;
$import="INSERT into dispatch (delivery_note_number, delivery_date, dispatch_date, customer_delivery_date, delivery_line, produce, variety, quantity, pallets, count, depot, customer, grower, haulier, status)
values ('$noQuotes[0]', '$delivery_date', '$noQuotes[2]', '$noQuotes[3]', '$noQuotes[4]', '$noQuotes[5]', '$noQuotes[6]', '$noQuotes[7]', '$noQuotes[8]', '$noQuotes[9]', '$noQuotes[10]', '$noQuotes[11]', '$noQuotes[12]', '$noQuotes[13]', '$noQuotes[14]')";
echo $import;
mysql_query($import) or die(mysql_error());
}
//header("location:list_dispatch.php?st=recordsadded");
fclose($handle);
}
?>
If your database is using a different character encoding than the CSV file, it is possible the data should converted first.
One way to perform this is using the mb_convert_encoding() function.
Also useful, mb_detect_encoding() should be able to detect the character encoding for a given input string.
Someone found a solution on a another forum:
Those are NUL characters (ASCII code 0x00), replace them like this:
$string = str_replace(chr(0), '', $string);
fputcsv($f, $array, ' ', chr(0));
I was just about to ask the same questions as the question aksed here.... Forcing fputcsv to Use Enclosure For *all* Fields
The question was
When I use fputcsv to write out a line
to an open file handle, PHP will add
an enclosing character to any column
that it believes needs it, but will
leave other columns without the
enclosures.
For example, you might end up with a
line like this
11,"Bob ",Jenkins,"200 main st. USA
",etc
Short of appending a bogus space to
the end of every field, is there any
way to force fputcsv to always enclose
columns with the enclosure (defaults
to a ") character?
The answer was:
No, fputcsv() only encloses the field
under the following conditions
/* enclose a field that contains a delimiter, an enclosure character, or a newline */
if (FPUTCSV_FLD_CHK(delimiter) ||
FPUTCSV_FLD_CHK(enclosure) ||
FPUTCSV_FLD_CHK(escape_char) ||
FPUTCSV_FLD_CHK('\n') ||
FPUTCSV_FLD_CHK('\r') ||
FPUTCSV_FLD_CHK('\t') ||
FPUTCSV_FLD_CHK(' ')
)
There is no "always enclose" option.
I need to create a CSV file will every field enclosed... What would be the best solution?
Thanks in advance...
Roll your own function - its not hard:
function dumbcsv($file_handle, $data_array, $enclosure, $field_sep, $record_sep)
{
dumbescape(false, $enclosure);
$data_array=array_map('dumbescape',$data_array);
return fputs($file_handle,
$enclosure
. implode($enclosure . $field_sep . $enclosure, $data_array)
. $enclosure . $record_sep);
}
function dumbescape($in, $enclosure=false)
{
static $enc;
if ($enclosure===false) {
return str_replace($enc, '\\' . $enc, $in);
}
$enc=$enclosure;
}
(above is using unix style escaping)
C.
A workaround: Supposing you have your data in a 2-dimensional array, you can append a string that will force quoting and you are sure is not contained in your data ("## ##" here) and then remove it:
$fp = fopen($filename, 'w');
foreach ($data as $line => $row) {
foreach ($row as $key => $value) {
$row[$key] = $value."## ##";
}
fputcsv($fp, $row);
}
fclose($fp);
$contents = file_get_contents($filename);
$contents = str_replace("## ##", "", $contents);
file_put_contents($filename, $contents);
I have encountered the same problem, and I have solved it as follows.
I have inserted single quotes to each array value.
This way when you open the csv file with excel, the scientific notation E + 15 will no longer be displayed.
Here I share you as I did.
This worked for me, I hope you do too.
Regards
// this function add a single quote for each member of array
function insertquote($value) {
return "'$value'";
}
# here i send each value of array
# to a insertquote function, and returns an array with new values,
# with the single quote.
foreach ($list as $ferow) {
fputcsv($fp, array_map(insertquote, $ferrow), ';');
}