I am trying to read the first line in a text file, but the fgets() function does not seem to be doing the job. I have a hunch that it might be due to the way the new lines are done in the string, but I am not very experienced in the different ways that a new line can be denoted. I have an image from a website showing what the new lines are inputted as below as well as my code.
link(no rep for images): https://i.gyazo.com/373e217112edbfce272f82b2dae6b317.png
I have already tried changing the mode from w to w+ which I thought would fix the problem, but it did not. I also tried trimming the string using the trim() function in php but that also did not work. I have verified that I am actually writing into the file as well.
Here is the code,
<?php
$input = "def sum(numbers):
total = 0
for x in numbers:
total += x
return total
print(sum((8, 2, 3, 0, 7)))";
$answerFile = fopen("/afs/cad.njit.edu/u/a/j/ajr74/public_html/answer.txt", "w+") or die("Unable to open file.");
fwrite($answerFile, $input);
$line = fgets($answerFile);
print($line);
?>
I am expecting the output to be the first line of the file before the first CR LF tags, but I am getting an empty output instead.
I guess the file pointer is at the end. To bring it back you can use rewind in between writing to your file and reading from it.
So
fwrite($answerFile, $input);
$line = fgets($answerFile);
Becomes
fwrite($answerFile, $input);
rewind($answerFile);
$line = fgets($answerFile);
Note: that's aside from the fact that you already have the content. Normally you wouldn't really need to read form the file, you could just extract the first line from $input. But I guess that you're either just learning or planning to do this in two different points.
Interesting.
After performing a write, you would need to reset the pointer to read the contents back. Best way is to close it and open it for reading.
<?php
$input = "def sum(numbers):
total = 0
for x in numbers:
total += x
return total
print(sum((8, 2, 3, 0, 7)))";
//$file_name = "/afs/cad.njit.edu/u/a/j/ajr74/public_html/answer.txt";
$file_name = "./answer.txt";
echo "Write {$file_name} and Read back a line<br>";
$answerFileHandle = fopen($file_name, "w+") or die("Unable to open file.");
fwrite($answerFileHandle, $input);
// Required these two lines to close and re-open the file.
// Resets the pointer after the write operation above
fclose($answerFileHandle);
$answerFileHandle = fopen($file_name, "r") or die("Unable to open file.");
$line = fgets($answerFileHandle);
echo $line;
fclose($answerFileHandle);
Output is:
`Write ./answer.txt and Read back a line
def sum(numbers):`
Related
When I explode the lines of a .csv file with a tab as delimiter, like such:
// $handle = some TSV file
while (($line = fgets($handle)) !== false) {
$fields = explode("\t",$line);
}
If the last column of the row is empty (or maybe even if it isn't), for some reason the last element in $fields will contain a newline (\n). This is causing problems and I can't quite figure out why it does this, and if it is normal, how to compensate for it.
The csv file is typical like so:
col1\tcol2\tcol3\n
col1\tcol2\tcol3\n
...
*The \t and \n are real tabs and new lines in the file.
So in this instance, if col3 was empty, my issue would persist. It might even do so if it isn't empty.
NOTE: The issue is that I am inserting each of the columns into a MySQL database and the last column has a newline in it. When I export this database back to CSV, it breaks the layout of the file.
So now my question(s) are:
Is this normal behavior?
If so, what can I do about it if I can't have a newline in the last $field?
1. Since you use fgets(), yes this is the expected behaviour, since you grab the full line, which includes the new line character at the end.
2. You can just use fgetcsv() and specify the delimiter as tab, e.g.
$handle = fopen("test.csv", "r");
if ($handle) {
while (($data = fgetcsv($handle, 4000, "\t")) !== FALSE) {
var_dump($data);
}
fclose($handle);
}
Just to add an alternative solution here:
You can get your file into an array with file() and ignore the new line characters at the end with a flag, so you do something similar as what fgets() does. And then explode() each line by a tab, e.g.
$data = array_map(function($v){
return explode("\t", $v);
}, file("yourFile.csv", FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES));
I have a very curious issue whith fgtcsv(). Look at this code
$csv_check = fopen(CSV_DIR.$this->db_table.".csv","r");
$data = fgetcsv($csv_check, 1000, $this->fields_terminated_by);
fclose($csv_check);
A print_r($data) outputs the following:
array (
0 => '"program_id"',
1 => 'program_name',
2 => 'program_logo',
)
Curiously, $data[0] is double-quoted here... The original line in this CSV file looks like this:
"program_id";"program_name";"program_logo"
I don't get it at all... Counting the chars of $data[0] with strlen($data[0]) returns 15, even if wrongly quoted, it must be 12 chars... I'm very stunned...!
Any ideas?!?
From PHP.net notes:
When a BOM character is suppled, fgetscsv may appear to wrap the first element in "double quotation marks". The simplest way to ignore it is to progress the file pointer to the 4th byte before using fgetcsv.
<?php
// BOM as a string for comparison.
$bom = "\xef\xbb\xbf";
// Read file from beginning.
$fp = fopen($path, 'r');
// Progress file pointer and get first 3 characters to compare to the BOM string.
if (fgets($fp, 4) !== $bom) {
// BOM not found - rewind pointer to start of file.
rewind($fp);
}
// Read CSV into an array.
$lines = [];
while (!feof($fp) && ($line = fgetcsv($fp)) !== false) {
$lines[] = $line;
}
I know this is an old topic, but as someone may come like me and try to figure out a solution, here is how to fix it.
Open notepad (in my case, I used notepad++) and create a new file.
Copy/paste all the data in the new file.
Save it as "All type" and add ".csv" yourself.
The file should be saved without BOM, and you can process with reading your CSV file with PHP.
I'm trying to read the file and take the first line of content and write it at the end. Then I want to rewind back to the beginning of the file and remove the content that part that I just wrote at the end.
$pklist = "pklist.txt";
$pkhandle = fopen($pklist, 'a+');
$pkdata = fread($pkhandle, 5);
fwrite($pkhandle, "\n" . $pkdata);
rewind($pkhandle);
So far this is working to read the first 5 characters and then append them at the end. But after reading the PHP documentation and looking around SO I'm still not sure how to just chop off a set number of characters from the beginning after I rewind.
btw. My text file is just a list of 5 digit numbers with a line break at the end of each.
<?php
$f = 'pklist.txt';
$fp = fopen($f, 'r+');
$data = fgets($fp);
$contents = fread($fp, filesize($f));
fseek($fp, 0);
fwrite($fp,$contents);
fwrite($fp,$data);
fclose($fp);
?>
That should work..
Open file using r+
Read first line and store to $data
Read the rest and store to $contents (fread will stop once end of file is reach)
Rewind to beginning of file
Write $contents
Write $data
Close file
Note: Also, if you want just a fixed number of characters instead of the entire line. Just change fgets to something like fgets($fp,5) to only move 5 chars.
If the file is not too big, you can use these calls:
$file = file($pklist); // read the file line by line
$file[] = $file[0]; // append first line to the end
$file[0] = null; // delete line 0
// if not working, use unset($file[0]);
$file = array_filter($file); // remove empty elements
$file = implode("\n", $file); // array to string, concat by 1 newline
file_put_contents($pklist, $file); // write contents back to file
The file get's loaded into memory thus not suitable for very big files.. but simplest usage for files of size < 1GB.
Good day guys,
I am really nowhere to the guy who do PHP coding, so I am asking you.
I have file in txt format and in that file somewhere I am having line with "count: (n)", where "(n)" can be any numeric value.
I need to search for count: (n), take the (n) value, sum it with +1 and save the file again.
So if I will have count: 10 it must be 10 + 1 = 11.
Thank you!
You'll probably want to use some regex to parse the 'count: n' string from the file. Although my regex is kind of rusty, this pattern might help:
$file = fopen('text.txt', 'r+'); // Open the file for reading and writing into the variable $file.
$fileContents = file_get_contents($file); // Load the contents of the file to variable $fileContents.
$countString = preg_match('/count: [0-9]+/', $fileContents); // Find instances of string 'count: n' where n is an integer, load the string into $countString.
$count = preg_match('/[0-9]+/', $countString); // Find the integer from $countString, load into $count.
$count++; // Iterate count up one.
$newCountString = 'count: '.$count; // The 'count: n+1' string where n is the original integer.
$newFileContents = preg_replace('/count: [0-9]+/', $newCountString, $fileContents); // Find the string 'count: n' and replace with 'count: n+1' where n is the original integer.
fwrite($file, $newFileContents); // Write the new contents into the file.
fclose($file);
Good luck!
I have try to write data to csv using the php function.
But the 0's are truncate while write in to an csv.
$data = array ( 'aaa,bbb,ccc,dddd', '000123,456,789','"aaa","bbb"');
$fp = fopen('data.csv', 'w');
foreach($data as $line)
{
$val = explode(",",$line);
fputcsv($fp, $val);
}
fclose($fp);
if you are trying to open csv in excel or open office, it will truncate leading zeros.
when u construct the string with "\t" before zero to avoid 0 truncation
I think Excel has treated it as a number and omitted the 0.
You may try to do this:
fputcsv ($fp, "='".$val."'");
See if it works
You could find that it's Excel, etc that's eating the 0 characters (you can test this out by opening the csv file in notepad (or whatever your favourite text editor is) and seeing if they're there.
If that's not the case then try using the following line:
fputcsv($fp, (string) $val);
Just in case the variable is somehow being cast to an integer somewhere.