I want to do if conditional between text data and variable data then delete the line
Example
I have a txt data with usernames like ( one two one three one) every user in line,
And i want to delete all data except "one" username
My Code;
if(file_get_contents('visitors.txt') != "one") {
$GetLine = ;
function removeLine ($url, $lineToRemove)
{
$data = file_get_contents($url);
$lines = explode(PHP_EOL, $data);
$lineNo = 1;
foreach($lines as $line)
{
$linesArray[$lineNo] = $line;
$lineNo++;
}
unset($linesArray[$lineToRemove]);
return implode("\n", $linesArray);
}
$data = removeLine ("username.txt", $getLine);
echo $data
}
the function is used to remove lines.
My problem is doing if with the data + $getLine number, I just want to remove all the lines except line that has one word.
Can simply do it with a regular expression:
$file = preg_grep('#one#', file('file.txt'));
This will make $file an array holding only lines containing the string "one". To turn the array back into a string, you just implode it.
If you only want to echo the lines containing "one", you can also use iterators:
$file = new RegexIterator(new SplFileObject("file.txt"), '#one#');
foreach ($file as $content) {
echo $content, PHP_EOL;
}
This will go over the file line by line and echo any line having the string one in it. The benefit is that it doesn't use two arrays as intermediate structures.
Just a note, you shouldn't be defining functions inside an if statement.
Also, unless I'm misunderstanding, you shouldn't even need line numbers.
function remove_line( $data, $remove ){
$lines = explode( PHP_EOL, $data ); // Convert to Array
$new_lines = ''; // Start a new variable we'll add to in a loop
foreach( $lines as $line ){
$line = trim( $line ); // Trim Whitespace
if( $line != $remove ){
// Line isn't a line we want removed, so save it plus an EOL
$new_lines .= $line.PHP_EOL;
}
}
return $new_lines;
}
Now if you load in a file like so: $file = file_get_contents( 'my-file.txt' ); that contains the following:
One
Two
One
Three
One
Once you run it through the remove_line function, you'll end up something like:
$file = file_get_contents( 'my-file.txt' );
$new_file = remove_line( $file, 'One' );
var_dump( $new_file ); // Returns: string(10) "Two Three "
Related
I have a txt file which has a lot of lines and the values in every line are separated with commas.
I want to read the 1st line alone which I did already using fgets :
$head = fgets(fopen($file, 'r'));
$headValues = explode(',', $head);
but now I want to read every other line from line 2 until the end of file and put those values into an array.
I searched for similar solutions but couldn't find any
Just use descriptor
$fd = fopen($file, 'r');
$head = fgets($fd);
$headValues = explode(',', $head);
$data = [];
while(($str = fgets($fd)) !== false) {
$otherValues = explode(',', $str);
$data[] = $otherValues;
}
This uses fgetcsv for the lines you care about and uses array_combine to put the headers and the line data together.
$fh = fopen($file, 'r');
$headValues = fgetcsv($fh);
$data = [];
while (true) {
if ( ($values = fgetcsv($fh)) === false ) {
break;
}
$data[] = array_combine($headValues, $values);
if ( fgets($fh) === false ) {
break;
}
}
fclose($fh);
print_r($data);
It checks at each read in case the EOF has been reached and then breaks out of the read loop.
You could use file(), array_map() and array_shift() :
$lines = file($file) ; // get file as array.
$lines = array_map(function($l){ return explode(',', $l); }, $lines);
$headValues = array_shift($lines); // get first values (removed from $lines)
So, $lines will contains all lines except the first one.
I am facing some problems while converting a set of semicolon delimited strings to json.
The input string:
si;dialed_no;connect_time;duration;region;call_cost
0;918592877727;2015-08-25 18:51:01;21;India(91);0.029
1;918907777727;2015-08-25 19:04:08;220;India(91);0.232
2;918907777727;2015-08-25 19:09:50;40;India(91);0.058
3;918907777727;2015-08-25 19:10:46;69;India(91);0.087
4;919048232151;2015-08-26 13:30:24;19;India(91);0.029
5;919895842822;2015-08-26 14:23:35;423;India(91);0.435
My code:
function my_wrap($val) {
return '{"test":"' . $val. '"}';
}
$parts = explode(';', $string);
$parts = array_map('my_wrap', $parts);
$json = '[' . implode(',', $parts) . ']';
echo $json;
And the output is like:
[{"test":"dialed_no"},{"test":"connect_time"},{"test":"duration"},{"test":"region"},{"test":"call_cost 0"},{"test":"918592877727"},{"test":"2015-08-25 18:51:01"},{"test":"21"},{"test":"India(91)"},{"test":"0.029 1"},{"test":"918907777727"},{"test":"2015-08-25 19:04:08"},{"test":"220"},{"test":"India(91)"},{"test":"0.232 2"},{"test":"918907777727"},{"test":"2015-08-25 19:09:50"},{"test":"40"},{"test":"India(91)"},{"test":"0.058 3"},{"test":"918907777727"},{"test":"2015-08-25 19:10:46"},{"test":"69"},{"test":"India(91)"},{"test":"0.087 4"},{"test":"919048232151"},{"test":"2015-08-26 13:30:24"},{"test":"19"},{"test":"India(91)"},{"test":"0.029 5"},{"test":"919895842822"},{"test":"2015-08-26 14:23:35"},{"test":"423"},{"test":"India(91)"},{"test":"0.435 6"},{"test":"8801711788025"},{"test":"2015-08-30 19:29:48"},{"test":"1"},{"test":"Bangladesh(880)"},{"test":"0.029 7"},{"test":"8801711788025"},{"test":"2015-08-30 19:29:57"},{"test":"2"},{"test":"Bangladesh(880)"},{"test":"0.029 8"},{"test":"8801711788025"},{"test":"2015-08-30 19:30:07"},{"test":"2"},{"test":"Bangladesh(880)"},{"test":"0.029 9"},{"test":"8801711788025"},{"test":"2015-08-30 19:30:17"},{"test":"1"},{"test":"Bangladesh(880)"},{"test":"0.029 10"},{"test":"8801711788025"},{"test":"2015-08-30 21:24:31"},{"test":"88"},{"test":"Bangladesh(880)"},{"test":"0.087 11"},{"test":"8801833316038"},{"test":"2015-08-31 12:06:15"},{"test":"5"},{"test":"Bangladesh(880)"},{"test":"0.029 12"}]
What I want is like:
[{si:"0",dialed_no:"91xxx",connect_time:"2015-08-25 18:51:01"}, {si:"1",dialed_no:"9184sd",connect_time:"2015-08-25 18:51:01"}]
and so on...
Note: I am getting the above input string from a API URL and not from a csv file or something.
Can you try this code and see if it works as you want?
//we split the single lines
$lines = explode("\n", $string);
$linesArray = array();
//we split each line in a set of elements
foreach($lines as $line){
$linesArray[] = explode(";",$line);
}
//we use the first line of data as an array of headers
$headers = $linesArray[0];
//and remove it
unset($linesArray[0]);
$jsonArray = [];
foreach($linesArray as $l=>$ln){
foreach($ln as $k=>$part){
//we re-build an array with the right headers
$jsonArray[$l][$headers[$k]] = $part;
}
}
print json_encode($jsonArray);
What you described as the output you want is not JSON.
Don't invent your own routines when PHP already has perfectly good ones (e.g. for JSON encoding and CSV parsing).
Assuming that the data is starting in a file....
$data=array();
$y=0;
$header=fgtetcsv($file_handle, 0, ';');
while (!feof($file_handle)) {
$row=fgtetcsv($file_handle, 0, ';');
foreach ($row as $x=>$value) {
$data[$y][$header[$x]]=$value;
}
$y++;
}
print json_encode($data);
Of course this will need some tweaks to handle error conditions and possibly for datasets larger than the working memory of php.
<?php
$records = array_map(
function($e) { // 2: to each line/record apply this functions
return str_getcsv($e, ';'); // 3: split the line/record into fields
},
explode( "\n", data() ) // 1: split data into "lines"/records
);
// 4: now $records is an array of records, each being an array of fields
$fields = array_shift($records); // 5: first record contains the field names, remove from array and assign to $fields
$records = array_map(
function($e) use ($fields) { // 7: this function has access to $fields, i.e. the names of the fields
return array_combine($fields, $e); // 8: see http://docs.php.net/array_combine
},
$records // 6: apply the function above to each element, i.e. record, in $records
);
echo json_encode($records);
function data() {
return <<< eot
si;dialed_no;connect_time;duration;region;call_cost
0;918592877727;2015-08-25 18:51:01;21;India(91);0.029
1;918907777727;2015-08-25 19:04:08;220;India(91);0.232
2;918907777727;2015-08-25 19:09:50;40;India(91);0.058
3;918907777727;2015-08-25 19:10:46;69;India(91);0.087
4;919048232151;2015-08-26 13:30:24;19;India(91);0.029
5;919895842822;2015-08-26 14:23:35;423;India(91);0.435
eot;
}
While I appreciate that VolkerK is using a lot of the right functions, I find that functional syntax creates too much bloat and makes the code harder to read. Furthermore, this task can be accomplished in a single loop and therefore it should be.
Code: (Demo)
$input = <<<SSV
si;dialed_no;connect_time;duration;region;call_cost
0;918592877727;2015-08-25 18:51:01;21;India(91);0.029
1;918907777727;2015-08-25 19:04:08;220;India(91);0.232
2;918907777727;2015-08-25 19:09:50;40;India(91);0.058
3;918907777727;2015-08-25 19:10:46;69;India(91);0.087
4;919048232151;2015-08-26 13:30:24;19;India(91);0.029
5;919895842822;2015-08-26 14:23:35;423;India(91);0.435
SSV;
$lines = explode(PHP_EOL, $input);
$header = str_getcsv(array_shift($lines), ';');
foreach ($lines as $line) {
$result[] = array_combine($header, str_getcsv($line, ';'));
}
echo json_encode($result, JSON_PRETTY_PRINT);
A note to the OP, you must not manually craft a json string. Always rely on the accuracy of json_encode() -- it won't fail you.
I have this script that extracts a .csv file from the database that holds data for different locals that a user has logged into. The .csv files come like this:
"id_user";"id_local"
"1";""
"2";"2,3,4"
"3";""
"5";"2,5"
"10";""
"13";"2"
"14";"5"
"15";"2"
"16";"1"
"20";"2"
"21";""
As you can se, it get one register per user
But, to manipulate it properly, we need it like this:
"id_user";"id_local"
"2";"2"
"2";"3
"2";"4"
"5";"2"
"5";"5"
"13";"2"
"14";"5"
"15";"2"
"16";"1"
"20";"2"
So, I need to create a function that deletes users with no local and splits different locals of the same user in different registers. Does anyone knows how can I do it?
Here is the code I have so far but I'm not sure if I'm on the right way:
function fix_local_secundario(){
$filename = "local_secundario.csv";
$file_locais = file_get_contents($filename);
$locais = explode("\n", $file_locais);
// $pattern = "/,/";
// $replacement = "\"\n;\"";
while ($line = current($locais)) {
$line = str_getcsv($line, ';', '"','\n');
// $line = preg_replace($pattern, $replacement, $line);
var_dump($line);
echo "\n";
next($locais);
}
}
Try this and see if this works:
function fix_local_secundario(){
$filename = "local_secundario.csv";
$file_locais = file_get_contents($filename);
$locais = explode("\n", $file_locais);
while ($line = current($locais)) {
// do first split on ; character
$arr1 = explode(";", $line);
// if the part after ; is not empty for this line
if ($arr1[1]!='""'){
// split it further on , character
$arr2 = explode(",", $arr1[1]);
foreach ($arr2 as $key => $val){
if($val[0] != '"'){
$val = '"'.$val;
}
if($val[strlen($val)-1] != '"'){
$val = $val . '"';
}
echo $arr1[0] . ";" . $val . "<BR>";
}
}
next($locais);
}
}
Once this basic piece is working, you should change it to return values rather than echo values since this code is part of a function as per updates made to your question.
What about this…
$f = fopen("myfile.csv", "r");
while($row = fgetcsv($f, 0, ";")){
$locals = explode(",", $row[1]);
if (count($locals)>1){
foreach($locals as $local)
// iterate with $row[0] and $local
}elseif($row[1] != "")
// use $row[0] and $row[1]
}
I've got a large flat file of usernames and emails in the following format:
"username", "email"
"username", "email"
"username", "email"
etc...
I need to take the email and search for the username, but for some reason it will not return a result. It works if I search opposite.
$string = "user_email#something.com";
$filename = "user_email.txt";
$h = fopen("$filename","r");
$flag=0;
while (!feof ($h)) {
$buffer = fgets($h);
$thisarray = split(",", $buffer);
if ($string == str_replace('"','', $thisarray[1])) {
$i = 1;
$i++;
echo '<td bgcolor="#CCFFCC"><b style="color: maroon">' . str_replace('"','',$thisarray[0]). '</b></td>';
}
Any ideas? Thanks!
As per reko_t's suggestion: Use fgetcsv to read individual lines of csv into arrays, until you find one where the second element matches your search term. The first element then is the username. Something like:
<?php
function find_user($filename, $email) {
$f = fopen($filename, "r");
$result = false;
while ($row = fgetcsv($f)) {
if ($row[1] == $email) {
$result = $row[0];
break;
}
}
fclose($f);
return $result;
}
You may use fgetcsv() directly
$string = "user_email#something.com";
$filename = "user_email.txt";
$h = fopen("$filename","r");
$flag=0;
while (!feof ($h)) {
list($username, $email= fgetcsv($h);
if ($string == $email) { /* do something */ }
}
fgetcsv() (as a nice side effect) also removes the "field enclosures" (the double quotes ") for you, if they exists.
Your own example probably does not work, because if you have such a line
"username", "email"
splitting at , will result in
'"username"'
' "email"'
Notice the whitespace before "email", that you forgot to remove. Additional using str_replace() to remove the surrounding quotes is quite unsafe. Have a look at trim().
First, just use file() to get the contents of the file into an array:
$file_contents = file( $filename, 'r' );
Now loop through the contents of the array, splitting the strings and examining the email address:
foreach ( $file_contents as $line ) {
list ( $username, $email ) = str_split( ',' $line );
if ( trim( $email ) == $string ) {
// A match was found. Take appropriate action.
}
}
I think the easiest solution is to use file() with str_getcsv().
The code would be something like this:
foreach (file($fileName, FILE_SKIP_EMPTY_LINES) as $line) {
$columns = str_getcsv($line); // Where $columns[0] and $columns[1] hold the username and email respectively.
}
I truly believe that all examples in other answers works!
But all they are slow, because all of them travers each line in csv file...
I have another example how to find desired string:
$command = sprintf("grep '%s,%s' -Er %s", $userName, $email, $file);
$result = `$command`;
Yes it some kind of dark matter, but it really works and it really fast!
While fgetcsv is potentially a more elegant solution, that doesn't answer your original question: your second array element has a newline, and you're comparing against a string that doesn't.
To fix:
if ($string == str_replace('"','', chop($thisarray[1]))) {
I need to read the data from a file that can be either comma or tab delimited. I now that there is a function getcsv but it accepts only one possible delimiter.
Any ideas how to handle this?
Thanks.
Starting from PHP 5.3, you can use str_getcsv() to read individual lines using different delimiters.
$someCondition = someConditionToDetermineTabOrComma();
$delimiter = $someCondition ? "," : "\t";
$fp = fopen('mydata.csv', 'r');
while ( !feof($fp) )
{
$line = fgets($fp, 2048);
$data = str_getcsv($line, $delimiter);
doSomethingWithData($data);
}
fclose($fp);
You can specify a delimiter for fgetcsv(). This is an example of reading tab-delimited files,
while (($data = fgetcsv($handle, 1000, "\t")) !== FALSE) {
...
}
Here is an example that will read mydata.txt CSV fields
$tab = "\t";
$fp = fopen('mydata.txt', 'r');
while ( !feof($fp) )
{
$line = fgets($fp, 2048);
$data_txt = str_getcsv($line, $tab);
//Get First Line of Data over here
print_r($data_txt);
exit;
}
fclose($fp);
$filePath = "somefile.txt";
$delimiter = "\t";
$file = new \SplFileObject($filePath);
while (!$file->eof()) {
$line = $file->fgetcsv($delimiter);
print_r($line);
}
Read the whole file, or line by line and split it using split.
There you can include a regex with arbitrary delimiters. I have not PHP here to test a statement, but php.net -> search for split().
There you also have a comment relating to regex.
you can try explode
explode ( string $delimiter , string $string [, int $limit ] );
Here is the function that I added to my utilities library for future use. I derived it from NSSec's answer.
This solution allows you to specify whether you want to use the first line as keys for the array. I will probably add the ability to pass an array to be used for keys for the $first_line_keys parameter at some point.
/**
* Converts a CSV file into an array
* NOTE: file does NOT have to have .csv extension
*
* $file - path to file to convert (string)
* $delimiter - field delimiter (string)
* $first_line_keys - use first line as array keys (bool)
* $line_lenght - set length to retrieve for each line (int)
*/
public static function CSVToArray($file, $delimiter = ',', $first_line_keys = true, $line_length = 2048){
// file doesn't exist
if( !file_exists($file) ){
return false;
}
// open file
$fp = fopen($file, 'r');
// add each line to array
$csv_array = array();
while( !feof($fp) ){
// get current line
$line = fgets($fp, $line_length);
// line to array
$data = str_getcsv($line, $delimiter);
// keys/data count mismatch
if( isset($keys) && count($keys) != count($data) ){
// skip to next line
continue;
// first line, first line should be keys
}else if( $first_line_keys && !isset($keys) ){
// use line data for keys
$keys = $data;
// first line used as keys
}else if($first_line_keys){
// add as associative array
$csv_array[] = array_combine($keys, $data);
// first line NOT used for keys
}else{
// add as numeric array
$csv_array[] = $data;
}
}
// close file
fclose($fp);
// nothing found
if(!$csv_array){
return array();
}
// return csv array
return $csv_array;
} // CSVToArray()