Converting TAB Delimited to CSV - php

I'm currently opening a TAB delimited file with the following code...
if (($handle = fopen($filetxt, "r")) !== FALSE) {
while (($data = fgetcsv($handle, 0, "\t")) !== FALSE) {
// var_dump($data);
$num = count($data);
echo "<br>\n";
$row++;
for ($c=0; $c < $num; $c++) {
echo $data[$c] . "<br />\n";
}
}
fclose($handle);
}
Now I'm just trying to figure out how I can put the data into a CSV using fputcsv. An example would be great -- right now I'm just trying to get the headers into a CSV and then I can go from there.
The data right now (that's being echoed) looked like this...
part_number
aaia_part_term_id
short_description
bullet_points
list_price
jobber_price
base_price
epc_code
length
width
height
weight
image_name
If I could just figure out how to echo only the header into the CSV, I think I can figure out the rest.

fopen only gives you a handle to the file. A csv file's formatting relies going through each line, the way you are reading the file uses all contents at once, try:
<?PHP
if($handle = fopen($filetext, "r") !== FALSE){
while (!feof($handle)) {
$line_of_text = fgets($handle);
foreach( fgetcsv($line_of_text, 0, "\t") as $csv_item)
print $csv_item."," ;
print "<br>";
}
fclose($handle);
}
?>
I haven't tested this

Since a CSV file is just a comma delimited data file, it might be simpler just to read the current tab-delimited file line by line, and replace tabs with commas
if (($handle = #fopen($filetxt, "r")) !== false) {
while (($line = fgets($handle, 0)) !== false) {
$csv_line = str_replace("\t", ",", $line);
// write $csv_line to your csv file
}
fclose($handle);
}

Related

How to remove specific line from CSV file by its line number?

I'm trying to delete one line from CSV file by its line number, which I get as a parameter in URL.
I saw some discussions here, but it was mainly "delete a line by its id stored in first column" and so on. I tried to make it in the same way as others in these discussions, but it does not work. I only changed the condition.
if (isset($_GET['remove']))
{
$RowNo = $_GET['remove']; //getting row number
$row = 1;
if (($handle = fopen($FileName, "w+")) !== FALSE)
{
while (($data = fgetcsv($handle, 1000, ";")) !== FALSE)
{
//Here, I don't understand, why this condition does not work.
if ($row != $RowNo)
{
fputcsv($handle, $data, ';');
}
$row++;
}
fclose($handle);
}
}
I supposed, that it should work for me too, BCS just condition was changed. But it does not. It clears the whole file. Could you help me with it, please?
Thank you very much for any advice. Daniel.
You could load the file as an array of lines by using file().
Then remove the line and write the file back.
// read the file into an array
$fileAsArray = file($FileName);
// the line to delete is the line number minus 1, because arrays begin at zero
$lineToDelete = $_GET['remove'] - 1;
// check if the line to delete is greater than the length of the file
if ($lineToDelete > sizeof($fileAsArray)) {
throw new Exception("Given line number was not found in file.");
}
//remove the line
unset($fileAsArray[$lineToDelete]);
// open the file for reading
if (!is_writable($fileName) || !$fp = fopen($fileName, 'w+')) {
// print an error
throw new Exception("Cannot open file ($fileName)");
}
// if $fp is valid
if ($fp) {
// write the array to the file
foreach ($fileAsArray as $line) {
fwrite($fp, $line);
}
// close the file
fclose($fp);
}
If you have a unix system you could also use sed command:
exec("sed -e '{$lineToDelete}d' {$FileName}");
Remember cleaning command parameters if user input used:
https://www.php.net/manual/de/function.escapeshellcmd.php
Option if your CSV can fit to memory:
// Read CSV to memory array
$lines = file($fileName, FILE_SKIP_EMPTY_LINES | FILE_IGNORE_NEW_LINES);
// Remove element from array
unset($lines[$rowNo - 1]); // Validate that element exists!
// Rewrite your CSV file
$handle = fopen($fileName, "w+");
for ($i = 0; $i < count($lines); $i++) {
fputcsv($handle, $data, ';');
}
fclose($handle);
Option if your CSV can not fit to memory:
Use code from question, just write to separate file and later replace it with actual file:
$handle = fopen($FileName, "r");
// Read file wile not End-Of-File
while (!feof($fn)) {
if ($row != $RowNo) {
file_put_contents($FileName . '.tmp', fgets($fn), FILE_APPEND);
}
$row++;
}
fclose($handle);
// Remove old file and rename .tmp to previously removed file
unlink($FileName);
rename($FileName . '.tmp', $FileName);

PHP - Convert Tab Delimited TXT file to CSV

I'm trying to convert a tab delimited .txt file into a .csv file.
I was able to use fgetcsv() to open the txt file and get the data for each line with the following code:
$handle = fopen("fileurl.com", "r");
$row = 1;
if (($handle = fopen("fileurl.com", "r")) !== FALSE) {
while (($data = fgetcsv($handle, 1000, "\t")) !== FALSE) {
$num = count($data);
echo "<p> $num fields in line $row: <br /></p>\n";
$row++;
for ($c=0; $c < $num; $c++) {
echo $data[$c] . "<br />\n";
}
print_r($data);
}
fclose($handle);
}
Now i just need to create a csv file from the data array. I've tried using fputcsv(), but haven't had any luck. I've tried something like this, but the csv file it creates isn't correct and only has 1 row:
$fp = fopen('file.csv', 'w');
fputcsv($fp, $data, "\t");
fclose($fp);
An example of how to create a .csv file from the $data array would be great. I've spent a lot of time researching and trying to get this figured out, but haven't been able to get it working.
fputcsv() only writes one line at a time. Not the whole file. You you need to loop through $data in order to add all of that data into your CSV file.
$fp = fopen('file.csv', 'w');
foreach ($data as $line) {
fputcsv($fp, $line);
}
fclose($fp);
A full example using your code:
$handle = fopen("fileurl.com", "r");
$lines = [];
if (($handle = fopen("fileurl.com", "r")) !== FALSE) {
while (($data = fgetcsv($handle, 1000, "\t")) !== FALSE) {
$lines[] = $data;
}
fclose($handle);
}
$fp = fopen('file.csv', 'w');
foreach ($lines as $line) {
fputcsv($fp, $line);
}
fclose($fp);
This is the correct way to write data into csv file
<?php
$list = array (
array('aaa', 'bbb', 'ccc', 'dddd'),
array('123', '456', '789'),
array('"aaa"', '"bbb"')
);
$fp = fopen('file.csv', 'w');
foreach ($list as $fields) {
fputcsv($fp, $fields);
}
fclose($fp);
?>
In fputcsv we use second parameter as an array .
along with it $attachment = mb_convert_encoding($attachment, 'UTF-8', $parts[$i]->parameters[0]->value); also needed for tsv to csv. it will change file type to text/plain

Read CVS file and ouput the CSV file to .txt file

Hi here I am reading a CSV file and I am trying to write the CSV file data into a .txt file.
$row = 1;
if (($handle = fopen("data.csv", "r")) !== FALSE) {
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
$num = count($data);
echo "<p> $num fields in line $row: <br /></p>\n";
$row++;
for ($c=0; $c < $num; $c++) {
$myfile = fopen("newfile.txt", "w") or die ("unable to open file");
fwrite($myfile, $data[$c]);
}
}
fclose($handle);
}
The newfile.txt are being created and only the last record in the CSV file are showing in the newfile.txt. Can anyone tell me why everything in the CSV are not showing in my newfile.txt(only the last record are displaying). Thank You
You only need to open the new file once.
$row = 1;
if (($handle = fopen("data.csv", "r")) && $myfile = fopen("newfile.txt", "w")) {
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
$num = count($data);
echo "<p> $num fields in line $row: <br /></p>\n";
$row++;
fputcsv($myfile, $data);
}
fclose($handle);
fclose($myfile);
}
Open your file with a+ parameter instead of w for fopen.
From the doc, the mode 'w' opens for writing only, while the mode 'a+' opens for reading and writing and place the file pointer at the end of the file. If the file does not exist, it attempts to create it.
$row = 1;
if (($handle = fopen("data.csv", "r")) !== FALSE) {
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
$num = count($data);
echo "<p> $num fields in line $row: <br /></p>\n";
$row++;
for ($c=0; $c < $num; $c++) {
$myfile = fopen("newfile.txt", "a+") or die ("unable to open file");
fwrite($myfile, $data[$c]);
}
}
fclose($handle);
}
You are opening the file on every loop iteration which not a good idea try putting it above the loop
Use a+ mode instead of w in the fopen reference
this is probably because you reopen your textfile everytime you write a record and overwrite its content. Either open the file in append mode (can't tell you how, I am not a php programmer) or open your textfile only once and write several times in one session.
Edit: You should use 'a' or 'a+' instead of 'w' as parameter for fopen as explained here: http://php.net/manual/en/function.fopen.php

merger the csv data with php?

There are many CSV file like the following:a.csv, b.csv, aab.csv etc.
They hold the same column and header. Now I want to put all the csv data into whole.csv. With only one header. How can I do it?
a.csv data:
header1 title post.....
test who posand
b.csv data:
header1 title post.....
head she pnow
etc .....
The whole.csv will contain all the csv data.
eg:
header1 title post.....
head she pnow
test who posand
I tried the following code.but not get I want to:
$csvs = glob("*.csv");
foreach($csvs as $csv) {
$row = 1;
if (($handle = fopen($csv, "r")) !== FALSE) {
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
$fp = fopen("whole.csv", 'w');
fputcsv($fp, $data);
$row++;
}
fclose($handle);
}
}
I have put all CSV files in the same directory.
For every input csv file you are opening the resultant csv file in write mode:
$fp = fopen("whole.csv", 'w');
which wipes the content of the whole.csv!!
You need to open the whole.csv file just once outside the loop and keep writing into it.
$csvs = glob("*.csv");
$fp = fopen("whole.csv", 'w');
foreach($csvs as $csv) {
$row = 1;
if (($handle = fopen($csv, "r")) !== FALSE) {
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
fputcsv($fp, $data);
$row++;
}
fclose($handle);
}
}
Have a look at file_put_contents.
You would open each CSV file, then use file_put_contents passing whole.csv as the $filename parameter, the file handle as the $data parameter and use the FILE_APPEND flag to tell it to append the contents instead of overwriting.

CSV import via PHP

I'm importing a .CSV into an application with the following:
if (($handle = fopen($file, "r")) !== FALSE) {
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
$num = count($data);
echo "<p> $num fields in line $row: <br /></p>\n";
$row++;
for ($c=0; $c < $num; $c++) {
echo $data[$c] . "<br />\n";
}
}
fclose($handle);
}
It sort of works but it's far from perfect. I wanted to first get out the row heads and put them into an array and then loop round each row to get the data sets in.
It seems to be having delimitting problems as the first row (heads) are also including a few parts of the second row.
I exported the .csv file straight from Excel. Wonder if there are encoding tricks etc I might be missing.
It sounds like your 1000 limit is not long enough; you should set it to a high enough value for that file ... or set to 0 for unlimited (not recommended, because it tends to be slower).
Set it to 4096 or 8192 first and see how it goes.
// use 8kB buffer for reading comma delimited line
while (($data = fgetcsv($handle, 8192, ",")) !== FALSE) {
Update
Okay, on second thought, perhaps you should inspect the file and confirm a few things:
Are the delimiters really a comma? (I guess you've already established this)
Are the string enclosures always double quotes?
Are strings escaped with a backslash (default) or another double quote?
fgetcsv doesnt always properly detect line endings.
Try using before the fgetcsv call:
ini_set('auto_detect_line_endings', true);
I changed to 8192 and got same results
while (($data = fgetcsv($handle, 8192, ",")) !== FALSE) {
...
}
and then did this one and got same results
$handle = fopen($_FILES['filename']['tmp_name'], "r");
ini_set('auto_detect_line_endings', true);
while (($data = fgetcsv($handle, 8192, ",")) !== FALSE) {
$data = array_map('mysql_real_escape_string', $data);
Why are you not using file()?
$trimmed = file('somefile.txt', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);

Categories