So I'm trying to append a string at the end of a row. The row and the string is inputted by the user.
//irrelevant...
$row = $_POST["whichRow"];
$Comment = $_POST["stringValue"];
$lines = array();
$arrayWithComment = array(";", "$actualComment");
$lineCount = 0;
foreach(file('/var/www/html/bkbpNew/tickets.csv') as $line){
if ($lineCount == $row){
array_push($lines, $line, $arrayWithComment[0], $arrayWithComment[1]);}
else{
array_push($lines, $line);}
$lineCount++;
}
file_put_contents('/var/www/html/bkbpNew/tickets.csv', $lines);
And that sort of works, but not in the way that I want it to. Here is the edited file before/after & the desired state:
(Input values for this example are comment = "test" and row = 2)
Desired result of edited file:
1;example;example;example;example;example;example
2;example;example;example;example;example;example;test
3;example;example;example;example;example;example
Edited file BEFORE the above code is executed:
1;example;example;example;example;example;example
2;example;example;example;example;example;example
3;example;example;example;example;example;example
Edited file AFTER the above code is executed:
1;example;example;example;example;example;example
2;example;example;example;example;example;example
;test3;example;example;example;example;example;example
it automatically goes into the next line (Desired result) but I don't want it to. How do I go about this? Cheers!
when you use file(), newline characters are included at the end of the line, so when you're adding your new comment to the end of the line you're adding it after the new line character
I'm not a big fan of your approach to this, but as a quick and dirty solution use the FILE_IGNORE_NEW_LINES flag for file(), and then manually re-add the newline characters for each line in your loop
Related
I have a text file with data that looks like this:
#dacdcadcasvsa
#svsdvsd
#
#sfcnakjncfkajnc
I want to keep this line
and this one
How can I remove all lines containing # and echo out the lines that don't so it looks like:
I want to keep this line
and this one
All I know is that I have to get_file_contents($filename). Would I have to put it in an array?
Any tips and guidance would be appreciated.
Using file() and foreach()
$lines = file("a.txt");
foreach ( $lines as $line ) {
if ( $line[0] != '#' ){
echo $line;
}
}
Just update the name of the file.
You can replace all the comment lines with empty strings before you output.
<div style="white-space: pre-line;">
<?= preg_replace('/^#.*\n/m', '', file_get_contents($filename)) ?>
</div>
You're thinking along the right lines; although the PHP method (function) you need is actually file_get_contents(), not get_file_contents() (as per your question).
Let's break it down:
We need a way of separating out our data into sortable chunks. As you stated, the best way to do this is using an array.
We could do this, using the hash symbol (#) as a delimiter - but this
would mean the last chunk of text is a mixture of text we want to
remove, and text we want to keep. Instead, we'll be using line
breaks as our delimiter.
Once the data has been separated, we can work on removing those lines that begin with a hash symbol.
Our code will look something like this:
<?php
// Get the file contents
$fileContents = file_get_contents('my_file.txt'); // This could be any file extension
// Split the file by new lines
$contentsArr = preg_split('/\r\n|\r|\n/', $fileContents);
// Function for removing items from an array - https://stackoverflow.com/questions/9993168/remove-item-from-array-if-item-value-contains-searched-string-character?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa
function myFilter($string) {
return strpos($string, '?') === false;
}
// Remove comment items from array
$newFileContents = array_filter($fileContents, 'myFilter');
// Concatenate and echo out the result
echo implode(",\n",$newFileContents);
An alternate because I was bored:
foreach(preg_grep('/^#/', file($filename), PREG_GREP_INVERT) as $line) {
echo $line;
}
Read file lines into an array
Get all lines NOT starting with ^ the # character
Loop those lines
i have this code:
//This line is for the input that i've looped above my code, it's a URL
$textAr[$i] = str_replace("\r\n","", $textAr[$i]);
//This is for implode purposes
$finalArray = array($textAr[$i], $m1, $m2, $m3, $m4, $m5, $m6);
//When i echo this variable, $test, the URL is in the line along with the implode arrays
$test = implode($finalArray, "***");
echo $test."\n";
//This is for writing into my text file
fwrite($sitesTxt, implode($finalArray, "***")."\n");
I'm having the kind of error where after i input a 3 URLs, the first and second URL has new line after i write in the file, but the last URL I've input is in line along with the imploded arrays. I've even trimmed the $textArr, but i keep getting the new lines.
Expected output:
https://docs.google.com***false***false***false***false***false***false***
https://stackoverflow.com***false***false***false***false***false***false***
https://stackexchange.com***false***false***false***false***false***false***
Output i'm getting at the txt file:
https://docs.google.com
***false***false***false***false***false***false***
https://stackoverflow.com
***false***false***false***false***false***false***
https://stackexchange.com***false***false***false***false***false***false***
Depending on your system, your lines may not end with a \r\n combination, but perhaps just \r.
I suggest either change str_replace to:
$textAr[$i] = str_replace(array("\r","\n"),"", $textAr[$i]);
Or, change the array:
$finalArray = array(trim($textAr[$i]), $m1, $m2, $m3, $m4, $m5, $m6);
Incidentally, although it will work, your implode parameters are reversed:
$test = implode("***", $finalArray);
You should use PHP_EOL constant for 'break-line' character. Because the break-line character in DOS is \r\n, but in *nix, it's just \n.
So, you replace the first line to
$textAr[$i] = str_replace(PHP_EOL, '', $textAr[$i]);
I have following data in text file
375020222511963
284970411563422
290245594366931
I need to retrieve a random variable from the above text file.
I use the following php code to do that
<?php
$file = file("file.txt");
$len = count($file);
$rand = rand ( 0, $len-1 );
echo $file[$rand];
?>
But it's returning new line along with the retrieved data. I need to retrieve data without new line.
The file() function has an optional second argument taking a bit mask of flags which affect what is returned in the array.
Available flags are FILE_USE_INCLUDE_PATH, FILE_IGNORE_NEW_LINES, and SKIP_EMPTY_LINES. The FILE_IGNORE_NEW_LINES is the one that you want to use in order to have each line in the array not include the trailing newline character.
So, your line of code should look like the following.
$file = file("file.txt", FILE_IGNORE_NEW_LINES);
Descriptions and more info, see http://php.net/file.
Change last line to:
echo trim($file[$rand]);
trim() removes white-spaces (blanks, new lines, tabs) from the beginning and end of a string.
In order to avoid empty lines... If the last line is always the only empty one:
$rand = rand (0, $len - 2); // Instead of -1
Else, if you can have empty lines everywhere, replace the last two lines of code with:
do {
$rand = rand (0, $len - 1);
} while (trim($file[$rand]) == '');
echo $file[$rand];
I need to find a specic line of text, from a text-file,
and then copy it to a new text-file:
1: I have a text file with several lines of text, eg:
JOHN
MIKE
BEN
*BJAMES
PETE
2: So, I read that text-files contents into an array,
with each line of text, placed into a seperate element of the array.
3: Then I tested each element of the array,
to find the line that starts with, say: *B ie:
if ( preg_match( "/^\*(B)/",$contents[$a] ) )
Which works ok...
4: Then I copy (WRITE) that line of text, to a new text-file.
Q: So how can I remove the '*B' from that line of text,
BEFORE I WRITE it to the new text-file ?
If you already use preg_match, you can modify your regex to get what you want in another variable.
if (preg_match('/^\*B(.*)$/', $contens[$a], $matches)
{
fwrite($targetPointer, $matches[1]);
}
After using preg_matchthe variable $matches holds the single matches of subparts of the regex enclosed in brackets. So the relevant part of your line ist matched by (.*) and saved into $matches[1].
This approach writes the lines as the file is read, which is more memory efficient:
$sourceFile = new SplFileObject('source.txt');
$destinationFile = new SplFileObject('destination.txt', 'w+');
foreach (new RegexIterator($sourceFile, '/^\*B.*/') as $filteredLine) {
$destinationFile->fwrite(
substr_replace($filteredLine, '', 0, 2)
);
}
demo
With substr or preg_replace.
Have a try with:
preg_replace('/^\*B/', '', $content[$a], -1, $count);
if ($count) {
fwrite($file, $content[$a]);
}
Question 1: How can I manually move the fgetc file pointer from its current location to the next line?
I'm reading in data character by character until a specified number of delimiters are counted. Once the delimiter count reaches a certain number, it needs to copy the remainder of the line until a new line (the record delimiter). Then I need to start copying character by character again starting at the next record.
Question 2: Is manually moving the file pointer to the next line the right idea? I would just explode(at "\n") but I have to count the pipe delimiters first because "\n" isn't always the record delimiter.
Here's my code (it puts all the data into the correct record until it reaches the last delimiter '|' in the record. It then puts the rest of the line into the next record because I haven't figured out how to make it correctly look for the '\n' after specified # of | are counted):
$file=fopen("source_data.txt","r") or exit ("File Open Error");
$record_incrementor = 0;
$pipe_counter = 0;
while (!feof($file))
{
$char_buffer = fgetc($file);
$str_buffer[] = $char_buffer;
if($char_buffer == '|')
{
$pipe_counter++;
}
if($pipe_counter == 46) //Maybe Change to 46
{
$database[$record_incrementor] = $str_buffer;
$record_incrementor++;
$str_buffer = NULL;
$pipe_counter = 0;
}
}
Sample Data:
1378|2009-12-13 11:51:45.783000000|"Pro" |"B13F28"||""|1||""|""|""|||False|||""|""|""|""||""||||||2010-12-15 11:51:51.330000000|108||||||""||||||False|""|""|False|""|||False
1379|2009-12-13 12:23:23.327000000|"TLUG"|"TUG"||""|1||""|""|""|||False|||""|""|""|""||""||||||1943-04-19 00:00:00|||||||""||||||False|""|""|False|""|||False
I'd say that doing this via file handling functions is a bit clumsy, when it could be done via regular expression quite easily. Just read the entire file into a string using file_get_contents() and doing a regular expression like /^(([^|]*\|){47}([^\r\n]*))/m with preg_match_all() could find you all the rows (which you can then explode() using | as the delimiter and setting 48 as the limit for number of fields.
Here is a working example function. The function takes the file name, field delimiter and the number of fields per row as the arguments. The function returns 2 dimensional array where first index is the data row number and the second is the field number.
function loadPipeData ($file, $delim = '|', $fieldCount = 48)
{
$contents = file_get_contents($file);
$d = preg_quote($delim, '/');
preg_match_all("/^(([^$d]*$d){" . ($fieldCount - 1) . '}([^\r\n]*))/m', $contents, $match);
$return = array();
foreach ($match[0] as $line)
{
$return[] = explode($delim, $line, $fieldCount);
}
return $return;
}
var_dump(loadPipeData('source_data.txt'));
(Note: this is a solution to the original problem)
You can read to the end of the line like this:
while (!feof($file) && fgetc($file) !== '\n');
As for whether or not fgetc is the right way to do this... your format makes it difficult to use anything else. You can't split on \n, because there may be newlines within a field, and you can't split on |, because the end of the record doesn't have a pipe.
The only other option I can think is to use preg_match_all:
$buffer = file_get_contents('test.txt');
preg_match_all('/((?:[^|]*\|){45}[^\n]*\n)/', $buffer, $matches);
foreach ($matches[0] as $row) {
$fields = explode('|', $row);
}
Answer to the modified question:
To read from the file pointer to the end of the line, you can simply use the file reading function fgets(). It returns everything from the current file pointer position until it reaches the end of the line (and also returns the end of the line character(s)). After the function call, the file reading pointer has been moved to the beginning of the next line.