PHP浮点数精度丢失问题解决方案

 更新时间:2016年11月25日 15:37  点击:2644
浮点数就是有很我小数的那种并且不只单纯了数字了,而小编在用支付接口时就碰到浮点数丢失的问题,下文一起来看看问题解决方法.


先看下面这段代码:

$f = 0.57;
echo intval($f * 100);  //56

结果可能有点出乎你的意外,PHP遵循IEEE 754双精度:
浮点数, 以64位的双精度, 采用1位符号位(E), 11指数位(Q), 52位尾数(M)表示(一共64位).
符号位:最高位表示数据的正负,0表示正数,1表示负数。
指数位:表示数据以2为底的幂,指数采用偏移码表示
尾数:表示数据小数点后的有效数字.

再来看看小数用二进制怎么表示:

乘2取整,顺序排列,即将小数部分乘以2,然后取整数部分,剩下的小数部分继续乘以2,然后取整数部分,剩下的小数部分又乘以2,一直取到小数部分,但是像0.57这样的小数像这样一直乘下去,小数部分不可能为0.有效位的小数用二进制表示却是无穷的。

0.57的二进制表示基本上(52位)是: 0010001111010111000010100011110101110000101000111101

如果只有52位的话,0.57 =》 0.56999999999999995

不难看出上面意外的结果了吧,再补充一下例子

办法有很多,这里列举两个:

1. sprintf

substr(sprintf("%.10f", ($a/ $b)), 0, -7);
2. round (注意会进行四舍五入)

round($a/$b, 3);

对于精度我一直理解为小数点后保留多少,那么在php的浮点数中是这样的么?答案是否定的。

浮点数其实是整数部分和小数部分组成,这里的精度是指整数部分的位数加小数部分的位数不能超过其精度最大值,如果超过,则按照四舍五入的方法截断到最大的精度值。整数部分如果是0,则不计位数,小数部分末尾0也不计入位数。另外对于同一个数,precision的不同,可能显示的出来表现形式也不一样。下面通过例子的方式来说明。

整数部分为 0 情况

 $num = 0.12345600000000000;
 //整数部分为0 ,位数为 0 ,小数部分末尾的 0 不计入位数,所以总位数为 6

 ini_set("precision", "12");
 echo $num; // 0.123456
 //未超过精度值,显示的结果为 0.123456

 ini_set("precision", "3");
 echo $num; // 0.123
 //超过精度值,保留3位

 ini_set("precision", "5");
 echo $num; // 0.12346
 //超过精度值,保留5位
这种情况下,精度值等价于小数点后保留几位。

整数部分大于 0 情况

 $num = 12.12345600000000000;
 //整数部分为12 ,位数为 2 ,小数部分末尾的 0 不计入位数,位数为6,所以总位数为 2 + 6

 ini_set("precision", "12");
 echo $num; // 12.123456
 //未超过精度值,显示的结果为 12.123456

 ini_set("precision", "3");
 echo $num; // 12.1
 //超过精度值,整数部分位数为 2 ,所以只保留一位小数

 ini_set("precision", "5");
 echo $num; // 12.123
 //超过精度值,整数部分位数为 2 ,所以只保留3位小数
可以看到小数点后保留的位数跟精度已经整数部分的位数有关。

整数部分大于 0 情况 之二

 $num = 12345678.12345600000000000;
 //整数部分为12345678 ,位数为 8 ,小数部分末尾的 0 不计入位数,位数为6,所以总位数为 8 + 6

 ini_set("precision", "12");
 echo $num; // 12345678.1235
 //超过精度值,显示的结果为 12345678.1235

 ini_set("precision", "3");
 echo $num; // 1.23E+7
 //超过精度值,且整数部分位数超过精度,小数部分舍弃,且整数部分只取3位

 ini_set("precision", "5");
 echo $num; // 12346000
 //超过精度值,且整数部分位数超过精度,小数部分舍弃,且整数部分只取5位
上述例子中可以看到,精度值也关系到整数部分的截取。注意到最后两个例子中显示的方式不一样,一个是使用科学计数法,一个是后面用 0 补。通过实验得出的结论是当整数部分的位数 减去 精度值 大于 4 的时候,使用科学计数法的方式,否则后面用 0 补,换句话说,就是整数部分位数超过精度值后,截断后,补 0 的个数不会超过 4 。

浮点数运算

 $num1 = 1331625729.687;
 $num2 = 1331625730.934;
 ini_set("precision", "8");

 echo $num1 . '
';
 echo $num2 . '
';

 $sub = $num1 - $num2;

 echo $sub . '
';
//输出的结果为:
/*
 1331625700
 1331625700
 -1.247
*/
上述例子就说明了精度值只是控制显示结果,内部存储还是原始值,所以 $sub 的值为1331625729.687减1331625730.934。

PHP 5.4中的traits,是新引入的特性,用于实现代码重用的方法,下面我们就一起来看看PHP使用traits实现代码复用的例子,希望文章可以帮助到各位.


PHP5.4后新增traits实现代码复用机制,Trait和类相似,但不能被实例化,无需继承,只需要在类中使用关键词use引入即可,可引入多个Traits,用','隔开。
(1)Trait简单使用

<?php
 
trait A {
    public $var1 = 'test1';
    public function test1() {
        echo 'trait A::test1()';
    }
}
 
trait B {
    public $var2 = 'test2';
    public function test2() {
        echo 'trait B::test2()';
    }
}
 
class C {
    use A,B;
}
 
$c = new C();
echo $c->var1; //test1
$c->test2(); //trait B::test2()

(2)优先级问题
Trait会覆盖继承的方法,当前类会覆盖Trait方法。
trait A {
    public $var1 = 'test';
    public function test() {
        echo 'A::test()';
    }
    public function test1() {
        echo 'A::test1()';
    }
}
 
class B {
    public function test() {
        echo 'B::test()';
    }
    public function test1() {
        echo 'B::test1()';
    }
}
class C extends B{
    use A;
    public function test() {
        echo 'c::test()';
    }
}
 
$c = new C();
$c->test(); //c::test()
$c->test1(); //A::test1()

(3)多个Trait冲突问题
如果没有解决冲突,会产生致命错误;
可用insteadof来明确使用冲突中哪一个方法;
可用as操作符将其中一个冲突方法另起名;
trait A {
    public function test() {
        echo 'A::test()';
    }
}
 
trait B {
    public function test() {
        echo 'B::test()';
    }
}
 
class C {
    use A,B {
        B::test insteadof A;
        B::test as t;
    }
}
 
$c = new C();
$c->test(); //B::test()
$c->t(); //B::test()   可以用as另起名

(4)as可用来修改方法访问控制
trait  HelloWorld  {
    public function  sayHello () {
        echo  'Hello World!' ;
    }
}
 
// 修改 sayHello 的访问控制
class  A  {
    use  HelloWorld  {  sayHello  as protected; }
}
 
// 给方法一个改变了访问控制的别名
// 原版 sayHello 的访问控制则没有发生变化
class  B  {
    use  HelloWorld  {  sayHello  as private  myPrivateHello ; }
}
 
$b = new A();
$b->sayHello(); //Fatal error: Call to protected method A::sayHello() from context ''

(5)Trait中使用Trait
trait A {
    public function test1() {
        echo 'test1';
    }
}
 
trait B {
    public function test2() {
        echo 'test2';
    }
}
 
trait C {
    use A,B;
}
 
class D {
    use C;
}
 
$d = new D();
$d->test2();  //test2

(6)Trait支持抽象方法、支持静态方法、不可以直接定义静态变量,但静态变量可被trait方法引用。
trait A {
    public function test1() {
        static $a = 0;
        $a++;
        echo $a;
    }
 
    abstract public function test2(); //可定义抽象方法
}
 
class B {
    use A;
    public function test2() {
 
    }
}
 
$b = new B();
$b->test1(); //1
$b->test1(); //2

(7)Trait可定义属性,但类中不能定义同样名称属性
trait A {
   public $test1;
}
 
class B {
    use A;
    public $test2;
}

接着看

<?php
    trait Drive {
        public $carName = 'trait';
        public function driving() {
            echo "driving {$this->carName}\n";
        }
    }
    class Person {
        public function eat() {
            echo "eat\n";
        }
    }
    class Student extends Person {
        use Drive;
        public function study() {
            echo "study\n";
        }
    }
    $student = new Student();
    $student->study();
    $student->eat();
    $student->driving();
输出结果如下:

study
eat
driving trait
上面的例子中,Student类通过继承Person,有了eat方法,通过组合Drive,有了driving方法和属性carName。

如果Trait、基类和本类中都存在某个同名的属性或者方法,最终会保留哪一个呢?通过下面的代码测试一下:

<?php
    trait Drive {
        public function hello() {
            echo "hello drive\n";
        }
        public function driving() {
            echo "driving from drive\n";
        }
    }
    class Person {
        public function hello() {
            echo "hello person\n";
        }
        public function driving() {
            echo "driving from person\n";
        }
    }
    class Student extends Person {
        use Drive;
        public function hello() {
            echo "hello student\n";
        }
    }
    $student = new Student();
    $student->hello();
    $student->driving();
输出结果如下:

hello student
driving from drive
因此得出结论:当方法或属性同名时,当前类中的方法会覆盖 trait的 方法,而 trait 的方法又覆盖了基类中的方法。

如果要组合多个Trait,通过逗号分隔 Trait名称:

use Trait1, Trait2;
如果多个Trait中包含同名方法或者属性时,会怎样呢?答案是当组合的多个Trait包含同名属性或者方法时,需要明确声明解决冲突,否则会产生一个致命错误。

<?php
trait Trait1 {
    public function hello() {
        echo "Trait1::hello\n";
    }
    public function hi() {
        echo "Trait1::hi\n";
    }
}
trait Trait2 {
    public function hello() {
        echo "Trait2::hello\n";
    }
    public function hi() {
        echo "Trait2::hi\n";
    }
}
class Class1 {
    use Trait1, Trait2;
}
输出结果如下:

PHP Fatal error:  Trait method hello has not been applied, because there are collisions with other trait methods on Class1 in ~/php54/trait_3.php on line 20
使用insteadof和as操作符来解决冲突,insteadof是使用某个方法替代另一个,而as是给方法取一个别名,具体用法请看代码:

<?php
trait Trait1 {
    public function hello() {
        echo "Trait1::hello\n";
    }
    public function hi() {
        echo "Trait1::hi\n";
    }
}
trait Trait2 {
    public function hello() {
        echo "Trait2::hello\n";
    }
    public function hi() {
        echo "Trait2::hi\n";
    }
}
class Class1 {
    use Trait1, Trait2 {
        Trait2::hello insteadof Trait1;
        Trait1::hi insteadof Trait2;
    }
}
class Class2 {
    use Trait1, Trait2 {
        Trait2::hello insteadof Trait1;
        Trait1::hi insteadof Trait2;
        Trait2::hi as hei;
        Trait1::hello as hehe;
    }
}
$Obj1 = new Class1();
$Obj1->hello();
$Obj1->hi();
echo "\n";
$Obj2 = new Class2();
$Obj2->hello();
$Obj2->hi();
$Obj2->hei();
$Obj2->hehe();
输出结果如下:

Trait2::hello
Trait1::hi

Trait2::hello
Trait1::hi
Trait2::hi
Trait1::hello
as关键词还有另外一个用途,那就是修改方法的访问控制:

<?php
    trait Hello {
        public function hello() {
            echo "hello,trait\n";
        }
    }
    class Class1 {
        use Hello {
            hello as protected;
        }
    }
    class Class2 {
        use Hello {
            Hello::hello as private hi;
        }
    }
    $Obj1 = new Class1();
    $Obj1->hello(); # 报致命错误,因为hello方法被修改成受保护的
    $Obj2 = new Class2();
    $Obj2->hello(); # 原来的hello方法仍然是公共的
    $Obj2->hi();  # 报致命错误,因为别名hi方法被修改成私有的
Trait 也能组合Trait,Trait中支持抽象方法、静态属性及静态方法,测试代码如下:

<?php
trait Hello {
    public function sayHello() {
        echo "Hello\n";
    }
}
trait World {
    use Hello;
    public function sayWorld() {
        echo "World\n";
    }
    abstract public function getWorld();
    public function inc() {
        static $c = 0;
        $c = $c + 1;
        echo "$c\n";
    }
    public static function doSomething() {
        echo "Doing something\n";
    }
}
class HelloWorld {
    use World;
    public function getWorld() {
        return 'get World';
    }
}
$Obj = new HelloWorld();
$Obj->sayHello();
$Obj->sayWorld();
echo $Obj->getWorld() . "\n";
HelloWorld::doSomething();
$Obj->inc();
$Obj->inc();
输出结果如下:

Hello
World
get World
Doing something
1
2

通常情况下我们用户可以多个人同时登录了,但有时客户需求我们需要的是同一个账号同时只能一个人登录了,下面我们就一起来看此问题的解决办法.

以前考虑过这个问题,今天实现了一下,挺快的,从研究到开发完成差不多4个小时。有点类似QQ,二台电脑登录,一台会把另一台挤掉线,并提示其他地点登录信息。

一,实现原理

1,用户在电脑A登录,session信息存放在redis当中,并将session_id存到mysql数据库中。
2,同一用户在电脑B登录,验证完用户名和密码后,将该用户信息从数据库读出,取得用户在电脑A登录的session_id,然后在到redis中验证session是否过期。
3,如果过期,不用openfire推送提示信息。如果没有过期,php利用openfire推送消息后,在将redis中用户在电脑A中登录的session删除掉,删除后,在将用户在电脑B登录的个人信息放到session中,并将电脑B登录的session_id更新到数据库中,在这里一定要先发送推送,然后在清空session,不然用户在电脑A收不到xmpp发过来的消息。

注意:

openfire是java cms的一种,自身有数据库,您创建的用户表根openfire自带的用户表之间要建立某种联系(如:手机号,邮箱等),方便信息推送。
同一session_id肯定是在相同媒介上登录的,这个时候,也不用更新数据库和推送消息
下面简单说一下安装过程,以及要注意的地方。

二,安装所用到的工具

# yum install php php-fpm nginx mysql mysql-server redis php-redis php-devel php-pdo php-mysql 

修改session存储方式:

# vim /etc/php-fpm.d/www.conf    
 
;php_value[session.save_handler] = files   //注释掉旧的 
;php_value[session.save_path] = /var/lib/php/session 
 
php_value[session.save_handler] = redis  //添加以下内容 
php_value[session.save_path] = "tcp://127.0.0.1:6379" 

启动服务后,如果以下内容说明,session存redis成功了

redis telnet查看session
redis telnet查看session

openfire下载地址:http://www.igniterealtime.org/downloads/

# rpm -ivh ./*.rpm   //下载的是rpm安装包 

openfire启动后,然后访问http://ip:9090,一步一步配置就成了,有一点要注意就是数据库的编码。

PDO是高版本php中的一个mysql数据库操作功能了,我们下面就一起来看看关于php中PDO的一些学习笔记,有兴趣了解PDO的朋友可一起来看看哦.

一、PDO简介

  PDO是PHP Data Object的简称,用于定义数据库访问的抽象层,统一各种数据库的访问接口。PDO有如下特性:

编码一致性:PDO支持多种数据库扩展,并为其提供统一的访问接口
灵活性:PDO提供了统一的SQL操作方法和属性
高效性:PDO是用C编写、PHP编译的
面向对象:PDO完全采纳面向对象的思想
  PDO支持的数据库:

pdo支持的数据库

  但是,需要注意的是,PDO只是提供了一组数据库访问接口,利用PDO本身不能操作任何数据库。

二、PDO对象

  利用PDO的构造函数连接特定的数据库,创建一个PDO对象。在利用PDO之前,需要开启PDO扩展。以PHP+MySQL为例,

  开启PHP对PDO的扩展:在php.ini中去掉extension=php_pdo.dll的注释。

  开启MySQL对PDO的扩展:在my.ini中去掉extension=php_pdo_mysql.dll的注释。

  利用phpinfo()可以查看是否开启PDO扩展。

  1、连接数据库

    PDO连接数据库有三种方式:

   1.1  通过参数形式连接(推荐)

$dsn = "mysql:host=localhost;dbname=xxx";
$username = "xxxxx";
$pwd = "xxxx";
$pdo = new PDO($dsn,$username,$pwd);
  PDO构造函数还有一个$options参数,它是一个数组,用于配置运行中的数据库,如是否开启自动提交、设置结果集的返回方式等。

  1.2  通过uri连接

  首先建立一个文件,保存数据源,文件内容形如:mysql:host=localhost;dbname=xxx。然后在程序中引入该文件。

$dsn = "uri:file://保存数据源配置的文件路径";
$username = "xxxxx";
$pwd = "xxxx";
$pdo = new PDO($dsn,$username,$pwd);
  1.3  通过配置文件连接

  在php.ini中的任意一个位置添加数据源的配置:

        pdo.dsn.test=”mysql:host=localhost;dbname=xxxx”;

  test是自定义的数据源名称。为方便,可以在php.ini的首行中添加,然后重启服务器,在程序中引入该数据源

$dsn = "test";    //数据源名称
$username = "xxxxx";
$pwd = "xxxx";
$pdo = new PDO($dsn,$username,$pwd);
  2、PDO对象的常见方法和属性

方法或属性 描述
exec() 执行一条SQL语句,返回受影响的行数。用于增删改,对查询返回0
query() 执行一条SQL语句,返回PDOStatement对象,用于保存结果集
prepare() 执行一条SQL语句,返回PDOStatement对象
quote() 返回一个添加引号的字符串,用于SQL语句,可防止SQL注入
lastInsertId 返回最后插入的ID
setAttribute() 设置数据库连接属性
getAttribute() 获取数据库连接属性
errorCode() 获取跟数据库句柄上一次操作相关的SQLSTATE
errorInfo() 获取跟数据库句柄上一次操作相关的错误信息
beginTransaction() 开启一个事务。需要先关闭自动提交
commit() 提交事务
rollBack() 回滚事务
inTransaction() 检查操作是否在事务内
 

三、PDOStatement对象

  PDO对象的query()和prepare()方法均会返回一个PDOStatement对象,该对象可以用于PDO的预处理执行。其常见方法如下:

方法 描述
execute() 执行一条预处理语句
rowCount() 返回上一个SQL语句影响的行数
fetch() 从结果集中获取一行
fetchAll() 返回一个包含结果中所有行的数组
setFetchMode() 设置默认获取结果集的模式
fetchObject() 获取结果集下一行并作为对象返回
fetchColumn() 获取结果集下一行的单独一列
bindParam() 绑定一个参数到指定的变量名
bindValue() 将某个值绑定到指定的参数
bindColumn() 绑定一列到PHP变量
getColumnMeta() 返回结果集中一列的元素据
columnCount() 返回结果中的列数
setAttribute() 设置一个语句属性
getAttribute() 获取一个语句属性
errorCode() 获取跟数据库句柄上一次操作相关的SQLSTATE
errorInfo() 获取跟数据库句柄上一次操作相关的错误信息
debugDumpparams() 打印一条SQL预处理语句
nextRowset() 在一个多行集语句句柄中推进到下一个行集
 

四、异常模式

 PDO支持三种异常模式:

默认模式:PDO::ERRMODE_CLIENT
警告模式:PDO::ERRMODE_WARNING
异常模式:PDO::ERRMODE_EXCEPTION(推荐)
  可以在PDO的构造函数的第四个$options参数或用PDO对象的setAttribute()方法设置。

多服务器数据同步并且实时数据处理功能想了很多没找到合适的工具了,今天想了可以使用ftp+rsync工具来实现,下文重点介绍的是php ftp上传类的实现了。

现在很多地方需要用ftp类操作另外的网站服务器,上传图片之类的。现在贴一个php ftp类给大家

class Ftp {
       
    //FTP 连接资源
    private $link;
    //FTP连接时间
    public $link_time;
    //错误代码
    private $err_code = 0;
    //传送模式{文本模式:FTP_ASCII, 二进制模式:FTP_BINARY}
    public $mode = FTP_BINARY;
       
    /**
     * 连接FTP服务器
     * @param string $host       服务器地址
     * @param string $username   用户名
     * @param string $password   密码
     * @param integer $port       服务器端口,默认值为21
     * @param boolean $pasv        是否开启被动模式
     * @param boolean $ssl      是否使用SSL连接
     * @param integer $timeout     超时时间 
     */
    public function connect($host, $username = '', $password = '', $port = '21', $pasv = false, $ssl = false, $timeout = 30) {
        $start = time();
        if ($ssl) {
            if (!$this->link = @ftp_ssl_connect($host, $port, $timeout))     {
                $this->err_code = 1;
                return false;
            }
        } else {
            if (!$this->link = @ftp_connect($host, $port, $timeout)) {
                $this->err_code = 1;
                return false;
            }
        }
       
        if (@ftp_login($this->link, $username, $password)) {
            if ($pasv)
                ftp_pasv($this->link, true);
            $this->link_time = time() - $start;
            return true;
        } else {
            $this->err_code = 1;
            return false;
        }
        register_shutdown_function(array(&$this, 'close'));
    }
       
    /**
     * 创建文件夹
     * @param string $dirname 目录名,
     */
    public function mkdir($dirname) {
        if (!$this->link) {
            $this->err_code = 2;
            return false;
        }
        $dirname = $this->ck_dirname($dirname);
        $nowdir = '/';
        foreach ($dirname as $v) {
            if ($v && !$this->chdir($nowdir . $v)) {
                if ($nowdir)
                    $this->chdir($nowdir);
                @ftp_mkdir($this->link, $v);
            }
            if ($v)
                $nowdir .= $v . '/';
        }
        return true;
    }
       
    /**
     * 上传文件
     * @param string $remote 远程存放地址
     * @param string $local 本地存放地址
     */
    public function put($remote, $local) {
        if (!$this->link) {
            $this->err_code = 2;
            return false;
        }
        $dirname = pathinfo($remote, PATHINFO_DIRNAME);
        if (!$this->chdir($dirname)) {
            $this->mkdir($dirname);
        }
        if (@ftp_put($this->link, $remote, $local, $this->mode)) {
            return true;
        } else {
            $this->err_code = 7;
            return false;
        }
    }
       
    /**
     * 删除文件夹
     * @param string $dirname  目录地址
     * @param boolean $enforce 强制删除
     */
    public function rmdir($dirname, $enforce = false) {
        if (!$this->link) {
            $this->err_code = 2;
            return false;
        }
        $list = $this->nlist($dirname);
        if ($list && $enforce) {
            $this->chdir($dirname);
            foreach ($list as $v) {
                $this->f_delete($v);
            }
        } elseif ($list && !$enforce) {
            $this->err_code = 3;
            return false;
        }
        @ftp_rmdir($this->link, $dirname);
        return true;
    }
       
    /**
     * 删除指定文件
     * @param string $filename 文件名
     */
    public function f_delete($filename) {
        if (!$this->link) {
            $this->err_code = 2;
            return false;
        }
        if (@ftp_delete($this->link, $filename)) {
            return true;
        } else {
            $this->err_code = 4;
            return false;
        }
    }
       
    /**
     * 返回给定目录的文件列表
     * @param string $dirname  目录地址
     * @return array 文件列表数据
     */
    public function nlist($dirname) {
        if (!$this->link) {
            $this->err_code = 2;
            return false;
        }
        if ($list = @ftp_nlist($this->link, $dirname)) {
            return $list;
        } else {
            $this->err_code = 5;
            return false;
        }
    }
       
    /**
     * 在 FTP 服务器上改变当前目录
     * @param string $dirname 修改服务器上当前目录
     */
    public function chdir($dirname) {
        if (!$this->link) {
            $this->err_code = 2;
            return false;
        }
        if (@ftp_chdir($this->link, $dirname)) {
            return true;
        } else {
            $this->err_code = 6;
            return false;
        }
    }
       
    /**
     * 获取错误信息
     */
    public function get_error() {
        if (!$this->err_code)
            return false;
        $err_msg = array(
            '1' => 'Server can not connect',
            '2' => 'Not connect to server',
            '3' => 'Can not delete non-empty folder',
            '4' => 'Can not delete file',
            '5' => 'Can not get file list',
            '6' => 'Can not change the current directory on the server',
            '7' => 'Can not upload files'
        );
        return $err_msg[$this->err_code];
    }
       
    /**
     * 检测目录名
     * @param string $url 目录
     * @return 由 / 分开的返回数组
     */
    private function ck_dirname($url) {
        $url = str_replace('', '/', $url);
        $urls = explode('/', $url);
        return $urls;
    }
       
    /**
     * 关闭FTP连接
     */
    public function close() {
        return @ftp_close($this->link);
    }
       
}

先来说说远程附件上传的大致流程:

  用户选择文件上传提交到服务器->服务器接收到文件->服务器一些安全检测完成通过FTP功能上传到相应FTP服务器。

我说的只是一个大概过程,不是很标准,明白个意思即可啦!~

这个类大致使用方法:

 首先通过 $ftps->connect($host,$username,$password,$post,$pasv,$ssl,$timeout);进行FTP服务器连接。

 通过具体的函数进行FTP的操作。

  $ftps->mkdir() 创建目录,可以创建多级目录以“/abc/def/higk”的形式进行多级目录的创建。

  $ftps->put()上传文件

  $ftps->rmdir()删除目录

  $ftps->f_delete()删除文件

  $ftps->nlist()列出指定目录的文件

  $ftps->chdir()变更当前文件夹

  $ftps->get_error()获取错误信息

rsync工具同步

这里只介绍原理了rsync同步在windows中只能使用windows计划任务来实现了,我们可以定义为1小时同步一次,这样可以保证同步失败文件再次同步一下,当然在ftp上传类时可以做一个错误日志记录,上传失败之后记录在一个日志文件,然后我们可以手工点击再实现一次上传了,这样台保证万无一失了。

[!--infotagslink--]

相关文章

  • PHP传值到不同页面的三种常见方式及php和html之间传值问题

    在项目开发中经常见到不同页面之间传值在web工作中,本篇文章给大家列出了三种常见的方式。接触PHP也有几个月了,本文总结一下这段日子中,在编程过程里常用的3种不同页面传值方法,希望可以给大家参考。有什么意见也希望大...2015-11-24
  • js修改input的type属性问题探讨

    js修改input的type属性有些限制。当input元素还未插入文档流之前,是可以修改它的值的,在ie和ff下都没问题。但如果input已经存在于页面,其type属性在ie下就成了只读属性了,不可以修改。...2013-10-19
  • Mysql常见问题集锦

    1,utf8_bin跟utf8_general_ci的区别 ci是 case insensitive, 即 "大小写不敏感", a 和 A 会在字符判断中会被当做一样的; bin 是二进制, a 和 A 会别区别对待. 例如你运行: SELECT * FROM table WHERE txt = 'a'...2013-10-04
  • Mysql大小写敏感的问题

    一、1 CREATE TABLE NAME(name VARCHAR(10)); 对这个表,缺省情况下,下面两个查询的结果是一样的:复制代码 代码如下: SELECT * FROM TABLE NAME WHERE name='clip'; SELECT * FROM TABLE NAME WH...2015-03-15
  • linux mint 下mysql中文支持问题

    一.mysql默认不支持中文,它的server和db默认是latin1编码.所以我们要将其改变为utf-8编码,因为utf-8包含了地球上大部分语言的二进制编码 1.关闭mysql服务 sudo /etc/init.d/mysql stop 2.修改mysql配置文件 mysql配...2015-10-21
  • go浮点数转字符串保留小数点后N位的完美解决方法

    这篇文章主要介绍了go浮点数转字符串保留小数点后N位解决办法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2020-05-11
  • C#使用队列(Queue)解决简单的并发问题

    这篇文章主要介绍了使用队列(Queue)解决简单的并发问题,讲解的很细致,喜欢的朋友们可以了解一下...2020-06-25
  • PHP浮点数精度丢失问题解决方案

    浮点数就是有很我小数的那种并且不只单纯了数字了,而小编在用支付接口时就碰到浮点数丢失的问题,下文一起来看看问题解决方法. 先看下面这段代码: $f = 0.57; echo...2016-11-25
  • windows 10 安装和使用中5个常见问题

    2015年7月29日0点起,Windows 10推送全面开启,Windows7、Windows8.1用户可以免费升级到Windows 10,用户也可以通过系统升级到Windows10,在这过程中,用户会遇到这样那样的问题,下面小编总结了windows 10 安装和使用中5个常见问题,需要的朋友可以参考下...2016-01-27
  • php中session常见问题分析

    PHP的session功能,一直为许多的初学者为难。就连有些老手,有时都被搞得莫名其妙。本文,将这些问题,做一个简单的汇总,以便大家查阅。 1. 错误提示 引用 代...2016-11-25
  • javascript学习指南之回调问题

    回调函数被认为是一种高级函数,一种被作为参数传递给另一个函数(在这称作"otherFunction")的高级函数,回调函数会在otherFunction内被调用(或执行)。回调函数的本质是一种模式(一种解决常见问题的模式),因此回调函数也被称为回调模式。...2016-04-25
  • json error: Use of overloaded operator [] is ambiguous错误的解决方法

    今天小编就为大家分享一篇关于json error: Use of overloaded operator [] is ambiguous错误的解决方法,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧...2020-04-25
  • C++基于递归算法解决汉诺塔问题与树的遍历功能示例

    这篇文章主要介绍了C++基于递归算法解决汉诺塔问题与树的遍历功能,简单描述了递归算法的原理,并结合实例形式分析了基于递归算法解决汉诺塔问题与数的遍历相关操作技巧,需要的朋友可以参考下...2020-04-25
  • PHP date函数显示1970-01-01问题详解

    我们使用date函数直接显示后面带有date("Y-m-d H:i:s",$t);发现显示的为1970-01-01了,这个问题对于新手来讲可能不好理解,但对于做过几年的高手来讲小菜了。 如date...2016-11-25
  • C#约瑟夫问题解决方法

    这篇文章主要介绍了C#约瑟夫问题解决方法,较为详细的分析了约瑟夫问题及C#解决技巧,具有一定参考借鉴价值,需要的朋友可以参考下...2020-06-25
  • 学习动态网页PHP技术常见问题汇总解答

    1:为什么我得不到变量 我在一网页向另一网页POST数据name,为什么输出$name时却得不到任何值? 在PHP4.2以后的版本中reGISter_global默认为off 若想取得从另一页...2016-11-25
  • 基于C++浮点数(float、double)类型数据比较与转换的详解

    本篇文章是对C++中浮点数(float、double)类型数据比较与转换进行了详细的分析介绍,需要的朋友参考下...2020-04-25
  • IIS 配置问题 一些iis常见问题的解决方法

    前几天在IIS的配置上出了些问题,到网上查找了些资料,顺便整理放在这里,希望对大家有帮助 ...2016-01-27
  • 解决:Bitmap too large to be uploaded into a texture exception问题

    下面我们一起来看一篇关于 解决:Bitmap too large to be uploaded into a texture exception问题解决办法。 最近做项目发现其他手机没有问题,但是出现了一个手机报...2016-09-20
  • php FILTER_VALIDATE_FLOAT 浮点数验证

    filter_validate_float 过滤器把值作为浮点数来验证。 */ $var=12.3; var_dump(filter_var($var, filter_validate_float)); //float(12.3) /* 非负浮点数(正浮点数...2016-11-25