I am converting my space separated text using into a html table.
This is the code that I am using, but the output does not contain '|' which I can trying to use as a tab replacement.
function tabs_to_table($input) {
define('TAB_REPLACEMENT', "|");
define('NEWLINE_REPLACEMENT', "\n");
define('ROW_BEGIN', "");
define('TABLE_BEGIN', "\n");
define('TABLE_END', "\n");
$input = preg_replace("/\t/", TAB_REPLACEMENT , $input);
$rows = preg_split("/\r\n/", $input);
$output = "";
foreach ($rows as $index => $row) {
if (strlen($row) > 0) {
$output .= ROW_BEGIN . $row . NEWLINE_REPLACEMENT;
}
}
//build table
$input = TABLE_BEGIN . $output . TABLE_END;
return $input;
}
The output is
aggr0 367GB 350GB 17GB 95%
aggr0/.snapshot 0TB 0TB 0TB 0%
aggr1 1102GB 554GB 547GB 50%
aggr1/.snapshot 0TB 0TB 0TB 0%
but I want
aggr0 |367GB |350GB|17GB |95%
aggr0/.snapshot|0TB |0TB |0TB |0%
aggr1 |1102GB|554GB|547GB|50%
aggr1/.snapshot|0TB |0TB |0TB |0%
Can someone please point-out what I am doing wrong?
Thank you.
You need str_pad() function for this, look here for more info:
http://www.w3schools.com/php/func_string_str_pad.asp
Related
I'm having a small issue regarding a foreach() loop and writing an array to a text file within.
The loop gives me the format in the file that I want but it also adds (as I was told) an unwanted empty line at the end of the file.
Here is my piece of code:
foreach($data_arr as $data => $input)
{ fwrite($fh, $data . ":" . $input . "\n") or die("something went wrong here"); }
Is there a way to prevent this from happening and not add the \n when it reaches the end of the array?
You can do something like this :
$data_array = ['c', 'h', "hf"];
$last = count($data_array) - 1; #size of the array
foreach($data_array as $data => $input)
{
$separator = $data == $last ? "" : "\n"; #if is last, then seperator isn't a back to line
fwrite($fh, $data . ":" . $input . $separator);
}
Just check if current index is the last one, then eventually add "\n" to the string
$last_index = count($data_arr)-1;
foreach ($data_arr as $data => $input)
{
$string = $data . ":" . $input;
if ($data != $last_index)
{
$string .= "\n";
}
fwrite($fh, $string) or die("something went wrong here");
}
Determining whether you are doing something for the last time, is cumbersome - for starters, you need to count your items, and then you need a loop index to compare to that count …
Much easier to determine, whether you are doing something for the first time. So just reverse your logic here - do not try to output “all lines, followed by a newline each, except the last one”, but instead, output “all lines preceded by a newline each, except the first one.”
You could use a simple boolean flag for that:
$is_first_line = true;
foreach($data_arr as $data => $input) {
fwrite($fh, ($is_first_line ? "" : "\n") . $data . ":" . $input);
$is_first_line = false;
}
Or you just append a variable before the line data all the time - and simply make that variable “empty” on the first iteration, and then fill it with a newline character for all the following ones:
$prefix = "";
foreach($data_arr as $data => $input) {
fwrite($fh, $prefix . $data . ":" . $input);
$prefix = "\n";
}
I am writing the following code from a CSV to get stock data, When I have downloaded the string it is splitting it in the following way
<COMPANY NAME>,<STOCK PRICE>,<STOCK CHANGE>
<COMPANY2 NAME>,<STOCK PRICE2>,<STOCK CHANGE2>
I have tried to split the array by using the /n character using the PHP function explode. However this did not split it properly. Here is my code:
public function getQuotes()
{
$result = array();
$format = $this->format;
$stockString = "";
foreach ($this->stocks as $stock)
{
$stockString = $stockString . $stock . "+";
}
//Remove the last "+"
$stockString = substr($stockString,0,strlen($stockString)-1);
$s = file_get_contents("http://finance.yahoo.com/d/quotes.csv?s=". $stockString . "&f=" . $format . "&e=.csv");
//The splitting is to be done here.
}
}
Thank you in advance
Use file function instead of file_get_contents - it will split the content for you, as php manual says:
Returns the file in an array. Each element of the array corresponds to
a line in the file, with the newline still attached. Upon failure,
file() returns FALSE.
Then you can use str_getcsv for each element of array to get field values.
public function getQuotes()
{
$result = array();
$format = $this->format;
$stockString = "";
foreach ($this->stocks as $stock)
{
$stockString = $stockString . $stock . "+";
}
//Remove the last "+"
$stockString = substr($stockString,0,strlen($stockString)-1);
$s = file("http://finance.yahoo.com/d/quotes.csv?s=". $stockString . "&f=" . $format . "&e=.csv");
foreach($s as $line) {
$values = str_getcsv($line);
}
}
I would like to truncate a very long string, formatted via html elements.
I need the first 500 words (somehow I have to avoid html tags <p>, <br> while my function truncating the string), but in the result I have to keep/use those html elements because the result also should be formatted by html tags like the "original whole" text.
What's the best way to truncate my string?
Example:
Original text
> <p>The Huffington Post (via <a
> href="/t/daily-mail">Daily Mail</a>) is reporting that <a
> href="/t/misty">Misty</a> has been returned to a high kill shelter for
> farting too much! She appeared on Greenville County Pet Rescue’s
> “urgent” list, which means if she doesn’t get readopted, she will be
> euthanized!</p>
I need the first n words (n=10)
> <p>The Huffington Post (via <a
> href="/t/daily-mail">Daily Mail</a>) is reporting that.. </p>
A brute force method would be to just split all elements on blanks, then iterate over them. You count only non-tag elements up to a maximum, while you output tags nonetheless. Something along these lines:
$string = "your string here";
$output = "";
$count = 0;
$max = 10;
$tokens = preg_split('/ /', $string);
foreach ($tokens as $token)
{
if (preg_match('/<.*?>/', $token)) {
$output .= "$token ";
} else if ($count < $max) {
$output .= "$token ";
$count += 1;
}
}
print $output;
You could have found something like this with some Googling.
// Original PHP code by Chirp Internet: www.chirp.com.au
// Please acknowledge use of this code by including this header.
function restoreTags($input)
{
$opened = array();
// loop through opened and closed tags in order
if(preg_match_all("/<(\/?[a-z]+)>?/i", $input, $matches)) {
foreach($matches[1] as $tag) {
if(preg_match("/^[a-z]+$/i", $tag, $regs)) {
// a tag has been opened
if(strtolower($regs[0]) != 'br') $opened[] = $regs[0];
} elseif(preg_match("/^\/([a-z]+)$/i", $tag, $regs)) {
// a tag has been closed
unset($opened[array_pop(array_keys($opened, $regs[1]))]);
}
}
}
// close tags that are still open
if($opened) {
$tagstoclose = array_reverse($opened);
foreach($tagstoclose as $tag) $input .= "</$tag>";
}
return $input;
}
When you combine it with another function mentioned in the article:
function truncateWords($input, $numwords, $padding="")
{
$output = strtok($input, " \n");
while(--$numwords > 0) $output .= " " . strtok(" \n");
if($output != $input) $output .= $padding;
return $output;
}
Then you can just achieve what you're looking for by doing this:
$originalText = '...'; // some original text in HTML format
$output = truncateWords($originalText, 500); // This truncates to 500 words (ish...)
$output = restoreTags($output); // This fixes any open tags
I need to convert a CSV file to JSON on the server using PHP. I am using this script which works:
function csvToJSON($csv) {
$rows = explode("\n", $csv);
$i = 0;
$len = count($rows);
$json = "{\n" . ' "data" : [';
foreach ($rows as $row) {
$cols = explode(',', $row);
$json .= "\n {\n";
$json .= ' "var0" : "' . $cols[0] . "\",\n";
$json .= ' "var1" : "' . $cols[1] . "\",\n";
$json .= ' "var2" : "' . $cols[2] . "\",\n";
$json .= ' "var3" : "' . $cols[3] . "\",\n";
$json .= ' "var4" : "' . $cols[4] . "\",\n";
$json .= ' "var5" : "' . $cols[5] . "\",\n";
$json .= ' "var6" : "' . $cols[6] . "\",\n";
$json .= ' "var7" : "' . $cols[7] . "\",\n";
$json .= ' "var8" : "' . $cols[8] . "\",\n";
$json .= ' "var9" : "' . $cols[9] . "\",\n";
$json .= ' "var10" : "' . $cols[10] . '"';
$json .= "\n }";
if ($i !== $len - 1) {
$json .= ',';
}
$i++;
}
$json .= "\n ]\n}";
return $json;
}
$json = csvToJSON($csv);
$json = preg_replace('/[ \n]/', '', $json);
header('Content-Type: text/plain');
header('Cache-Control: no-cache');
echo $json;
The $csv variable is a string resulting from a cURL request which returns the CSV content.
I am sure this is not the most efficient PHP code to do it because I am a beginner developer and my knowledge of PHP is low. Is there a better, more efficient way to convert CSV to JSON using PHP?
Thanks in advance.
Note. I am aware that I am adding whitespace and then removing it, I do this so I can have the option to return "readable" JSON by removing the line $json = preg_replace('/[ \n]/', '', $json); for testing purposes.
Edit. Thanks for your replies, based on them the new code is like this:
function csvToJson($csv) {
$rows = explode("\n", trim($csv));
$csvarr = array_map(function ($row) {
$keys = array('var0','var1','var2','var3','var4','var5','var6','var7','var8','var9','var10');
return array_combine($keys, str_getcsv($row));
}, $rows);
$json = json_encode($csvarr);
return $json;
}
$json = csvToJson($csv);
header('Content-Type: application/json');
header('Cache-Control: no-cache');
echo $json;
Well there is the json_encode() function, which you should use rather than building up the JSON output yourself. And there is also a function str_getcsv() for parsing CSV:
$array = array_map("str_getcsv", explode("\n", $csv));
print json_encode($array);
You must however adapt the $array if you want the JSON output to hold named fields.
I modified the answer in the question to use the first line of the CSV for the array keys. This has the advantage of not having to hard-code the keys in the function allowing it to work for any CSV with column headers and any number of columns.
Here is my modified version:
function csvToJson($csv) {
$rows = explode("\n", trim($csv));
$data = array_slice($rows, 1);
$keys = array_fill(0, count($data), $rows[0]);
$json = array_map(function ($row, $key) {
return array_combine(str_getcsv($key), str_getcsv($row));
}, $data, $keys);
return json_encode($json);
}
None of these answers work with multiline cells, because they all assume a row ends with '\n'. The builtin fgetcsv function understands that multiline cells are enclosed in " so it doesn't run into the same problem. The code below instead of relying on '\n' to find each row of a csv lets fgetcsv go row by row and prep our output.
function csv_to_json($file){
$columns = fgetcsv($file); // first lets get the keys.
$output = array(); // we will build out an array of arrays here.
while(!feof($file)){ // until we get to the end of file, we'll pull in a new line
$line = fgetcsv($file); // gets the next line
$lineObject = array(); // we build out each line with our $columns keys
foreach($columns as $key => $value){
$lineObject[$value] = $line[$key];
}
array_push($output, $lineObject);
}
return json_encode($output); // encode it as json before sending it back
}
Some tips...
If you have URL opening enabled for fopen() and wrappers, you can use fgetscsv().
You can build an array of the CSV, and then convert it with PHP's native json_encode().
The correct mime type for JSON is application/json.
You could probably reduce the overhead by removing all the spaces and \n's. But that's in your note.
You could increase the performance by skipping the preg_replace and passing a boolean that would turn it on and off.
Other than that, the variable unrolling of your var[1-10] actually is good, as long as there are always ten varaibles.
The explode and the foreach approach are just fine.
I recommend using Coseva (a csv parsing library) and using the built in toJSON() method.
<?php
// load
require('../src/CSV.php');
// read
$csv = new Coseva\CSV('path/to/my_csv.csv');
// parse
$csv->parse();
// disco
echo $csv->toJSON();
I'm trying to remove some excessive indention from a string, in this case it's SQL, so it can be put into a log file. So I need the find the smallest amount of indention (aka tabs) and remove it from the front of each line, but the following code ends up printing out exactly the same, any ideas?
In other words, I want to take the following (NOTE: StackOverflow editor converted my tabs to spaces, in the code, a tab simulates 4 spaces, but it really is a \t character)
SELECT
blah
FROM
table
WHERE
id=1
and convert it to
SELECT
blah
FROM
table
WHERE
id=1
here's the code I tried and fails
$sql = '
SELECT
blah
FROM
table
WHERE
id=1
';
// it's most likely idented SQL, remove any idention
$lines = explode("\n", $sql);
$space_count = array();
foreach ( $lines as $line )
{
preg_match('/^(\t+)/', $line, $matches);
$space_count[] = strlen($matches[0]);
}
$min_tab_count = min($space_count);
$place = 0;
foreach ( $lines as $line )
{
$lines[$place] = preg_replace('/^\t{'. $min_tab_count .'}/', '', $line);
$place++;
}
$sql = implode("\n", $lines);
print '<pre>'. $sql .'</pre>';
It seems the problem was
strlen($matches[0])
returns 0 and 1 for the first and last line, which isn't the 3 I actually wanted as the minimum, so a quick hack was to
trim the SQL
skip counting the length if it's less than 2
Not the most elegant solution, but it'll always work because tabs are usually in the 4+ count in this code. Here's the fixed code:
$sql = '
SELECT
blah
FROM
table
WHERE
id=1
';
// it's most likely idented SQL, remove any idention
$lines = explode("\n", $sql);
$space_count = array();
foreach ( $lines as $line )
{
preg_match('/^(\t+)/', $line, $matches);
if ( strlen($matches[0]) > 1 )
{
$space_count[] = strlen($matches[0]);
}
}
$min_tab_count = min($space_count);
$place = 0;
foreach ( $lines as $line )
{
$lines[$place] = preg_replace('/^\t{'. $min_tab_count .'}/', '', $line);
$place++;
}
$sql = implode("\n", $lines);
print $sql;
private function cleanIndentation($str) {
$content = '';
foreach(preg_split("/((\r?\n)|(\r\n?))/", trim($str)) as $line) {
$content .= " " . trim($line) . PHP_EOL;
}
return $content;
}