How to sort array from file (PHP)? - php

I have a file here which contains list of database names and its corresponding size.
Now I want to sort the size from the largest to the lowest, and the database name
should go along it upon display.Am using PHP here..
Can anyone help me out?
Here's a simple code for that:
$file_name = test.txt
$handle = #fopen($file_name, "r");
if ($handle) {
while (!feof($handle)) {
$buffer = fgets($handle, 4096);
$data = explode(" ",$buffer);
echo $data[1]."\n";
}
fclose($handle);
}
File looks like this:
DatabaseName 300 KB
Note: $data[1] contains the sizes. Should i place it on an array? how about the db name?
Answers are very much appreciated. =)

First you need to build an array with an element you can actually sort on, then use usort or similar to perform the sort based on your custom criteria.
//first build up an array of databases with a unified size in bytes, ensuring
//we account for those postfixes like KB,MB,and GB
$databases=array();
while (!feof($handle)) {
$buffer = fgets($handle, 4096);
$data = explode(" ",$buffer);
if (count($data)==3)
{
$size=$data[1];
switch ($data[2])
{
case 'KB': $size*=1024; break;
case 'MB': $size*=1024*1024; break;
case 'GB': $size*=1024*1024*1024; break;
}
$data[3]=$size;
$databases[]=$data;
}
else
{
die("Bad line in file: $buffer");
}
}
Now sort with a custom comparison function to sort from high to low based on that calculated size:
function cmp($a, $b)
{
if ($a[3] == $b[3]) {
return 0;
}
return ($a[3] < $b[3]) ? 1 : -1;
}
usort($databases, "cmp");

You can use the file() PHP function here.
Your text file is like :
DatabaseName 300 KB
DatabaseName 300 KB
DatabaseName 300 KB
DatabaseName 300 KB
I think you can use the PHP native function on arrays.
$data = file('myfile.txt');
foreach($data as $one_line)
{
$db[] = explode(" ",$one_line)
//will have $db[0][0] = 'dbname';
//will have $db[0][2] = '30';
//will have $db[0][2] = 'KB';
//will have $db[1][0] = 'dbname';
//will have $db[1][3] = '30';
//will have $db[1][2] = 'KB';
}
array_multisort($db[1], SORT_NUMERIC, SORT_DESC);
See this comment in documentation, the same structure : http://fr2.php.net/manual/en/function.array-multisort.php#79491
Or maybe you have to flip the array, so you can have size in index and name in value.

function databases_sort($a, $b) {
if ($a[1] == $b[1]) { return 0; }
return ($a[1] < $b[1]) ? -1 : 1;
}
$file_name = "test.txt";
$handle = #fopen($file_name, "r");
$databases = array();
if ($handle) {
while (!feof($handle)) {
$buffer = fgets($handle, 4096);
$data = explode(" ",$buffer);
$databases[] = $data;
//echo $data[1]."\n";
}
usort($databases, "databases_sort");
foreach ($databases as $d) {
echo $d[1];
}
fclose($handle);
}
This code stores your information in an array, then runs a custom sorting function on your array, sorting it by the value of element 1 in the array. Higher values (larger database sizes) get sorted to the top of the list.
Warning: I haven't actually tested this code, but you can see the usort documentation if there are any bugs that need fixing.
Edit: d'oh, beaten by a few seconds :-)

Have you thought about parsing into a binary search tree structure instead of an array? That way you could have the data sorted with a tree traversal and you could have fast lookup too.

Related

replace rows from one csv file to another csv where id of is the samePHP?

I have one excel orginal.csv file
ID Name Price
1 Xblue 12
2 Yblue 32
3 Zblue 52
And another copy.csv file
ID Name Price
1 Xblue 89
2 Yblue 43
3 Zblue 45
I want to replace rows from orginal.csv to copy.csv where ID is the same.
Can I do this manually or maybe somehow using PHP?
I search for some options on the internet, but I only found getcsv and readcsv functions that can't help me in this case. Cause this is something like updating CSV file.
It may end up in request timeout in PHP because it requires so many loops to do it. If someone can reduce the time complexity of this program then it will work. if it even works it will take a lot of time to do it.
while(! feof($f_pointer)){ //open old csv to update loop1
$ar=fgetcsv($f_pointer); // getting first row
for($i=0;$i<count($ar);$i++){ //loop2 first row array
$f_pointer2=fopen("new.csv","r"); open new csv to get data
while(! feof($f_pointer2)){ // loop3 to find ID in new csv
$ar2=fgetcsv($f_pointer2); //getting each row in array
for($j=0;$j<count($ar2);$j++){ //loop4 to compare id of old csv to new csv and update data
if($ar[i] == $ar2[j]){
foreach ($ar2 as $fields) { //loop5
fputcsv($f_pointer, $fields);
}
}
}
}
}
}
?>
I've created a little soulution. If order is important you don't have to index the array and loop through the copied array.
<?php
if(file_exists('output.csv'))
{
unlink('output.csv');
}
function fputcsv_eol($handle, $array, $delimiter = ',', $enclosure = '"', $eol = "\n") {
$return = fputcsv($handle, $array, $delimiter, $enclosure);
if($return !== FALSE && "\n" != $eol && 0 === fseek($handle, -1, SEEK_CUR)) {
fwrite($handle, $eol);
}
return $return;
}
function scanFile($sFilename, $iIndexColumn)
{
$rFile = fopen($sFilename, 'r');
$aData = array();
while(($aLine = fgetcsv($rFile)) !== false)
{
$aData[$aLine[$iIndexColumn]] = $aLine;
}
fclose($rFile);
return $aData;
}
$iIndexColumn = 0;
$iValueColum = 2;
$aOriginalData = scanFile('original.csv', 0);
$aCopyData = scanFile('copy.csv', 0);
foreach($aOriginalData as $iID => $aOriginalDatum)
{
if(array_key_exists($iID, $aCopyData))
{
$aCopyData[$iID] = $aOriginalDatum;
}
}
$rFile = fopen('output.csv', 'w');
foreach($aCopyData as $aCopyDatum)
{
fputcsv_eol($rFile, $aCopyDatum, ',', '"',"\r\n");
}
fclose($rFile);

PHP - How to transpose an array that is from a text file

We have made an array from a text file full of numbers separated by commas, each new line is a new part of the array. (we are not allowed to use explode for this)
We are trying to create a transpose_matrix function to 'transpose' the array now.
Using tutorials on the internet, this is what we have come up with so far, but it doesn't work :(
$myfile = fopen("text1.txt", "r") or die("Unable to open file!");
//echo fread($myfile,filesize("text1.txt"));
$file1 = file("text1.txt");
$store1 = array();
for ($a = 0; $a<count($file1); $a++)
{
array_push($store1, $file1[$a]);
}
for ($k = 0; $k<count($store1); $k++)
{
echo "Line $store1[$k] <br/> END <br/>";
}
function transpose($store1) {
$file1 = file("text1.txt");
$store1 = array();
if (count($store1) == 0) // special case: empty matrix
return array();
else if (count($store1) == 1) // special case: row matrix
return array_chunk($store1[0], 1);
function myCallbackMethod() {
var_dump ($store1);
}
array_unshift($store1, NULL); // the original matrix is not modified because it was passed by value
return call_user_func_array('myCallbackMethod',$store1);
}
transpose($store1);
fclose($myfile);
}
Try reading with fscanf().
something like
fscanf($file_link, '%s\n', $temp);
array_push($array, $temp);
should work.
Sukhdev Mohan

PHP Moving an array into different text files?

I've been given a list of data and I need to split it and move it into different text files. I've tried a few things so far but cant seem to get it to work.
<?php
/*
*order the file based on surname (col 2)
*create two new text files - class A and B
*split the source text into two equal lists
*format them: ID, firstname, lastname. all words must be first letter caps
*move each list to a new file.
*close files
*/
//This function converts every attribute/variable passed to it into a sentence case
function Uppercase($convert) {
return ucwords($convert);
}
//This function compares two items to see which one is higher
//src: http://php.net/manual/en/function.usort.php
function cmp($a, $b) {
$compResult = strcmp($a[1], $b[1]);
if ($compResult == 0) {
return strcmp($a[2], $b[2]);
}else {
return $compResult;
}
}
//This function gets rid of the whitespace that is not needed
function cut($c) {
return trim($c, " \n\r\0");
}
//open file
$myfile = fopen("students.csv", "r");
echo "A";
//initialise the array, giving them 'headers'
$array = array();
echo "B";
//sort through the data, moving it to a multidimentional array and setting the first letter in each item to uppercase
$i=0;
while(!feof($myfile)){
$line = fgets($myfile);
$pieces = explode(",", $line);
$array[$i][0] = $pieces[0];
$array[$i][1] = cut(Uppercase($pieces[2]));
$array[$i][2] = cut(Uppercase($pieces[1]));
$i++;
}
echo "C";
//sort the file by the second item in the array
usort($array, "cmp");
echo array_shift($array)."<br>";
echo "D";
//create class files
$fileA = fopen("Class 1.txt", "w");
$fileB = fopen("Class 2.txt", "w");
echo "E";
//get size of array
$arraylength = count($array);
//half the array length(
$half = ceil($arraylength /= 2);
//echo $half;
//echo $arraylength."</br>";
echo "F";
echo "<pre>";
print_r($array);
echo "</br>";
//move the first class into a text file
$k = 0;
foreach ($array as $key){
echo $key[0];
if ($k < $half) {
$current = file_get_contents($fileA);
$current .= $key;
}
}
echo "G";
fclose($fileA);
fclose($fileB);
fclose($myfile);
echo "H";
When this runs, I get the following line recurring for each item in the array
Warning: file_get_contents() expects parameter 1 to be a valid path, resource given in C:\xampp\htdocs\PHPLabs\EE1600Assignment.php on line 93
The document itself has 25 items that look like this:
123, billy, bobs
Any help is appreciated. Thank you
file_get_contents expects a file path, but you are providing a file handler. You probably want instead fgets($fileA).
Alternatively, if you want to read the complete file (it's not entirely clear from your code), you can use fread($fileA).
According to the documentation, file_get_contents requires a path to the file you want to open (as per the error message you're getting - file_get_contents() expects parameter 1 to be a valid path).
You're passing in $fileA - which you created earlier using an fopen call
fopen("Class 1.txt", "w");

How to set variables in an array PHP

I am trying to read in a text file which has 21 names like this;
123, bill, bobs
124, joe, public
I have been able to put them into an array but I don't know how to set each name as a variable, as I need to sort them into alphabetical order based on their last name. This is my code so far;
$file = fopen("students.txt", "r");
If ($file) {
while (!feof($file)) {
$array = explode("/n", fread($file, filesize("students.txt")));
print_r($array);
}
} else {
echo 'File unopened';
}
I have tried the following code but it doesnt seem to work;
fscanf ($fp, "%s, %s, %s/n", $num, $first, $last). "<br/>";
Just read the entire file into an array, and explode each line, then usort the results.
$array = file('your_file.txt');
if(false === $array) {
// you had a problem reading file
exit();
}
$exploded_array = array();
foreach($array as $csv) {
$exploded_array[] = explode(',', $csv)
}
usort($exploded_array, function ($a, $b) {
if ($a[2] == $b[2]) {
return 0;
}
return ($a[2] < $b[2]) ? -1 : 1;
}
You can also look at using fgetscv() instead of the combination of file() and explode(). Either way it is pretty much the same.
Your file related code is overcomplicated.
$users = file('students.txt', FILE_SKIP_EMPTY_LINES);
array_walk($users, function (&$val) {
$newAr = explode(',', $val);
$val = array_map('trim', $newAr);
});
usort($users, function($a, $b) {
return strnatcmp($a[2], $b[2]);
});
var_dump($users);
Example with fake data #3v4l
Alternativly you may use fgetcsv to get the values from the file as #MarkB pointed out in the comments of your question

PHP - How do I open files and read them then write new ones with "x" lines per file?

I posted this question here before but there were no responses. I may have done something wrong so, here it is again with some more details.
The files in the directory are named 1.txt, 2.txt, 3.txt etc.... The snippet below enters that directory, opens all the *,txt files reading them, removes the dupes and creates one file with all the unique contents. (names in this case).
$files = glob($dirname."/*.txt"); //matches all text files
$lines = array();
foreach($files as $file)
{
$lines = array_merge($lines, file($file, FILE_SKIP_EMPTY_LINES | FILE_IGNORE_NEW_LINES));
}
$lines = array_unique($lines);
file_put_contents($dirname."/allofthem.txt", implode("\n", $lines));
}
The above works great for me! Thanks to great help here at stackoverflow.
But, I desire to take it one step further.
Instead of one big duplicate free "allofthem.txt" file, how can I modify the above code to create files with a maximum of 5oo lines each from the new data?
They need to go into a new directory eg $dirname."/done/".$i.".txt" I have tried counting in the loop but my efforts are not working and ended up being a mile long.
I also attempted to push 500 into an array, increment to another array and save that way. No luck. I am just not "getting" it.
Again, this beginner needs some expert assistance. Thanks in advance.
Once you have your array of lines as per your code, you can break it into chunks of 500 lines using array_chunk, and then write each chunk to its own file:
// ... from your code
$lines = array_unique($lines);
$counter = 1;
foreach (array_chunk($lines, 500) as $chunk)
{
file_put_contents($dirname . "/done/" . $counter . ".txt", implode("\n", $chunk));
$counter++;
}
this function will get you somewhere !
function files_identical($fn1, $fn2) {
if(filetype($fn1) !== filetype($fn2))
return FALSE;
if(filesize($fn1) !== filesize($fn2))
return FALSE;
if(!$fp1 = fopen($fn1, 'rb'))
return FALSE;
if(!$fp2 = fopen($fn2, 'rb')) {
fclose($fp1);
return FALSE;
}
$same = TRUE;
while (!feof($fp1) and !feof($fp2))
if(fread($fp1, 4096) !== fread($fp2, 4096)) {
$same = FALSE;
break;
}
if(feof($fp1) !== feof($fp2))
$same = FALSE;
fclose($fp1);
fclose($fp2);
return $same;
}
Src: http://www.php.net/manual/en/function.md5-file.php#94494
$files = glob($dirname."/*.txt"); //matches all text files
$lines = array();
foreach($files as $file)
{
$lines = array_merge($lines, file($file, FILE_SKIP_EMPTY_LINES | FILE_IGNORE_NEW_LINES));
}
$lines = array_unique($lines);
$lines_per_file = 500;
$files = count($lines)/$lines_per_file;
if(count($lines) % $lines_per_file > 0) $files++;
for($i = 0; $i < $files; $i++) {
$write = array_slice($lines, $lines_per_file * $i, $lines_per_file);
file_put_contents($dirname."/done/".$i.".txt", implode("\n", $write));
}

Categories