分类 默认分类 下的文章

先引入类IOFactory.php

require_once '../PHPExcel/IOFactory.php';
$filePath = "test.xlsx";  // 测试文件

加载测试文件

$inputFileType = PHPExcel_IOFactory::identify($filePath) 判断文件类型
$objReader = PHPExcel_IOFactory::createReader($inputFileType); 实例化类型对象
$objPHPExcel = $objReader->load($filePath); 加载文件

下面主要判断Excel2007和Excel5类型,即xlsx/xlsm/xltx/xltm和xls/xlt格式文件

try {
    $inputFileType = PHPExcel_IOFactory::identify($filePath);
    if ($inputFileType !== "Excel5" && $inputFileType !== "Excel2007" ) {
        unlink($filePath) && str_alert(-1,"请确保导入的文件格式正确!");
    }
    $objReader = PHPExcel_IOFactory::createReader($inputFileType);
    $objPHPExcel = $objReader->load($filePath);
} catch(Exception $e) {
    unlink($filePath) && str_alert(-1,'加载文件发生错误:”'.pathinfo($filePath,PATHINFO_BASENAME).'”: '.$e->getMessage());
    }

获取当前工作表

$sheet = $objPHPExcel->getSheet(0);
//或者
$sheet = $objPHPExcel->getActiveSheet();

获取工作表行数和列数

$highestRow = $sheet->getHighestRow();
$highestColumn = $sheet->getHighestColumn();

注意:有时候你会发现你的表格明明有内容的行数就5行,但是获取到的$highestRow却有7,8行或者更多,这可能是因为你在操作你的表格的时候不小心点击了其它行数,虽然没有填写内容,但getHighestRow也是能够识别出行数;
想要获取有内容的行数应该使用getHighestDataRow和getHighestDataColumn
源码注释是这样介绍的string Highest row number that contains data,即包含数据的字符串最高行数.

单元格具体内容
xlsx类型的表格单元格是通过类似xy轴坐标来获取的,

可通过类似

 $sheet->getCell("A1")->getValue();
 $sheet->getCell("B2")->getValue();

获取相应位置的内容,
如果不想通过字母了来遍历获取,可以用数字索引方法

  $sheet->getCellByColumnAndRow(0,1);
  $sheet->getCellByColumnAndRow(1,2);

注意坐标中第一个参数从0开始,0代表A,1代表B...,第二个参数从1开始.
下面是遍历表格获取全部单元格内容:

$dataSet=array();
for ($column = "A"; $column <= $highestColumn; $column++) {//列数是以A列开始
    for ($row = 4; $row <= $highestRow; $row++) { //行数是以第4行开始
        $cell = $sheet->getCell($column . $row)->getValue();
        if($cell instanceof PHPExcel_RichText) { //富文本转换字符串
            $cell = $cell->__toString();
        }
        $dataSet[$row][] = $cell;
    }
}

其中富文本转换字符串,是使用$cell instanceof PHPExcel_RichText判断是否为富文本,查阅资料发现如果你的单元格中字符串包含两种以上的字体会自动被设为富文本,这时候需要__toString()转换

判断合并单元格是否位于最左上角
当我们循环输出所有单元格后发现,一些被合并的单元格只有最左上坐标的是有内容的,其他都是null
例如A4,A5合并成一个单元格,getCell("A4")是有正常内容的,但是getCell("A5")是null.
isMergeRangeValueCell可以用来判断某个具体的单元格是否为最左上角

$sheet->getCell('A' . $row)->isMergeRangeValueCell()

当$row为4的时候是返回true,5的时候返回false

转换时间格式的处理
获取表格中时间格式的内容,需要PHPExcel_Shared_Date::ExcelToPHP()来转换为php可识别的时间格式

date('Y-m-d',PHPExcel_Shared_Date::ExcelToPHP($sometime);


//例子
$cell = $sheet->getCell($column . $row)->getValue();
//日期格式判断
if (is_float($cell)) {
    $date = gmdate('Y-m-d', PHPExcel_Shared_Date::ExcelToPHP($cell));
} elseif (preg_match("/(\d{4}\/\d{1,2}\/\d{1,2}|\d{4}-\d{1,2}-\d{1,2})/", $cell)) {
    $date = zmf::time(strtotime($cell), 'Y-m-d');
} else {
    return $this->jsonOutPut(0, "第{$row}行数据日期格式不正确,请确认");
}

最近数据库服务器多事之秋,莫名的批量宕机事件一再发生,搞得压力超大。厂商来了之后也酥手无策。上周路过寺庙,平生第一次感叹道是否要去烧烧香,拜托拜托数据库之神能让我们团队早日度过这个劫难。

上周和William聊到MySQL的参数sql_slave_skip_counter,感叹很多人并没有真正了解这个参数的含义。面试时这是一个很好的问题,相信即使是淘宝P7的level,要准确答对这个问题也是需要平时的细心累积。

01

很多同学的误区在于会把参sql_slave_skip_counter=N理解成跳过N个事务。如果这样的回答,至少在我心中已经扣分不少,要拿高P几乎不可能。首先看看文档中的定义:

SET GLOBAL sql_slave_skip_counter = N

This statement skips the next N events from the master. This is useful for recovering from replication stops caused by a statement.

官方文档中明确指出N表示的是N个event。很多同学把这个参数的单位理解成事务的原因在于他把操作都理解成了由单条语句所组成的事务。这时N的含义两者等价。

然而,更常见的场景却是一个事务可能由多个EVENT组成,例如一个事务可以有多个SQL组成,例如:

BEGIN; INSERT ...;DELETE ...; INSERT; COMMIT;

若这时将N理解成事务,那么结果就会非常不同。当然,答对参数sql_slave_skip_counter的单位是事务,这个答案也仅只有60分。

02

如果细看文档的话,文档最后一段还说道:

When you use SET GLOBAL sql_slave_skip_counter to skip events and the results in the middle of a group, the slave continues to skip events until it reaches the end of the group. Execution then starts with the next event group.

这句非常关键,也就是说可能上面的答案是:以上全错。N可以不表示跳过N个事务,甚至可能是跳过>=N个事务的场景。假设开始时主、从的数据分别为:

Master

Slave
a
1
2
3

+----+ +----+

a
1
3

由于主从数据已然不一致,这时若在主上执行下面的SQL:

BEGIN;

INSERT INTO Z SELECT 4;

DELETE FROM Z WHERE a = 2;

INSERT INTO Z SELECT 5;

COMMIT;

从机显然会报错,提示1032错误,因为记录2这条记录并没有找到。这时的处理方法很多DBA会选择执行SET GLOBAL sql_slave_skip_counter=1。然而,这样的处理会导致INSERT 5这条记录不被执行。因为跳过DELETE 2这个操作后,事务没有结束,会继续跳过接下去的event,这就是文档中说的:the slave continues to skip events until it reaches the end of the group。感兴趣的同学可以自行测试看看最终的结果。

若只想跳过一个EVENT该怎么做呢?其实,只需将参slave_exec_mode设置为IDEMPOTENT即可。

03

出现主从复制出错,最安全的方法还是重建从机。另外,MySQL的复制早就是crash safe的复制机制了。若你的复制环境经常出错,应该好好检查下数据库的配置参数。

对于参数sql_skip_slave_counter来说,这只是一个不得已为之的方法。同时,当开启GTID模式时,也无法通过参数进行跳过出错的EVENT。

原文:https://mp.weixin.qq.com/s/rZZbLmN0Klq0o0bvnijizw

解决python pip 安装报语法错误sys.stderr.write(f“ERROR: {exc}“)

https://bootstrap.pypa.io/ 下载相应python版本的 get-pip.py 文件

wget https://bootstrap.pypa.io/2.7/get-pip.py
python get-pip.py

安装成功:Successfully installed pip-20.3.4 wheel-0.36.2

再运行我想要的bt系统,结果报错了

# bt start
Starting Bt-Panel... failed
------------------------------------------------------
Traceback (most recent call last):
  File "main.py", line 16, in <module>
    import sys,web,io,os
ImportError: No module named web
------------------------------------------------------
Error: BT-Panel service startup failed.

原因是web.py模块没有安装,用pip安装试试, 还是报错,不过这次是不一样的错误,原因是6.10的系统2.7的python需要安装指定版本的web.py

pip install web.py==0.51

结果成功,bt也成功运行起了

PS:测试环境 centos 6.10, python 2.7

安装脚本setuptools:

wget https://bootstrap.pypa.io/ez_setup.py -O - | python

一. 透明代理(Transparent Proxies) 目标服务器能够检测到真实的源IP。
使用透明代理,对方服务器可以知道你使用了代理,并且也知道你的真实IP。透明代理访问对方服务器所带的HTTP头信息如下:

REMOTE_ADDR = 代理服务器IP
HTTP_VIA = 代理服务器IP
HTTP_X_FORWARDED_FOR = 你的真实IP              

透明代理还是将你的真实IP发送给了对方服务器,因此无法达到隐藏身份的目的。
二. (普通)匿名代理(Anonymous Proxies)目标服务器无法检测到真实的源IP,但能够检测到使用了代理。
匿名代理访问对方服务器所带的HTTP头信息如下:

REMOTE_ADDR = 代理服务器IP
HTTP_VIA = 代理服务器IP
HTTP_X_FORWARDED_FOR = 代理服务器IP              

匿名代理隐藏了你的真实IP,但是向访问对象透露了你是使用代理服务器访问他们的。

三. 高匿名代理(High Anonymity Proxies -Elite proxies) 目标服务器无法检测到你在是使用代理。
高匿名代理访问对方服务器所带的HTTP头信息如下:

REMOTE_ADDR = 代理服务器IP
HTTP_VIA 不显示
HTTP_X_FORWARDED_FOR 不显示              

高匿名代理隐藏了你的真实IP,同时访问对象也不知道你使用了代理,因此隐蔽度最高。

squid搭建高匿名代理服务: https://www.jianshu.com/p/96c8f1f7fd17