The str_getcsv() function is designed to work on a line of CSV text, not on a set of lines. I am trying to use it twice, once to split multiple lines of CSV into an array of lines, and then again on each of those. This solution was working for me, and indeed I supplied it as an answer to another question.
However, I now have a problem whereby the line "AC150AC,",service tool,845.71,-2 is returned as AC150AC,,service tool,845.71,-2, with the quotation marks removed, so the comma is now treated as a separator. In debugging that, I found that multi-line values are now also not working, and are now split in the middle despite being enclosed correctly.
How can I debug this?
$ cat csv.php
<?php
$csv = '130,TEST A 1258 (U10 001),28.66,2
"AC150AC,",service tool,845.71,-2
AL7951,SEA LION,47.19,2
T11,"Test multi-
line segments",587.36,4';
$n = str_getcsv($csv, "\n");
$r = str_getcsv($csv, "\r");
print_r($n);
print_r($r);
$ xxd csv.php
00000000: 3c3f 7068 700a 0a24 6373 7620 3d20 2731 <?php..$csv = '1
00000010: 3330 2c54 4553 5420 4120 3132 3538 2028 30,TEST A 1258 (
00000020: 5531 3020 3030 3129 2c32 382e 3636 2c32 U10 001),28.66,2
00000030: 0a22 4143 3135 3041 432c 222c 7365 7276 ."AC150AC,",serv
00000040: 6963 6520 746f 6f6c 2c38 3435 2e37 312c ice tool,845.71,
00000050: 2d32 0a41 4c37 3935 312c 5345 4120 4c49 -2.AL7951,SEA LI
00000060: 4f4e 2c34 372e 3139 2c32 0a54 3131 2c22 ON,47.19,2.T11,"
00000070: 5465 7374 206d 756c 7469 2d0a 6c69 6e65 Test multi-.line
00000080: 2073 6567 6d65 6e74 7322 2c35 3837 2e33 segments",587.3
00000090: 362c 3427 3b0a 0a24 6e20 3d20 7374 725f 6,4';..$n = str_
000000a0: 6765 7463 7376 2824 6373 762c 2022 5c6e getcsv($csv, "\n
000000b0: 2229 3b0a 2472 203d 2073 7472 5f67 6574 ");.$r = str_get
000000c0: 6373 7628 2463 7376 2c20 225c 7222 293b csv($csv, "\r");
000000d0: 0a0a 7072 696e 745f 7228 246e 293b 0a70 ..print_r($n);.p
000000e0: 7269 6e74 5f72 2824 7229 3b0a 0a rint_r($r);..
$ php csv.php
Array
(
[0] => 130,TEST A 1258 (U10 001),28.66,2
[1] => AC150AC,,service tool,845.71,-2
[2] => AL7951,SEA LION,47.19,2
[3] => T11,"Test multi-
[4] => line segments",587.36,4
)
Array
(
[0] => 130,TEST A 1258 (U10 001),28.66,2
"AC150AC,",service tool,845.71,-2
AL7951,SEA LION,47.19,2
T11,"Test multi-
line segments",587.36,4
)
The problem is that you are splitting it by end of line characters(of various types) which you don't know if they are mid line or genuine end of lines.
A fudge is to use fgetcsv() to do the work for you, so you first have to give it a file to work with. This code creates a temporary file, writes the contents to it and then rewinds the file so the read starts from the beginning...
$fh = tmpfile();
fwrite($fh, $csv);
fseek($fh, 0);
while ( $row = fgetcsv($fh)) {
print_r($row);
}
fclose($fh);
What is the result expected ? I'm not sure to understand what you want.
I guess explode() will help you ?
$csv = '130,TEST A 1258 (U10 001),28.66,2
"AC150AC,",service tool,845.71,-2
AL7951,SEA LION,47.19,2
T11,"Test multi-
line segments",587.36,4';
$n = explode("\n", $csv);
var_dump(array_map('str_getcsv', $n));
Related
NodeJS code:
const salt = new Buffer('GHlDHToiZA1ViUu+W+EXww==', 'base64');
Output like this:
<Buffer 18 79 43 1d 3a 22 64 0d 55 89 4b be 5b e1 17 c3>
I need the same output in PHP. Read somewhere about PHP's pack function but I don't know how to use it.
Seems that you are working with base64; in php you are right pack and unpack is your friends.
example
in Node
$ node
> Buffer('hello world').toString('base64')
aGVsbG8gd29sZA==
in PHP
$ php -a
php > echo base64_encode('hello world');
aGVsbG8gd29ybGQ=
But if you are only looking for the binary:
in Node
> Buffer('hello wold')
<Buffer 68 65 6c 6c 6f 20 77 6f 6c 64>
in PHP
php > print_r(unpack('H*', 'hello world'));
Array
(
[1] => 68656c6c6f20776f726c64
)
So in your instance you would first decode the base64 and then unpack it.
php > $raw = base64_decode('GHlDHToiZA1ViUu+W+EXww==');
php > print_r(unpack('H*', $raw));
Array
(
[1] => 1879431d3a22640d55894bbe5be117c3
)
Easy peasy ;)
I have the same problem, and i found solution using the packet: lcobucci/jwt.
Must to create a buffer by your key in base64, after create will be converting to binary for sign the jwt.
$configuration = Configuration::forSymmetricSigner(
// You may use any HMAC variations (256, 384, and 512)
new Sha256(),
// replace the value below with a key of your own!
InMemory::base64Encoded('your-base64-key')
// You may also override the JOSE encoder/decoder if needed by providing extra arguments here
);
I am trying to get the percentage value of download from the following string.
[download] Destination: Kool - Get Noticed - Apurbo-7CggL03TTl4.mp4
[download] 100% of 1.60MiB in 00:21
[download] Destination: Kool - Get Noticed - Apurbo-7CggL03TTl4.m4a
[download] 100% of 164.86KiB in 00:01
For ex. only the value '100' between '[download]' and '% of'.
This is my code what I've tried so far
$file = file_get_contents("t.txt");
if (preg_match_all("/(?<=\[download\])(.*?)(?=\% of)/s", $file, $result))
for ($i = 1; count($result) > $i; $i++) {
print_r($result[$i]);
}
But the problem is it grabs from the first line and outputs like
Array ( [0] => Destination: Kool - Get Noticed - Apurbo-7CggL03TTl4.mp4 [download] 100 [1] => Destination: Kool - Get Noticed - Apurbo-7CggL03TTl4.m4a [download] 100 )
If I can grab just before the '% of' that will be okay I think. Should I stick to this code for modifying or change the whole pattern?
This should work for you:
Here I first get your file into an array with file() where every line is one array element. There I ignore new line characters and empty lines.
After this I go through each line with array_map() where I check with preg_match_all() if there is a pattern like this: [download] (\d+)% of. If it finds the number I return it otherwise I return false and at the end I filter the elements with false with array_filter() out.
<?php
$lines = file("t.txt", FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
$numbers = array_filter(array_map(function($v){
if(preg_match_all("/\[download\] (\d+)% of/", $v, $m))
return $m[1][0];
else
return false;
}, $lines));
print_r($numbers);
?>
output:
Array ( [1] => 100 [3] => 100 )
I have this array $awstat that I extacted from an awstat file, an withing $awstat I have this that I need:
BEGIN_TIME 24
0 3245 9955 143463426 8047 13601 475741423
1 3122 9131 146244440 7579 12936 507921700
2 2639 5706 95369716 7351 11987 490330698
3 1917 4062 79234871 8245 13009 579453498
4 1757 4263 65580607 7887 11437 454870321
5 1723 4022 44682383 6888 10263 326819624
6 1876 4677 56964771 7339 11242 355385677
7 2796 8473 120152521 7770 12176 362904239
8 4227 13791 196173677 7421 12196 366706352
9 7984 25965 375376297 8398 13883 406545549
10 14605 34418 434054375 7183 13341 380773129
11 15533 41259 559938996 7123 12690 372426426
12 17495 40043 505139834 7432 13402 518541077
13 15815 34170 385108531 6519 12390 396494926
14 16330 41073 508838859 6761 12318 348417806
15 19093 44058 483568307 7692 13583 454365520
16 30429 59672 577852398 8273 13231 473134295
17 25094 48897 478246556 8207 12898 476038603
18 19136 42665 482073005 8087 12983 468300958
19 28849 46228 371229572 7721 12688 471632281
20 14068 30981 341103557 7832 13251 417443822
21 14727 33458 394841797 7575 12644 388811384
22 13480 31364 365096742 7460 13114 411771572
23 7189 19744 272606100 6643 12398 397762547
END_TIME
So I tried this and it doesn't seem to work!
preg_match("/BEGIN_TIME(.*)END_TIME/is", $awstats, $matches);
$time = $matches[0] ;
var_dump($time); // it displays "NULL"
Any solution for this? Thanks!
Not so much an answer, more of an opinion.
Using regular expressions here is overkill.
Something as simple as this will do:
$lines = file("awstats.output");
$lines = array_slice(1); // remove first line
$lines = array_slice(0, -1); // remove last line
foreach ($lines as $line) {
$data = explode(" ", $line);
// handle data
}
You can match linebreaks with:
([^\n]*\n+)+
So this should work:
preg_match("/BEGIN_DAY([^\n]*\n+)+END_DAY/is", $awstats, $matches);
$time = file_get_contents('awstat.log');
$time = preg_replace('/BEGIN_TIME(.*?)END_TIME/sim', '$1', $time);
<?php
$file = 'file.dat';
$file_contents = file_get_contents($file);
for ($i = 0x000481; $i <= 0x00048B; $i++) {
print $i;
}
?>
I am creating an online file analyzer but I have a small problem. It outputs (which is the actual position the hex is in)
1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163
when it should be
44 72 48 79 64 72 61 6C 69 73 6B
which his hex for DrHydralisk (me). Can anyone help me output the latter or just have it strait output ASCII (but hex is fine, I can just convert it)?
edit
Here is an image of what I am trying to do that I think will help.
http://imgur.com/nwenA.png
Here is the file I am trying to read, its a Starcraft replay (file.SC2Replay). Just search for DrHydralisk in a hex editor and that is where I am trying to read from.
http://www.mediafire.com/?6w8wi35q3o6ix8q
It should be (if clear text is in the file):
for( $i=0x481; $i<0x48D; $i++ ) {
printf("%X ", ord($file_contents[$i]));
}
Note the loop boundaries: 0x481 .. 0x48D
Result:
44 72 20 48 79 64 72 61 6C 69 73 6B
If the file contains hexadecimal numbers, this would be impossible because you need two bytes per hex char for the ascii character value range. So what is really in the file?
Edit
After reading your file, i did:
...
$file = 'file.SC2Replay';
$file_contents = file_get_contents($file);
for( $i=0x438; $i<0x443; $i++) {
printf("%X ", ord($file_contents[$i]));
}
for( $i=0x438; $i<0x443; $i++) {
printf("%s ", $file_contents[$i]);
}
...
And it says:
72 48 79 64 72 61 6C 69 73 6B
and
D r H y d r a l i s k
You messed up the file position ;-)
Regards
rbo
EDIT:
Thanks for providing the file, helped a lot! Beleive I got it working too:
//Do binary safe file read
$filename = 'file.SC2Replay';
$file = fopen($filename, "rb");
$contents = fread($file, filesize($filename));
fclose($file);
//position 1080 - 1091
for ($i = 0x438; $i < 0x443; $i++)
echo $contents[$i];
The reasons you were probably having problems is that first of all, a binary safe file read in php automatically replaces the bytes with the correct ASCII characters, so that threw off what position you actually needed to start reading from. Intead of 1153, it starts at 1080.
Could you explain how you are using the file you read in? Because the hex equivalent of:
11531154115511561157115811591160116111621163
is:
481 482 483 484 485 486 487 488 489 48a 48b
Also, there are two php functions you may find helpful
chr(int): returns the ascii character associated with the integer provided - http://php.net/manual/en/function.chr.php
dechex(int): returns the hex value of the integer provided - http://php.net/manual/en/function.dechex.php
I am to import a file, say june.txt that would have data such as the following data:
Sandy,820,384,133,18,408
Wanda,120,437,128,807,595
Jane,631,415,142,687,600
Andrea,179,339,349,594,986
Wanda,803,191,6,807,322
Jane,741,975,34,15,832
Jane,239,714,250,94,497
Andrea,219,188,411,584,713
And then the PHP would parse it into 2 difference ways:
The first way being all the names bundled together with totals, such as:
Sandy 820 384 133 18 408
Total 820 384 133 18 408
Jane 631 415 142 687 600
Jane 741 975 34 15 832
Jane 239 714 250 94 497
Total 1611 2104 426 796 497
Andrea 179 339 349 594 986
Andrea 219 188 411 584 713
Total 398 527 760 1178 1699
Wanda 120 437 128 807 595
Wanda 803 191 6 807 322
Total 923 628 134 1614 917
The second way would total and add the names together in a big list, such as
Sandy 820 384 133 18 408
Jane 1611 2104 426 796 497
Andrea 398 527 760 1178 1699
Wanda 923 628 134 1614 917
Any logic or suggestions would be helpful, I am new to PHP and not sure how this could even be done. My plan is to eventually display the results in HTML tables and have them sortable, but I can tackle that at a later date, Unless someone feels obligated to just add the and such for me in the parsing.
I think something useful for you would be the explode function.
As far as creating these views I'd start by loading all this data into an associative array of arrays based on the name, then iterate as necessary:
$datafile = file("filename.txt");
// reads lines into an associative array (key is the name) of arrays
// where each sub-array is a list of the records for each name
$arr = array();
foreach($datafile as $line){
$temp = explode(',', $line);
$arr[$temp[0]][] = $temp;
}
// iterate over each person
foreach($arr as $person_set){
// create an array to hold the sum of each column
// (and the name in the first column)
$totals = array();
$totals[0] = $person_set[0][0];
for($i = 1; $i < length($record); $i++){
$totals[$i] = 0;
}
// now iterate over each record for this person
foreach($person_set as $record){
// print a particular record
echo implode(' ', $record) . '<br>';
// add each column (1..end) to the totals array
for($i = 1; $i < length($record); $i++){
$totals[$i] += $record[$i];
}
}
// print out the totals line
echo implode(' ', $totals) . '<br><br>';
}
I'll leave formatting this data into a table as an exercise.
Well, to start, I'd real a file like that with PHP's fgetcsv(). Docs.
You could try a script like this:
<?php
echo "<table>";
$data = file("june.txt");
foreach($data as $month) {
$line = explode(',', $data);
echo '<tr><td>', implode('</td><td>', $line), '</td></tr>';
}
echo "</table>";
Edit:
My bad, didn't notice that you were sorting/grouping/totaling. This should set you on the right track, though. The key is to use $line as your source of information. Just compile it into an array and output later (instead of right in the loop).