Parse CSV with PHP [duplicate] - php

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
how to extract data from csv file in php
i'm new on php and now i try to make a private site for me and read out some stock information over yahoo api
Link: finance.yahoo.com/d/quotes.csv?s=^GDAXI+^TECDAX+eurusd=x+gcf12.cmx+CLH12.NYM&f=nl1k2
The link works fine but now how can i read this file out? And echo the information on my page?
Output:
"DAX",6864.43,"+54.97 - +0.81%"
"TECDAX",775.33,"+3.78 - +0.49%"
"EUR to USD",1.3447,"N/A - 0.00%"
"Gold Jan 12",1731.80,"N/A - +0.32%"
"Crude Oil Mar 12",105.88,"N/A - +0.04%"
What i need:
echo $name;
echo $rate;
echo $change;
echo $changeinpercent;
I hope some one can help me, and sry for my bad english.
Greetings,
matthias

Have you tried looking at str_getcsv or fgetscsv?

If you are using PHP5.3 you can use str_getcsv although you will still need to parse the last string value as that contains two values you are looking for (hint: explode).
If you're not on PHP5.3, you should be able to use fgetcsv with a stream passed to it.

You could use RegEx to extract from each line the information you need. The following php code is what you need to extract this specific data. It's a RegEx code and you should use it with a preg_match function:
/\"([^\"]+)\",(\d+\.\d+),\"(N\/A)?([+-]?\d+\.?\d+)?\s+-\s+([+-]?\d+\.?\d+%?)/
It gives you an array, and you will use it as:
$match[0]
$match[1]
$match[2]
$match[3]
UPDATE:
This is the code to do it:
<?php
$csv=file_get_contents("http://finance.yahoo.com/d/quotes.csv?s=^GDAXI+^TECDAX+eurusd=x+gcf12.cmx+CLH12.NYM&f=nl1k2");
$rows=explode("\n", $csv);
for($i=0;$i<count($rows);$i++)
{
preg_match_all("/\"([^\"]+)\",(\d+\.\d+),\"(N\/A)?([+-]?\d+\.?\d+)?\s+-\s+([+-]?\d+\.?\d+%?)/", $rows[$i],$matches,PREG_SET_ORDER);
}
?>
It returns:
Array
(
[0] => Array
(
[0] => "DAX",6864.43,"+54.97 - +0.81%
[1] => DAX
[2] => 6864.43
[3] =>
[4] => +54.97
[5] => +0.81%
)
Array
(
[0] => Array
(
[0] => "Gold Jan 12",1731.80,"N/A - +0.32%
[1] => Gold Jan 12
[2] => 1731.80
[3] => N/A
[4] =>
[5] => +0.32%
)
)
If it is N/A you will find it in $matches[3], if a value in 4.
)

first of all, you should see the manual here
and then, see the following code pasted as example,
<?php
//
// Convert csv file to associative array:
//
function csv_to_array($input, $delimiter='|')
{
$header = null;
$data = array();
$csvData = str_getcsv($input, "\n");
foreach($csvData as $csvLine){
if(is_null($header)) $header = explode($delimiter, $csvLine);
else{
$items = explode($delimiter, $csvLine);
for($n = 0, $m = count($header); $n < $m; $n++){
$prepareData[$header[$n]] = $items[$n];
}
$data[] = $prepareData;
}
}
return $data;
}
//-----------------------------------
//
//Usage:
$csvArr = csv_to_array(file_get_contents('test.csv'));
?>
this code should help you a lot, but please save the file to CSV to use this function..and saving the file is not tough. and the source for the code is still the stated above link you just need to modify it as per your requirements..
HTH

Related

concatenate words from two separate files

I am trying to concatenate words from a file with words from another file. However when I run the script I get a full output of the first file, then the output of the second file, then I see that the execution does not complete so I am stuck in an infinite loop. This is my code:
include 'passgen.txt';
include 'mycharset.txt';
$lines=file('passgen.txt');
$additions=file('mycharset.txt');
foreach($lines as $line){
foreach($additions as $addition){
$newPasswords=$line . $addition;
}
}
file_put_contents('newPasswords.txt', print_r($newPasswords, true));
passgen.txt content example:
stack
5tack
St4ck
...
mycharset.txt content example:
1
1!
2
2!
Expected results of what I am trying to achieve:
stack1
stack1!
stack2
stack2!
5tack1
5tack1!
...
EDIT:
adding full code from Jay answer:
#!/usr/bin/php
<?php
include 'passgen.txt';
include 'mycharset.txt';
$lines=file('passgen.txt');
$additions=file('mycharset.txt');
foreach($lines as $start) {
foreach($additions as $end) {
file_put_contents('newPasswords2.txt', $start.$end ."\r\n", FILE_APPEND);
}
}
?>
SAMPLE OUTPUT from Jay answer:
St4ck
6!3
St4ck
6!4
St4ck
6!5
I tried to remove the \r\n but still does not append the 6!5 to the word in the desired format below:
St4ck6!4
St4ck6!5
...
You are just creating a line, so you will not get an array as $newPasswords is overwritten on each iteration. What I did was place the concatenated words into an array ($word_array). You can then loop through the array easily and place into a text file:
EDIT
Added the trim() function to account for any whitespace characters in the text files we may not be aware of:
$file1 = ['stack','5tack','St4ck'];
$file2 = ['1','1!','2'];
$word_array = array();
foreach($file1 as $start) {
foreach($file2 as $end) {
$word_array[] = trim($start).trim($end);
}
}
print_r($word_array);
Returns:
Array
(
[0] => stack1
[1] => stack1!
[2] => stack2
[3] => 5tack1
[4] => 5tack1!
[5] => 5tack2
[6] => St4ck1
[7] => St4ck1!
[8] => St4ck2
)
Now you can put these in your text file like this:
foreach($word_array as $word) {
file_put_contents('newPasswords.txt', $word."\r\n");
}
Having said that I caution you against using this for password generation for any reason. You're essentially creating a rainbow table based on your comment:
I am using a weak password finder and I need a custom list of password to compare if hashes are weak.
You'd be better off providing the users with a password strength indicator that would encourage them to create strong passwords.
Shortening the process...
You could shorten the process entirely by writing to the file during the loop, which would require no arrays:
foreach($file1 as $start) {
foreach($file2 as $end) {
file_put_contents('newPasswords.txt', trim($start).trim($end) ."\r\n", FILE_APPEND);
}
}
You can use the fgets() function to read from a file line by line. Then you can concatenate that.
So something like:
$count = 0;
while($word = fgets($lines, 4096)){
$word = $word . additions[$count];
echo $word;
$count++;
}

Handle csv with php in for loop and write them back

i'm struggling with a php code that must open more than 1 csv, handle its content and write back on a different way that was initially.
So, i have all csv's on rows, and i wanna parse them and split them in columns on 2 rows.
The code looks like:
$currentDirOtherCSV = __DIR__ . "/uploads/" . $ftp_location . "partial_crawler_data/";
$files_other_CSV = scandir($partial_crawler_data, 1);
for($i = 0; $i < count($files_other_CSV) - 2; $i++){
$csvFileToOpen = file($currentDirOtherCSV . $files_other_CSV[$i]);
$screamingDataFirst = [];
foreach ($csvFileToOpen as $line) {
$screamingDataFirst[] = str_getcsv($line);
}
// remove header from csv
array_shift($screamingDataFirst);
array_shift($screamingDataFirst);
// handle array to export it on 2 rows
$theExportArray = [[],[]];
for($j = 0; $j < count($screamingDataFirst); $j++){
if(!array_key_exists('1', $screamingDataFirst[$j])) {
$screamingDataFirst[$j][1] = "";
}
}
foreach ($screamingDataFirst as $key => $row){
$theExportArray[0][$key] = $row[0];
$theExportArray[1][$key] = $row[1];
}
print_r($theExportArray);
// edit csv file remote
$new_csv_data = fopen($currentDirOtherCSV . $files_other_CSV[$i], "w");
foreach($theExportArray as $row){
fputcsv($new_csv_data, $row, ";");
}
fclose($new_csv_data);
}
The csv looks like:
"Page Titles - Duplicate"
"Address","Title 1"
"http://www.seloo.ro/index.php?route=product/product&path=60&product_id=123","Scaun tapitat Alb"
"http://www.seloo.ro/index.php?route=product/product&path=60&product_id=122","Scaun tapitat Alb"
"http://www.seloo.ro/index.php?route=product/product&path=60&product_id=121","Scaun tapitat Alb"
"http://www.seloo.ro/index.php?route=product/product&path=60&product_id=127","Scaun tapitat Alb"
so i get this array by parsing it:
Array
(
[0] => Array
(
[0] => http://www.seloo.ro/index.php?route=product/product&path=60&product_id=123
[1] => http://www.seloo.ro/index.php?route=product/product&path=60&product_id=122
[2] => http://www.seloo.ro/index.php?route=product/product&path=60&product_id=121
[3] => http://www.seloo.ro/index.php?route=product/product&path=60&product_id=127
)
[1] => Array
(
[0] => Scaun tapitat Alb
[1] => Scaun tapitat Alb
[2] => Scaun tapitat Alb
[3] => Scaun tapitat Alb
)
)
EDIT
That must be:
http://www.seloo.ro/index.php?route=product/product&product_id=95;http://www.seloo.ro/index.php?route=product/product&path=59&product_id=95;http://www.seloo.ro/index.php?route=product/product&product_id=94;
"Masa New vision";"Masa flori lila";"Masa flori lila";
Problem:
I thought that if i open the file, handle it, push it back modified in the csv and close (fclose) then do it again untill no csv, will handle them 1 by one...
But it only write in a single csv, rest of them arent touched
Am i missing something?
UPDATE
The script works fine.
The problem was that i have tried to update the unuploaded files on the server.
Script was faster than upload.
Thank you all and sorry, i should check that earlier

Counting blank spaces till next string in PHP array

I have imported .xlsx file to PHP through a script. I only need two columns from the file
This is done, but as you can see there is address and following it blank spaces.
I need the information from right column to be in one string corresponding to the address on the left.
foreach ($Reader as $Row)
{
array_push($data, $Row);
$aadress_loc = array_search("Aadress", $Row);
$eluruumid = array_search("Ehitise osad", $Row);
array_push($asukohtruumid, $aadress_loc);
array_push($asukohtruumid, $eluruumid);
}
$li_length = count($data);
for ($i = 1; $i < $li_length; $i++){
array_push($aadress_mas,($data[$i][$asukohtruumid[0]])); // left column
array_push($ruumid_mas,($data[$i][$asukohtruumid[1]])); // right column
}
Array
(
[0] => Harju maakond, Kernu vald, Laitse küla, Lossi tee 6
[1] =>
[2] => // 0;2 is the length of the first element
)
Array
(
[0] => E/1;E/2;E/3;E/4;E/5;E/6;M/7/Kontoriruumid;E/8;E/9
[1] => E/10;E/11;E/12;E/13;E/14;E/15;E/16;E/17;E/18;E/19
[2] => E/20;E/21;E/22;E/23;E/24
so I need to merge these 0;2 elements from another array to one string
and repeat the process with another elements from aadress array.
Here is the array with the diffrences but I don't know how can I use it to do what I need.
Sorry for not so good english.
Hopefully I understand the question but I think you are looking for this:
foreach ($Reader as $Row)
{
echo $row[0].' - '.$row[7];
// OR
echo $row['Aadress'].' - '.$row['Ehitise osad'];
}
I am not sure which one will work in your situation.

php regular expression to capture number from table and load into variable

So here is the string that im scraping a page to read (using file get contents)
<th>Kills (K)</th><td><strong>4,751</strong></td><td><strong>0</strong></td>
How can i navigate to the above section of the page contents, and then isolate the 4,751 inside the above html and load it into $kills ?
Difficulty: the number will change and have additional numbers before the comma
Ok got it to work by removing all spaces and turning the page contents into a string
<?
$url = "http://combatarms.nexon.net/Community/Profile.aspx?user=tect0n";
$raw = file_get_contents($url);
$newlines = array("\t","\n","\r","\x20\x20","\0","\x0B");
$content = str_replace($newlines, "", html_entity_decode($raw));
preg_match_all('|<th>.*?</th><td><strong>(\d+,\d+)</strong></td>|', $content,$match);
?>
This returns
Array ( [0] => Array ( [0] => Kills (K)4,751 [1] => Deaths (D)4,868 ) [1] => Array ( [0] => 4,751 [1] => 4,868 ) )
This should do it:
if (preg_match("/<th>Kills \(K\)<\/th><td><strong>([\d,]+)<\/strong>/",
$string, $matches)) {
$kills = str_replace(",","",$matches[1]);
} else {
$kills = 0;
}
This is what im using and gnarf's code returns 0
RageZ's returned an empty array
<?
$string = file_get_contents("http://combatarms.nexon.net/Community/Profile.aspx?user=tect0n");
if (preg_match("/<th>Kills \(K\)<\/th><td><strong>([\d,]+)<\/strong>/",
$string, $matches)) {
$kills = str_replace(",","",$matches[1]);
} else {
$kills = 0;
}
echo $kills;
?>
Coming up 0
here you go
preg_match_all('|<th>.*?</th><td><strong>([\d,]+)</strong></td>|x', $subject,$match);
var_dump($match);
but if I were you I would use xpath it's is safer.
preg_match_all('#\(K\).*?<strong>(.*?)</strong>#s',$html,$matches);
tell me that aint pretty
preg_match('#<table class="tbl_profile">(.*?)</table>#s',file_get_contents('http://combatarms.nexon.net/Community/Profile.aspx?user=tect0n'),$m);
preg_match_all('#<tr>.*?<t.*?>(.*?)</t.*?>.*?<t.*?>(.*?)</t.*?>.*?<t.*?>(.*?)</t.*?>.*?</tr>#s',preg_replace('#(<strong>)|(</strong>)|(<!--.*?-->)#s','',$m[1]),$r);
echo 'You got '.$r[2][1].' killz';
//print_r($r);
now tell me thaaaaaaat aint pretty, cooooool it.

php function to split an array at each blank line?

I'm building a script which will open a saved text file, export the contents to an array and then dump the contents in a database. So far I've been able to get the file upload working quite happily and can also open said file.
The trouble I'm having is the contents of the file are variable, they have a fixed structure but the contents will change every time. The structure of the file is that each "section" is seperated by a blank line.
I've used php's file() to get an array ... I'm not sure if there's a way to then split that array up every time it comes across a blank line?
$file = $target_path;
$data = file($file) or die('Could not read file!');
Example output:
[0] => domain.com
[1] => # Files to be checked
[2] => /www/06.php
[3] => /www/08.php
[4] =>
[5] => domain2.com
[6] => # Files to be checked
[7] => /cgi-bin/cache.txt
[8] => /cgi-bin/log.txt
[9] =>
[10] => domain3.com
[11] => # Files to be checked
[12] => /www/Content.js
[13] =>
I know that Field 0 and 1 will be constants, they will always be a domain name then that hash line. The lines thereafter could be anywhere between 1 line and 1000 lines.
I've looked at array_chunk() which is close to what I want but it works on a numerical value, what would be good if there was something which would work on a specified value (like a new line, or a comma or something of that sort!).
Lastly, apologies if this has been answered previously. I've searched the usual places a few times for potential solutions.
Hope you can help :)
Foxed
I think what you're looking for is preg_split. If you just split on a carriage return, you might miss lines that just have spaces or tabs.
$output = array(...);//what you just posted
$string_output = implode('', $output);
$array_with_only_populated_lines = preg_split('`\n\W+`', $string_output);
You could just do something like this. You could change it also to read the file in line-by-line rather than using file(), which would use less memory, which might be important if you use larger files.
$handle = fopen('blah', 'r');
$blocks = array();
$currentBlock = array();
while (!feof($handle)) {
$line = fgets($handle);
if (trim($line) == '') {
if ($currentBlock) {
$blocks[] = $currentBlock;
$currentBlock = array();
}
} else {
$currentBlock[] = $line;
}
}
fclose($handle);
//if is anything left
if ($currentBlock) {
$blocks[] = $currentBlock;
}
print_r($blocks);
Have you tried split('\n\n', $file);
?
You could do it by splitting first on the blank line and then on new lines, e.g.:
$file = $target_path;
$fileData = file_get_contents($file) or die('Could not read file!');
$parts = explode("\n\n", $data);
$data = array();
foreach ($parts as $part) {
$data[] = explode("\n", $part);
}
You could also use preg_split() in place of the first explode() with a regex to sp.lit on lines containing just whitespace (e.g. \s+)
I would use the function preg_grep() to reduce the resulting array:
$array = preg_grep('/[^\s]/', $array);

Categories