I am having one txt file, with data simillar to below. I need to read the file and store the content in database using php, I am trying to explode the line and read it into array, but 7th column itself contains "," so not able to explode it properly using ",". Any help on this, how it can be done.
"MN", 2215," 309 ","4002 ",10,"10463","VAN TULL, GORDON ",000003120," ",1, 2, 4, "Y"
"MN", 2215," 309 ","4002 ",10,"10463","RODRIGUEZ, RANDY ",000003120," ",1, 2, 4, "Y"
I am trying following
$handle = fopen($filename, "r")
1) $line = fgetcsv($handle,",")
this is not working as column 7th itself have "," in its value.
2)
$Line = fgets($handle);
$data=explode(",",$Line);
if count($data)>13
// concatenating col 6 and 7
You didn't mention how you're trying to parse the csv, but I'm guessing you're just splitting it around the comma. Instead, try fgetcsv.
There are couple of ways at least
SIMPLE way is to replace all necessary commas with some special character and explode
bit programmatic - use regex
$contents = file_get_contents(__dir__.'/sample.txt');
$rows = explode(PHP_EOL, $contents);
foreach($rows as $row){
$cols = preg_split('/,(?=(?:[^"]|"[^"]*")*$)/', $row);
// do what you want to do with cols, which is an array of columns
}
Related
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):`
I've got a form which submits data to a csv file.
When a user inputs a comma to a field, it destroys my csv structure.
I want to convert inputted commas so that they can get displayed as a character.
I tried this:
$_POST["field"] = str_replace(",", "','", $_POST["field"]);
Use html encoding for instant relief , but still my recommendation to use phpExcel
$comma=",";
$_POST["field"] = str_replace(",", $comma, $_POST["field"]);
You can use fputcsv() to write, and fgetcsv() to read the file, it automatically converts your string.
A simple example for writing the data:
$csv = fopen('file.csv', 'w');
$array = array($csv);
fputcsv($csv, $array);
And reading the data:
$csv = fopen('file.csv','r');
print_r(fgetcsv($csv));
Probably not the best answer, but it does work.
You could replace the comma with a random string when inputting to the CSV as below:
$commastring = str_replace(",", "/zwdz/", $tempstring);
and then when you need to output the comma somewhere on your website (if a database website) you can do the opposite str_replace
You can escape coma like this:
$_POST["field"] = str_replace(",", "\,", $_POST["field"]);
Or you can put string in quotes
$_POST["field"] = "'".$_POST["field"]."'";
when I explode csv file on delimiter (;)
the explode successfully in some excel program and failed in others
also when I explode csv file on delimiter (,)
the explode successfully in some excel program and failed in others
How can I do explode in all versions of excel?
How can I know the perfect delimiter to explode?
yes there is code..
if (!function_exists('create_csv')) {
function create_csv($query, &$filename = false, $old_csv = false) {
if(!$filename) $filename = "data_export_".date("Y-m-d").".csv";
$ci = &get_instance();
$ci->load->helper('download');
$ci->load->dbutil();
$delimiter = ";";
$newline = "\r\n";
$csv = "Data:".date("Y-m-d").$newline;
if($old_csv)
$csv .= $old_csv;
else
$csv .= $ci->dbutil->csv_from_result($query, $delimiter, $newline);
$columns = explode($newline, $csv);
$titles = explode($delimiter, $columns[1]);
$new_titles = array();
foreach ($titles as $item) {
array_push($new_titles, lang(trim($item,'"')));
}
$columns[1] = implode($delimiter, $new_titles);
$csv = implode($newline, $columns);
return $csv;
}
}
sometimes I put $delimiter = ";";
and sometims $delimiter = ",";
thanks..
You can use helper function to detect best delimiter like:
public function find_delimiter($csv)
{
$delimiters = array(',', '.', ';');
$bestDelimiter = false;
$count = 0;
foreach ($delimiters as $delimiter)
if (substr_count($csv, $delimiter) > $count) {
$count = substr_count($csv, $delimiter);
$bestDelimiter = $delimiter;
}
return $bestDelimiter;
}
If you have an idea of the expected data (number of columns) then this might work as a good guess, and could be a good alternative to comparing which occurs the most (depending on what kind of data you're expecting).
It would work even better if you have a header record, I'd imagine. (You could put in a check for specific header values)
Sorry for not fitting it into your code, but I am not really sure what those calls you are making do, but you should be able to fit it around.
$expected_num_of_columns = 10;
$delimiter = "";
foreach (array(",", ";") as $test_delimiter) {
$fid = fopen ($filename, "r");
$csv_row = fgetcsv($fid, 0, $test_delimiter);
if (count($csv_row) == $expected_num_of_columns) {
$delimiter = $test_delimiter;
break;
}
fclose($fid);
}
if (empty($delimiter)) {
die ("Input file did not contain the correct number of fields (" . $expected_num_of_columns . ")");
}
Don't use this if, for example, all or most of the fields contain non-integer numbers (e.g. a list of monetary amounts) and has no header record, because files separated by ; are most likely to use , as the decimal point and there could be the same number of commas and semi-colons.
The short answer is, you probably can't unless you can apply some heuristic to determine the file format. If you don't know and can't detect the format of the file you're parsing, then parsing it is going to be difficult.
However, once you have determined (or, required a particular one) the delimiter format. You will probably find that php's built-in fgetcsv will be easier and more accurate than a manual explode based strategy.
There is no way to be 100% sure you are targeting the real delimiter. All you can do is guessing.
You should start by finding the right delimiter, then explode the CSV on this delimiter.
To find the delimiter, basically, you want a function that counts the number of , and the number of ; and that returns the greater.
Something like :
$array = explode(find_delimiter($csv), $csv);
Hope it helps ;)
Edit : Your find_delimiter function could be something like :
function find_delimiter($csv)
{
$arrDelimiters = array(',', '.', ';');
$arrResults = array();
foreach ($arrDelimiters as $delimiter)
{
$arrResults[$delimiter] = count(explode($delimiter, $csv));
}
$arrResults = rsort($arrResults);
return (array_keys($arrResults)[0]);
}
Well, it looks like you exactly know that your delimiter will be "," or ";". This is a good place to start. Thus, you may try to replace all commas (,) to semicolons (;), and then explode by the semicolon only. However, in this approach you would definitely have a problem in some cases, because some lines of your CSV files could be like this:
"name,value",other name,other value,last name;last value
In this way delimiter of your CSV file will be comma if there will be four columns in your CSV file. However, by changing commas to semicolons you would get five columns which would be incorrect. So, changing some delimiter to another is not a good way.
But still, if your CSV file is correctly formatted, then you may find correct delimiter in any of the lines. So, you may try to create some function like find_delimiter($csvLine) as proposed by #johnkork, but the problem with this is that the function itself can't know which delimiter to search for. However, you exactly know all the possible delimiters, so you may try to create another, quite similar, function like delimiter_exists($csvLine, $delimiter) which returns true or false.
But even the function delimiter_exists($csvLine, $delimiter) is not enough. Why? Because for the instance of CSV line provided above you would get that both "," and ";" are delimiters that exists. For comma it would CSV file with four columns, and for semicolon it would be two columns.
Thus, there is no universal way which would get you exactly what you want. However, there may be another way you can check for - the first line of CSV file which is the header assuming your CSV files have a header. Mostly, headers in CSV file have (not necessarily) no other symbols, except for the alphanumeric names of the columns, which are delimited by the specific delimiter. So, you may try to create function like delimiter_exists($csvHeader, $delimiter) whose implementation could be like this:
function delimiter_exists($csvHeader, $delimiter) {
return (bool)preg_match("/$delimiter/", $csvHeader);
}
For you specific case you may use it like this:
$csvHeader = "abc;def";
$delimiter = delimiter_exists($csvHeader, ',') ? ',' : ';';
Hope this helps!
I have a text file that contains a persons surname, address, time of accident and reason of accident separated by a white space in a line. I need to filter this file by only the people that have called in at least two times for the same reason and echo it.
I'm fairly new to PHP so I would like a simple way. :)
Thank you.
EDIT:
I haven't tried anything since I have no clue how to even filter file contents.
$data = array($_POST['surname'], $_POST['address'], $_POST['time'], $_POST['reason']);
$info = implode(" ", $data)
$info .= "\r\n";
serialize($info);
file_put_contents("data.txt", $info, FILE_APPEND);
serialize($info);
This is how I wrote it into a file.
I imploded the file because I needed to make them separated by 3 white spaces, but it no longer matters so I can just keep the array.
The expected output should be something like this:
Surname Address Time Reason
Adams Railroad 5 13:20 Heart Attack
Adams Railroad 5 23:35 Heart Attack
It would only need to repeat the same people that have matching Surnames and Reasons.
Update
your text file contains string, entries seprated by line brakes and values by three spaces (actually html coded spaces).
Here we read whole txt file in,(some could do this line by line):
$whole_string = file_get_contents('data.txt');
So firstly we get each line:
$entries = explode('\n',$whole_string);
Then value arrays are pushed:
$whole_ar = array();
foreach($entries as $e){
$whole_ar[] = explode(' ',$e);
}//if 3 spaces in file are in html
We get:
array(
array(
'name','date','etc..'
),
array(
'name2','date','etc..'
),
array(
'name2','date','etc..'
)
)
You could store array in php file, for later to include('data.php'); like so:
$file = '<?php $whole_ar='.var_export($whole_ar, TRUE)."; ?>";
file_put_contents('data.php', $file);
Main answer on how to parse this array to target copies is iteritating or:
$answer = array_unique(array_diff_assoc($whole_ar, array_unique( $whole_ar)));
As I understand, you get information like this string when user calls in:
$newest = "Huchinson Estonia Tallin Geo street 13 2015.12.02 13:44 Gas leak"
You have this string in variable, like stated above.
Then you could explode string by space characters: $data = explode(" ",$newest); which gives you an array with number of values. First value will be a surname and last will be reason of accident.
Parse them out of array like this: echo $data[0];//this will be surname and echo end($data);//this will be accident type
Instead of echo you can assign these values to variables and look up if this surname AND accident is present in your database:
if($saved_before == $data[0].end($data)){
echo "we are working on ".end($data).", be patient, dear ".$data[0];
}
p.s. dot (.) is for concatenating strings
If i understand well the txt file is a csv file that uses a space as the delimenter of the columns. So use use fgetcsv function to load columns of each row. Specify the blank space as the delimiter.
That should get you started:
function parseIt($line) { return str_getcsv($line, " "); }
$all = array_map('parseIt', file('yourfile.txt'));
$names = array();
foreach ($all as $row) {
$uniqkey = $row[0].$row[3];
if (isset($names[$uniqkey])) {
echo implode(" ",$row);
$names[$uniqkey]++;
} else {
$names[$uniqkey] = 1;
}
}
I noticed in your file writing code you use a delimiter of 3 white spaces so I used it in the example - you can set it to whatever you want in the str_getcsv(line, delimiter)
Explanation:
Lines 1,2 - file() will read the file into an array that are passed through the function parseIt() this function will parse the line and return an array of the line value.
Line 3 - The array $names will act our memory, at the end it will hold all names + reason as keys and the value will be the counter of occurrences.
Line 4... - Loops through $all checks if the key exists in $names if it does it prints the row and moves the counter otherwise sets a new key in $names and set its value to 1 (counter).
How'd I go about reading a tab delimited .txt file and then coding it so it puts each column of data(that is seperated with a tab) into a php variable.
for example....
505050 somedata moredata
and then, writing these variables to
$id
$somedata
$moredata
I read into fgetcsv and making an array although it seemed to make the whole line an array i need to split it into variables so that i can write it to individual columns in the MySQL database,
Can anyone give me any pointers?
Thanks so much...
A combination of fgetcsv() and list() will be the most efficient way to split this into named variables:
list($id, $somedata, $moredata) = fgetcsv($fp, 0, "\t");
However, you do not need to have them as named variables in order to insert them in MySQL, you can just use the raw array returned by fgetcsv():
$row = fgetcsv($fp, 0, "\t");
$query = "
INSERT INTO `tablename`
(`id`, `somedata`, `moredata`)
VALUES
('{$row[0]}', '{$row[1]}', '{$row[2]}')
";
Don't forget to escape the data before using it in a query ;-)
explode() will split a string. Try this:
list($id, $somedata, $moredata) = explode("\t", $string);
Where $string is the string you want to split. For more info about explode() and list(), just look up on php.net.
You can use explode():
http://php.net/manual/en/function.explode.php