2

I intentionally want to use a text file to do this. So I read a text file and I want to check if a username already exists in that text file or not and I want to either add this username to the text file if he doesn't exists or just add the points to him.

My current code:

<?php
$myfile = fopen("test.txt", "r") or die("Unable to open file!");
$file = fread($myfile,filesize("test.txt"));
//echo $file;
fclose($myfile);

//$username = $_REQUEST['username'];
//$points = $_REQUEST['point'];
$username = 'chinmay'; //chinmay is a username this is unique
$points = 200; //if username chinmay not exitst then Insert first time otherwise if username chimay exist then next onwards this point will update everytime in the text file.

$myfileWrite = fopen("test.txt", "a") or die("Unable to open file!");
$txt = $username."|".$points."\n";
fwrite($myfileWrite, $txt);

fclose($myfileWrite);
?> 

test.txt:

chinmay|800
john|200
sanjib|480
debasish|541

This is my complete code. My requirement is:

  • \n is not working when I am using this text inserted in the same line.
  • How can I check duplicate username?
  • If I found username then how can I update user points?

I googled last 2 hours but not getting any solution. I have no idea about this problem.

Rizier123
  • 58,877
  • 16
  • 101
  • 156
Chinmay235
  • 3,236
  • 8
  • 62
  • 93
  • I don't want to use any database. Because my database is heavy loaded. Another apps is running my database. Query executed 1000 and more times in a minute. So i want to use text file. – Chinmay235 Jul 23 '15 at 12:27
  • 2
    Text file is going to be less efficient. – chris85 Jul 23 '15 at 12:28
  • I know this is less efficient. But this is temporary. I will going to start a contest which duration is 7 days from today. So i don't need to give any pressure in my database. Maximum time i am getting `Too many connection in my database` – Chinmay235 Jul 23 '15 at 12:30
  • 1
    possible duplicate of [Flat File Databases](http://stackoverflow.com/questions/85/flat-file-databases) – Liam Sorsby Jul 23 '15 at 12:32
  • You have not implemented any error checking / handling at all. Is that by purpose? – arkascha Jul 23 '15 at 12:32
  • The issue with `\n` is probably just the old fact that different operating systems use different line end codings. – arkascha Jul 23 '15 at 12:33
  • For the rest you just make an associative array out of all read entries. That way multiple identical entries are eliminated automatically. Also when you add an entry you are guaranteed _not_ to get a twin entry. A very robust approach. – arkascha Jul 23 '15 at 12:36
  • horrible :) Please use database. Do not be afraid of databases. – B001ᛦ Jul 23 '15 at 12:48
  • You can use a simple DB like [sqLite](https://www.sqlite.org/) it does not need an online server. the DB file is read by library to the memory. If not follor DRY rules and create one point of write and read – michaelbn Jul 23 '15 at 12:51
  • Stop with the databases. The question is about how to work with **files**. Stay on track. – Sverri M. Olsen Jul 23 '15 at 13:02
  • Thanks @SverriM.Olsen for your comments. I got my answer. – Chinmay235 Jul 23 '15 at 13:12

4 Answers4

2

This should work for you:

First use file() to read your file into an array. Then you can use array_map() to loop through each line and explode() it by | as delimiter. After this you can use array_column() to get the username as key for the points as value. Like this:

Array
(
    [chinmay] => 1200
    [john] => 200
    [sanjib] => 480
    [debasish] => 541
    [chinmayx] => 200
)

With the array you can simply check if the username already exists or not. If not add it to the array and then add the points to it.

After adding the points to the username you can change your data back in the same format and save it with file_put_contents().

Full code:

<?php

    $lines = file("test.txt", FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
    $usernames = array_column(array_map(function($v){
        return explode("|", $v);
    }, $lines), 1, 0);

    $username = "chinmayx";
    $points = 200; 

    if(!isset($usernames[$username]))
        $usernames[$username] = 0;
    $usernames[$username] += $points;

    foreach($usernames as $k => $v)
        $data[] = "$k|$v" . PHP_EOL;

    file_put_contents("test.txt", $data);

?>

EDIT:

If you have PHP under 5.5 just replace:

$usernames = array_column(array_map(function($v){
    return explode("|", $v);
}, $lines), 1, 0);

with this:

$lines = array_map(function($v){
    return explode("|", $v);
}, $lines);

$usernames = array_combine(
    array_map(function($v){
        return $v[0];
    }, $lines),
    array_map(function($v){
        return $v[1];
    }, $lines)
);

Also if you want to get the TOP 10 users, just rsort() your array and then take an array_slice() of the first 10 elements, e.g.

rsort($usernames);
$topUsers = array_slice($usernames, 0, 10);
print_r($topUsers);
Rizier123
  • 58,877
  • 16
  • 101
  • 156
  • Error coming. `Fatal error: Call to undefined function array_column() in E:\xampp\htdocs\2015\demoProject\index.php on line 3` – Chinmay235 Jul 23 '15 at 12:45
  • @Chinu `echo phpversion();` will probalby give you something under 5.5. *Right?!* – Rizier123 Jul 23 '15 at 12:46
  • My php version is 5.3.5 – Chinmay235 Jul 23 '15 at 12:47
  • @Chinu Then just replace the line 3: `$usernames = array_column(array_map(function($v){ return explode("|", $v); }, $lines), 1, 0);` with `$usernames = array_combine( array_map(function($v){ return $v[0]; }, $lines), array_map(function($v){ return $v[1]; }, $lines) );` – Rizier123 Jul 23 '15 at 12:49
  • :( :( `Warning: array_combine() [function.array-combine]: Both parameters should have at least 1 element in E:\xampp\htdocs\2015\demoProject\index.php on line 9` – Chinmay235 Jul 23 '15 at 12:50
  • @Chinu wups forgot one line, use: `$lines = array_map(function($v){ return explode("|", $v); }, $lines); $usernames = array_combine( array_map(function($v){ return $v[0]; }, $lines), array_map(function($v){ return $v[1]; }, $lines) );` – Rizier123 Jul 23 '15 at 12:54
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/84080/discussion-between-chinu-and-rizier123). – Chinmay235 Jul 23 '15 at 12:57
0

you should use PHP_EOL instead of "\n" which also depends on your OS

$txt = $username."|".$points.PHP_EOL;

for checking userName, just use:

//this works because $file is String because of fread()
if (strpos($file,$username) !== false) {
    echo 'user exists';
}

for replacing you'll need regex or use strpos position (which returns position of name in string) and advance the pointer by count($username)+1 and search from there for newline, all this string between that, replace with new points

Daniel Krom
  • 9,751
  • 3
  • 43
  • 44
  • The `PHP_EOL` constant is an advice often given, but I have the impression many people get the constant wrong. It does not magically solve all problems. It is an elegant solution for the issue at hand, for writing and exploding file content. But it does not solve the OPs issue where seemingly no linebreaks are written. – arkascha Jul 23 '15 at 12:35
0

To get the \n working use the PHP_EOL as in another answer

$txt = $username."|".$points.PHP_EOL;

To update the user found in the text file go through following link

how to replace a particular line in a text file using php?

Community
  • 1
  • 1
Santosh Jagtap
  • 995
  • 8
  • 17
0

Try to use preg_match:

$file = fopen("score.txt", "r");

while (!feof($file)) {
preg_match("/^$username|(.*?)$/", $file, $array);
var_dump($array);
}

but I think it's better to use MySQL :)

Adam Bieńkowski
  • 585
  • 4
  • 21