I have this text file:
https://drive.google.com/file/d/0B_1cAszh75fYSjNPZFRPb0trOFE/view?usp=sharing
I can print it using the following code:
$file = fopen("gl20160630.txt","r");
while(! feof($file))
{
echo fgets($file). "<br />";
}
fclose($file);
But it looks like this:
I want the contents of this text file to be separated into four columns -Line, Description, Legacy GL Code and Closing Balance. If any one of these columns is empty it should remain empty. I just want to print those lines that start with ====>
Could you please help me find a way to print the text file like the way I want?
It's actually pretty simple, since your file has a strict number of character for each column.
All you need to do is a substr on each line starting by '====>{line}', then you can read each column by there position in the file.
Here is an example using your file :
$file = fopen("gl20160630.txt","r");
while(! feof($file))
{
$fullLine = fgets($file);
$line = substr($fullLine, 5, 4);
if (is_numeric($line)) {
$liability = trim(substr($fullLine, 10, 30));
$legacy = trim(substr($fullLine, 40, 39));
$balance = trim(substr($fullLine, 79, 15));
if ($liability != null && $legacy != null && $balance != null)
echo $line." ".$liability." ".$legacy." ".$balance."\n";
}
}
fclose($file);
You can see that all I do is:
check if the character in the column 'Line' are numbers
then I get all the other element
I 'clean' them by getting rid of unwanted characters (spaces, ...) with trim
After that, I check that all elements are filed
And I finally display them
I hope that this will help you, have a nice day ;)
Related
I have to write a function that return the sum of all the numbers in a file.
The text file is numbers.txt:
1
1
2
3
5
8
13
21
The code I write is:
function sumFromFileInput($fileName) {
$total = 0;
$file = fopen("numbers.txt", "r");
while ($number = fgets($file)) {
$total += $number;
}
fclose($file);
return $total;
}
The output should be 54 whereas my output is 124712203354.
Please help me to figure out what I did wrong.
You can use file() for this purpose and simplifiy your code:
$trimmed = file('<provide file path here>', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
$sum = array_sum($trimmed);
echo $sum;
In case you added values as string into file then you need to convert them to Integer first.
Add below line before array_sum() line:
$trimmed = array_map('intval', $trimmed);
function sumFromFileInput($fileName) {
$total = 0;
$file = fopen("numbers.txt", "r");
while (!feof($file)) { #this will give you a true value until it reaches end of the numbers.txt last line
$total += (int) fgets($file); # this will read file lines one by one
}
fclose($file);
return $total;
}
What happens if you modify your code to be like this:
function sumFromFileInput($fileName) {
$total = 0;
$file = fopen("numbers.txt", "r");
while ($number = fgets($file)) {
// Making sure to add integer values here
$total += (int)$number;
}
fclose($file);
return $total;
}
I have the feeling that your number values from your input file are being read in as strings instead of ints. Using something like (int) should be able to help with this type of issue. You could also potentially use (integer) or intval() instead of (int) for the conversion part. More info about this can be found here.
Update:
After seeing CBroe's comment, I removed my earlier part about the string concatenation conjecture.
When checking the sumFromFileInput() function locally and using var_dump($number) to show the $number variable's type, I can verify that it is a string. This is why I still recommend using something like (int), like in my added lines of code earlier in this answer. Without doing that, I get PHP notices in PHP 7.3.19 for these values that read like: PHP Notice: A non well formed numeric value encountered in [...].
Interestingly enough, though, I still get a total of 54 (as an int) with your original posted code. This gets me to thinking: it would be interesting to see the code you used to call your sumFromFileInput() function, because perhaps that might help explain why your output was what now appears to me to be a running sum total of the $total.
Also, this might not be as important, but it looks like your $fileName parameter isn't currently being used in your sumFromFileInput() function. Maybe this could be connected in the future?
I have a text file like this:
1
2
3
4
5
6
7
8
9
10
And I want to remove specific lines which numbers are in an array like this:
$myfile='txt.txt';
$remove=array(1,3,6,7,10);
//wanna remove these lines
So I tried this code but It didn't work and It just doubles the text and ruins everything:
<?php
$myfile='txt.txt';
$remove=array(1,3,5,7,10);
$lines=file($myfile);
$countline=sizeof($lines);
$data=file_get_contents($myfile);
for ($i=0; $i < $countline+1; $i++) {
if (in_array($i, $remove)) {
$editeddata=str_replace($lines[$i], "", $data);
$removeline = file_put_contents($myfile, $editeddata.PHP_EOL , FILE_APPEND | LOCK_EX);
}
}
?>
I couldn't use ((for)) properly and I think it will just ruin the text because it deletes lines one after another have been deleted and it changes the order so I should have a code to remove them all at once.
And please don't give a code to just replace numbers because the main text file is not only numbers and contains word,etc...
Thanks A lot!
You're reading the file twice (with file and file_get_contents), which I think is confusing the later code. You have everything you need with the first call - an array of all the lines in the file. You're also using str_replace to remove the content, which seems a bit dangerous if any of the content is repeated.
I'd refactor this to simply filter the array of lines based on their line-number, then write it back to the file in a single operation:
$myfile = 'txt.txt';
$remove = [1, 3, 5, 7, 10];
// Read file into memory
$lines = file($myfile);
// Filter lines based on line number (+1 because the array is zero-indexed)
$lines = array_filter($lines, function($lineNumber) use ($remove) {
return !in_array($lineNumber + 1, $remove);
}, ARRAY_FILTER_USE_KEY);
// Re-assemble the output (the lines already have a line-break at the end)
$output = implode('', $lines);
// Write back to file
file_put_contents($myfile, $output);
If the file fits in memory then you can do the simple:
$myfile='txt.txt';
$remove=array(1,3,6,7,10);
file_put_contents($myfile, implode(PHP_EOL,array_diff($file($myfile,FILE_IGNORE_NEW_LINES), $remove)));
Note: Because it's a bit ambiguous whether $remove has the content or the lines you want to remove, the above code removes the content . If you want to remove lines change array_diff($file($myfile,FILE_IGNORE_NEW_LINES), $remove) to array_diff_keys($file($myfile,FILE_IGNORE_NEW_LINES), array_flip($remove))
If your file is large then you need to resort to some sort of streaming. I suggest against reading and writing to the same file and doing something like:
$myfile='txt.txt';
$remove=array(1,3,6,7,10);
$h = fopen($myfile,"r");
$tmp = fopen($myfile.".tmp", "w");
while (($line = fgets($h)) !== false) {
if (!in_array(rtrim($line, PHP_EOL), $remove)) {
fwrite($tmp, $line);
}
}
fclose($h);
fclose($tmp);
unlink($myfile);
rename($myfile.".tmp", $myfile);
Iam creating a simple PHP application, where is a csv file upload then an .stm(its a simple text file) file download. The records must be write at given byte position. For example: 1st record position 1, length 2, 2nd record, etc.Records
So Im trying to use fwrite, fseek to get to given position, for example I dont need 2 record to be filled, so I jump to position 11 but there are NUL characters in the file.
Code:
$input = $sFileName;
//a nevbol kiszedni a datumot, majd EEEEHHNN verziora konvertalni
$get_date_from_name = str_replace(".","",substr($sFileName,0,10));
$output = $get_date_from_name . '_mpl_tensoft_import.stm';
$_SESSION['file_name'] = $output;
if (false !== ($ih = fopen($input, 'r'))) {
$oh = fopen($output, 'w+b');
//Create first line of the file 11 record type
fwrite($oh,"11");
fseek($oh, 11);
fwrite($oh,"120967120159857100100007");
/*while (false !== ($data = fgetcsv($ih,0,";"))) {
// this is where you build your new row
//Interne cislo, Dodavatel, Dodavacie c.faktury Celk.suma, Dátum prijatia, Dátum splat. = Datum uhrady, Predmet
$outputData = array($data[0], $data[1], $data[2], $data[3], $data[12], $data[13], $data[36] );
fputcsv($oh, $outputData);
}*/
fclose($ih);
fclose($oh);
unlink($input);
}
Result is:
11NULNULNULNULNULNULNULNULNUL120967120159857100100007
Visual Studio Code gives an error that the file is binary or to large or uses an unsupported encoding.
Notepad++ adds the NUL characters.
Should I just use a whitespace character? 1 whitespace character equals 1 byte? The file should be in CP852 encoding
Thanks for the help and pointing in to the right direction.
Your seek() offset seems to be "out of range".
Documentation said :
In general, it is allowed to seek past the end-of-file; if data is then written, reads in any unwritten region between the end-of-file and the sought position will yield bytes with value 0.
EDIT :
If you want to put the second number at offset 13, using spaces, you could do something like this :
$ban_pos = 13 ;
$num = "11" ;
$pos = $ban_pos - strlen($num) ;
$ban = "120967120159857100100007" ;
$oh = fopen($output, 'w+');
fwrite($oh, $num);
fwrite($oh, str_repeat(' ', $pos));
fwrite($oh, $ban);
fclose($oh);
The file will contains :
11 120967120159857100100007
I am working on reading a file in php.
I need to read specific lines of the file.
I used this code:
fseek($file_handle,$start);
while (!feof($file_handle))
{
///Get and read the line of the file pointed at.
$line = fgets($file_handle);
$lineArray .= $line."LINE_SEPARATOR";
processLine($lineArray, $linecount, $logger, $xmlReply);
$counter++;
}
fclose($file_handle);
However I realized that the fseek() takes the number of bytes and not the line number.
Does PHP have other function that bases its pointer in line numbers?
Or do I have to read the file from the start every time, and have a
counter until my desired line number is read?
I'm looking for an efficient algorithm, stepping over 500-1000 Kb file to get to the desired line seems inefficient.
Use SplFileObject::seek
$file = new SplFileObject('yourfile.txt');
$file->seek(123); // seek to line 124 (0-based)
Does this work for you?
$file = "name-of-my-file.txt";
$lines = file( $file );
echo $lines[67]; // echos line 68 (lines numbers start at 0 (replace 68 with whatever))
You would obviously need to check the lines exists before printing though. Any good?
You could do like:
$lines = file($filename); //file in to an array
echo $lines[1]; //line 2
OR
$line = 0;
$fh = fopen($myFile, 'r');
while (($buffer = fgets($fh)) !== FALSE) {
if ($line == 1) {
// $buffer is the second line.
break;
}
$line++;
}
You must read from the beginning. But if the file never/rarely changes, you could cache the line offsets somewhere else, perhaps in another file.
Try this,the simplest one
$buffer=explode("\n",file_get_contents("filename"));//Split data to array for each "\n"
Now the buffer is an array and each array index contain each lines;
To get the 5th line
echo $buffer[4];
You could use function file($filename) . This function reads data from the file into array.
Thank you for taking the time to read this and I will appreciate every single response no mater the quality of content. :)
Using php, I'm trying to create a script which will delete several lines within a text file (.txt) if required, based upon whether the line starts with a 0 or a negative number. Each line within the file will always start with a number, and I need to erase all the neutral and/or negative numbers.
The main part I'm struggling with is that the content within the text file isn't static (e.g. contain x number of lines/words etc.) Infact, it is automatically updated every 5 minutes with several lines. Therefore, I'd like all the lines containing a neutral or negative number to be removed.
The text file follows the structure:
-29 aullah1
0 name
4 username
4 user
6 player
If possible, I'd like Line 1 and 2 removed, since it begins with a neutral/negative number. At points, there maybe times when there are more than two neutral/negative numbers.
All assistance is appreciated and I look forward to your replies; thank you. :) If I didn't explain anything clearly and/or you'd like me to explain in more detail, please reply. :)
Thank you.
Example:
$file = file("mytextfile.txt");
$newLines = array();
foreach ($file as $line)
if (preg_match("/^(-\d+|0)/", $line) === 0)
$newLines[] = chop($line);
$newFile = implode("\n", $newLines);
file_put_contents("mytextfile.txt", $newFile);
It is important that you chop() the newline character off of the end of the line so you don't end up with empty space. Tested successfully.
Something on these lines i guess, it is untested.
$newContent = "";
$lines = explode("\n" , $content);
foreach($lines as $line){
$fChar = substr($line , 0 , 1);
if($fChar == "0" || $fChar == "-") continue;
else $newContent .= $line."\n";
}
If the file is big, its better to read it line by line as:
$fh_r = fopen("input.txt", "r"); // open file to read.
$fh_w = fopen("output.txt", "w"); // open file to write.
while (!feof($fh_r)) { // loop till lines are left in the input file.
$buffer = fgets($fh_r); // read input file line by line.
// if line begins with num other than 0 or -ve num write it.
if(!preg_match('/^(0|-\d+)\b/',$buffer)) {
fwrite($fh_w,$buffer);
}
}
fclose($fh_r);
fclose($fh_w);
Note: Err checking not included.
file_put_contents($newfile,
implode(
preg_grep('~^[1-9]~',
file($oldfile))));
php is not particularly elegant, but still...
Load whole line into variable trim it and then check if first letter is - or 0.
$newContent = "";
$lines = explode("\n" , $content);
foreach($lines as $line){
$fChar = $line[0];
if(!($fChar == '0' || $fChar == '-'))
$newContent .= $line."\n";
}
I changed malik's code for better performance and quality.
Here's another way:
class FileCleaner extends FilterIterator
{
public function __construct($srcFile)
{
parent::__construct(new ArrayIterator(file($srcFile)));
}
public function accept()
{
list($num) = explode(' ', parent::current(), 2);
return ($num > 0);
}
public function write($file)
{
file_put_contents($file, implode('', iterator_to_array($this)));
}
}
Usage:
$filtered = new FileCleaner($src_file);
$filtered->write($new_file);
Logic and methods can be added to the class for other stuff, such as sorting, finding the highest number, converting to a sane storage method such as csv, etc. And, of course, error checking.