PHP - Convert Tab Delimited TXT file to CSV - php

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

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);

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

Converting TAB Delimited to CSV

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);
}

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.

Add a new line to a CSV file

If I have a CSV saved on a server, how can I use PHP to write a given line, say 142,fred,elephants to the bottom of it?
Open the CSV file for appending (fopen­Docs):
$handle = fopen("test.csv", "a");
Then add your line (fputcsv­Docs):
fputcsv($handle, $line); # $line is an array of strings (array|string[])
Then close the handle (fclose­Docs):
fclose($handle);
You can use an object oriented interface class for a file - SplFileObject http://php.net/manual/en/splfileobject.fputcsv.php (PHP 5 >= 5.4.0)
$file = new SplFileObject('file.csv', 'a');
$file->fputcsv(array('aaa', 'bbb', 'ccc', 'dddd'));
$file = null;
This solution works for me:
<?php
$list = array
(
'Peter,Griffin,Oslo,Norway',
'Glenn,Quagmire,Oslo,Norway',
);
$file = fopen('contacts.csv','a'); // 'a' for append to file - created if doesn't exit
foreach ($list as $line)
{
fputcsv($file,explode(',',$line));
}
fclose($file);
?>
Ref: https://www.w3schools.com/php/func_filesystem_fputcsv.asp
If you want each split file to retain the headers of the original; this is the modified version of hakre's answer:
$inputFile = './users.csv'; // the source file to split
$outputFile = 'users_split'; // this will be appended with a number and .csv e.g. users_split1.csv
$splitSize = 10; // how many rows per split file you want
$in = fopen($inputFile, 'r');
$headers = fgets($in); // get the headers of the original file for insert into split files
// No need to touch below this line..
$rowCount = 0;
$fileCount = 1;
while (!feof($in)) {
if (($rowCount % $splitSize) == 0) {
if ($rowCount > 0) {
fclose($out);
}
$out = fopen($outputFile . $fileCount++ . '.csv', 'w');
fputcsv($out, explode(',', $headers));
}
$data = fgetcsv($in);
if ($data)
fputcsv($out, $data);
$rowCount++;
}
fclose($out);

Categories