Array isn't sorting when writing to file - php

I wrote this script:
<?PHP
$file_handle = fopen("info.txt", "rb");
while (!feof($file_handle) ) {
$line_of_text = fgets($file_handle);
$parts[] = explode('|', $line_of_text);
}
fclose($file_handle);
$a = $parts;
function cmp($a,$b){
return strtotime($a[8])<strtotime($b[8])?1:-1;
};
uasort($a, 'cmp');
$failas = "dinfo.txt";
$fh = fopen($failas, 'w');
for($i=0; $i<count($a); $i++){
$txt=implode('|', $a[$i]);
fwrite($fh, $txt);
}
fclose($fh);
?>
When I use:
print_r($a);
after
uasort($a, 'cmp');
Then I can see sorted array. But when I write to file using these commands:
$fh=fopen($failas, 'w');
for($i=0; $i<count($a); $i++){
$txt=implode('|', $a[$i]);
fwrite($fh, $txt);
}
fclose($fh);
It shows not sorted information, what am I doing wrong?

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 empty lines and new line characters at the end of each line.
After this I sort the array with usort(). Where I first get all dates and times from each line by explode()'ing it. After this I simply get the timestamp of each date with strtotime() and compare it which each other.
At the end I simply save the file with file_put_contents(), where I also add a new line character at the end of each line with array_map().
<?php
$lines = file("test.txt", FILE_SKIP_EMPTY_LINES | FILE_IGNORE_NEW_LINES);
usort($lines, function($a, $b){
list($aDate, $aTime) = explode(" ", explode("|", $a)[substr_count($a, "|")]);
list($bDate, $bTime) = explode(" ", explode("|", $b)[substr_count($b, "|")]);
if(strtotime("$aDate $aTime") == strtotime("$bDate $bTime"))
return 0;
return strtotime("$aDate $aTime") < strtotime("$bDate $bTime") ? 1 : -1;
});
file_put_contents("test.txt", array_map(function($v){return $v . PHP_EOL;}, $lines));
?>
Side notes:
I would recommend you to save this data in a database where it is much flexible to sort and getting the data!
EDIT:
For people which have a php version (echo phpversion();) under <5.3, just change the anonymous functions to normal functions and pass the function name as strings like this:
<?php
$lines = file("test.txt", FILE_SKIP_EMPTY_LINES | FILE_IGNORE_NEW_LINES);
function timestampCmp($a, $b) {
$aExploded = explode("|", $a);
$bExploded = explode("|", $b);
list($aDate, $aTime) = explode(" ", $aExploded[substr_count($a, "|")]);
list($bDate, $bTime) = explode(" ", $bExploded[substr_count($b, "|")]);
if(strtotime("$aDate $aTime") == strtotime("$bDate $bTime"))
return 0;
return strtotime("$aDate $aTime") < strtotime("$bDate $bTime") ? 1 : -1;
}
function addEndLine($v) {
return $v . PHP_EOL;
}
usort($lines, "timestampCmp");
file_put_contents("test.txt", array_map("addEndLine", $lines));
?>

Related

How to take a value of the input given in a file into an array with specified format

Input Format is
6
4 5 1 9 8 7
Where first line gives the length of the array or the number of character
Required Output
array{4,5,1,9,8,7}
<?php
$fp = fopen("C://wamp//www//phptut////Insertion Sort//stdin.txt", "r");
$m = (int) fgets($fp);
var_dump($m);
$arr = array();
for ($i=0; $i<$m; $i++) {
fscanf($fp, "%d", $arr[$i]);
}
//var_dump($arr);
foreach($arr as $value) {
print $value;
}
?>
$fp = fopen("your file loc", "r");
fscanf($fp, "%d", $m);
$ar= fgets($fp);
$arr = explode(" ", $ar);
// here this explode and implode is done because here whatever you want to do with your array ..do it
$value = implode(" ", $arr);
print $value;

Scandir newest files in array with limit

I have made a PHP script to scan a directory, it lists all filenames in an array with a limit of 20. Now its displaying only the beginning of the array. So if there are 40 files, it displays only the first 0-20 but we need 20-40.. Can someone help me ? Thanks!!
<?php
$files = glob('data/*.{png}', GLOB_BRACE);
usort($files, 'filemtime_compare');
function filemtime_compare($a, $b)
{
return filemtime($a) - filemtime($b);
}
$i = 0;
$show = 20;
foreach($files as $file)
{
if($i == $show) {
break;
} else {
++$i;
}
$var .= $file . "\n";
}
$fp = fopen("data.txt", "wb");
fwrite($fp, $var);
fclose($fp);
echo $var;
?>
You could use array_chunk() to split the $files array up in chunks of 20 files. Then use implode() to format the values in a chunk to a single string. Replace the foreach loop with this:
$show = 20;
$files = array_chunk($files, $show);
$page = 0; // page 0 is 0-19, page 1 is 20-39, etc.
$var = implode("\n", $files[$page]);
Edit: For the last 20 files you could use array_slice():
$files = array_slice($files, -20);
$var = implode("\n", $files);

Count specific lines in text file

How to count specific lines in a text file depending on a particular variable in that line.
For example i need to count the lines of a text file only containing for instance $item1 or $item2 etc.
Sounds like you need something like what grep -c do in the shell, try something like this:
$item1 = 'match me';
$item2 = 'match me too';
// Thanks to #Baba for the suggestion:
$match_count = count(
preg_grep(
'/'.preg_quote($item1).'|'.preg_quote($item2).'/i',
file('somefile_input.txt', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES)
)
);
// does the same without creating a second array with the matches
$match_count = array_reduce(
file('somefile_input.txt', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES),
function($match_count, $line) use ($item1, $item2) {
return
preg_match('/'.preg_quote($item1).'|'.preg_quote($item2).'/i', $line) ?
$match_count + 1 : $match_count;
}
);
The above code sample uses the file() function to read the file into an array (splitted by lines), array_reduce() to iterate that array and preg_match() inside the iteration to see if a line matched (the /i at the end makes it case-insensitive).
You could use a foreach as well too.
This code reads file.php and counts only lines containing '$item1' or '$item2'. The check itself could be finetuned, since you have to add a new stristr() for every word you want to check.
<?php
$file = 'file.php';
$fp = fopen($file, 'r');
$size = filesize($file);
$content = fread($fp, $size);
$lines = preg_split('/\n/', $content);
$count = 0;
foreach($lines as $line) {
if(stristr($line, '$item1') || stristr($line, '$item2')) {
$count++;
}
}
echo $count;
Read your file line by line and use strpos to determine if a line contains a specific string/item.
$handle = fopen ("filename", "r");
$counter = 0;
while (!feof($handle))
{
$line = fgets($handle);
// or $item2, $item3, etc.
$pos = strpos($line, $item);
if ($pos !== false)
{
$counter++
}
}
fclose ($handle);

PHP modify TXT file

I have a ID.txt file that looks like this:
"http://something.net/something-ak/41389_718783565_1214898307_q.jpg"
"http://something.net/something-ak/372142_106502518141813_1189943482_q.jpg"
and so on
I want to use PHP to open the file and remove everything before the first " _ " and everything after the second " _ " so I wind up with this:
718783565
106502518141813
and so on
Thing is I don't really know how to do that.
This is what I have so far:
<?PHP
$file_handle = fopen("ID.txt", "rb");
while (!feof($file_handle) ) {
$line_of_text = fgets($file_handle);
$parts = explode('\n', $line_of_text);
// Remove everything before the first "_" and everything after the last "_".
// echo the line
}
fclose($file_handle);
?>
Can someone help me fille in the blanks?
This is what I would do, although a regex might be shorter or more efficient:
$file_handle = fopen("ID.txt", "rb");
while (!feof($file_handle) )
{
$line_of_text = fgets($file_handle);
$parts = explode("\n", $line_of_text);
foreach ($parts as $str)
{
$str_parts = explode('_', $str); // Split string by _ into an array
array_shift($str_parts); // Remove first element
echo current($str_parts)."\n"; // echo current element and newline
// Same as $str_parts[0]
}
}
fclose($file_handle);
Demo: http://codepad.org/uFbVDtbR
Not a big deal, but $lines might be a better variable name there instead of $parts.
If you do need to write this back to the file, you can do this:
ob_start();
// code used above
$new_content = ob_get_clean();
file_put_contents("ID.txt", $new_content);
Relevant references:
http://php.net/manual/en/function.explode.php
http://www.php.net/manual/en/function.array-shift.php
http://php.net/manual/en/function.current.php
http://php.net/manual/en/function.file-put-contents.php
Just use file in a loop
$content = "";
foreach(file("ID.txt", FILE_SKIP_EMPTY_LINES) as $line){
$parts = explode('_', $line);
$content .= $parts[1] . "\n";
}
file_put_contents("ID.txt", $content);
If you want to achieve this by awk,
awk -F _ '{print $2}' ID.txt
Try this
preg_match('/(.*?)(.+?)(.*)/',$line,$matches);
$matches[2] will give the required string
This should work
<?php
// open files
$file_handle = fopen("ID.txt", "rb");
$new_file_handle = fopen("ID2.txt", "wb");
while (!feof($file_handle) ) {
$str = fgets($file_handle);
$start = strpos($str, '_'); // find first "_"
$end = strpos($str, '_', $start + 1); // find next "_"
$newstr = substr($str, $start + 1, $end - $start - 1) . "\n";
fputs($new_file_handle, $newstr);
}
// close files
fclose($file_handle);
fclose($new_file_handle);
// rename
rename("ID2.txt", "ID.txt");
$TXT = file_get_contents(__DIR__.'/in.txt');
$NewTXT = preg_replace('~^.+/[0-9]+_([0-9]+)_.+?$~mi', '$1', $TXT);
file_put_contents(__DIR__.'/out.txt', $NewTXT);
Just rename the .txt files accordingly.

PHP Parsing a .dat file

I have a .dat file that is essentially ; delimited file and I'm trying to convert it to a tab delimited .txt. The problem that I am not sure about is that each row of the new file will be a combination of 3 of the original file's rows, each original row has a different quantity of data. The first column just identifies each row in a grouping. What would be the best way to do this?
Sample original data:
01;zxc;asd;qwe;uio;jkl;asd;123;456
02;lkj;oiu;oji
03;fjifao;vbofekjf;fjieofk;aoijf;voien3984
01;lkj;oiu;fji;eoj;vnk;fji;098;321
02;fji;oje;jvi
03;jie;voi;djv;eojf;38723
End output:
zxc asd qwe uio jkl asd 123 456 lkj oiu oji fjifao vbofekjf fjieofk aoijf voien3984
lkj oiu fji eoj vnk fji 098 321 fji oje jvi jie voi djv eojf 38723
Any ideas?
Here's how I'd do it:
$lines = file($data);
$rows = array();
$row_pivot = -1;
foreach ($lines as $line) {
// Split line by ;
$data = explode(';', trim($line));
// Get the first element
$r_id = array_shift($data);
if ($r_id == '01') {
// When 01 is the first element, start a new row
// You can dump the previous row here as well if you aim for speed
$row_pivot++;
$rows[$row_pivot] = array();
}
// Add data to row
$rows[$row_pivot] = array_merge($rows[$row_pivot], $data);
}
// Print rows
foreach ($rows as $r) {
echo implode("\t", $r)."\n";
}
I would personally explode the data then foreach row in the resulting array, then again explode each line at your delimiter ';' and then format an output that is tab delimited.
<?php
$data = 'LOADED FILE DATA';
$lines = preg_split( '/\r\n|\r|\n/', $data);
$out = '';
foreach($lines as $line){
$parts = explode(';',$line);
foreach($parts as $part){
$out .= $part.'\t';
}
$out .= '\n';
}
echo $out;
?>
code untested.
Should be something like this
$lines = file($filename);
$lineCount = count($lines);
$output = '';
for ($i = 0; $i < $lineCount - 2; $i += 3) {
$newLines = array();
for ($j = $i; $j < $i + 3; $j++) {
list($_, $rest) = explode(';', isset($lines[$j]) ? $lines[$j] : '');
$newLines = array_merge($newLines, $rest);
}
$output .= implode("\t", $newLines) . "\n";
}

Categories