php中strlen,mb_strlen,substr(),mb_substr()及mb_strcut的区别

 更新时间:2016年11月25日 17:09  点击:1669
文章详细的介绍了关于strlen,mb_strlen,substr(),mb_substr()及mb_strcut的区别和用法,有需要学习的同学可参考一下。

关于mb_*的字符串分割函数使用:
在win下的配置
需要按装php_mbstring.dll扩展
需要在php.ini在把php_mbstring.dll打开
linux下的配置 可以在网上搜索一下也很简单

 代码如下 复制代码

<?php
    //测试时文件的编码方式要是UTF8
    $str='中文a字1符';
    echo strlen($str).'<br>';//14
    echo mb_strlen($str,'utf8').'<br>';//6
    echo mb_strlen($str,'gbk').'<br>';//8
    echo mb_strlen($str,'gb2312').'<br>';//10
?>


结果分析:在strlen计算时,对待一个UTF8的中文字符是3个长度,所以“中文a字1符”长度是3*4+2=14,在mb_strlen计算时,选定内码为UTF8,则会将一个中文字符当作长度1来计算,所以“中文a字1符”长度是6

mb_strlen 默认编码可以通过

mb_internal_encoding()获取到。

利用这两个函数则可以联合计算出一个中英文混排的串的占位是多少(一个中文字符的占位是2,英文字符是

1 echo (strlen($str) + mb_strlen($str,'UTF8')) / 2;

PHP内置的字符串长度函数strlen无法正确处理中文字符串,它得 到的只是字符串所占的字节数。对于GB2312的中文编码,strlen得到的值是汉字个数的2倍,而对于UTF-8编码的中文,就是3倍的差异了(在 UTF-8编码下,一个汉字占3个字节)。

字符串分割
substr()函数可以分割文字,但要分割的文字如果包括中文字符往往会遇到问题,这时可以用mb_substr()/mb_strcut这个函数

mb_substr是按字来切分字符,而mb_strcut是按字节来切分字符,但是都不会产生半个字符的现象.


substr()函数可以分割文字,但要分割的文字如果包括中文字符往往会遇到问题,这时可以用mb_substr()/mb_strcut这个函数,mb_substr()/mb_strcut的用法与substr()相似,只是在mb_substr()/mb_strcut最后要加入多一个参数,以设定字符串的编码,但是一般的服务器都没打开php_mbstring.dll,需要在php.ini在把php_mbstring.dll打开。

举个例子:

 代码如下 复制代码
<?php
echo mb_substr('这样一来我的字符串就不会有乱码^_^', 0, 7, 'utf-8');
?>

输出:这样一来我的字

 代码如下 复制代码
<?php
echo mb_strcut('这样一来我的字符串就不会有乱码^_^', 0, 7, 'utf-8');
?>


输出:这样一
从上面的例子可以看出,mb_substr是按字来切分字符,而mb_strcut是按字节来切分字符,但是都不会产生半个字符的现象……

mbstring 函数的说明:


php的mbstring扩展模块提供了多字节字符的处理能力,平常最常用的就是用mbstring来切分多字节的中文字符,这样可以避免出现半个字符的情况,由于是php的扩展,它的性能也要比一些自定义的多字节切分函数要好上一些。

mbstring extension提供了几个功能类似的函数,mb_substr和mb_strcut,看看手册上对它们的解释。

mb_substr
mb_substr() returns the portion of str specified by the start and length parameters.

mb_substr() performs multi-byte safe substr() operation based on number of characters. Position is sqlserver/42852.htm target=_blank >counted from the beginning of str. First character's position is 0. Second character position is 1, and so on.

mb_strcut
mb_strcut() returns the portion of str specified by the start and length parameters.

mb_strcut() performs equivalent operation as mb_substr() with different method. If start position is multi-byte character's second byte or larger, it starts from first byte of multi-byte character.

It subtracts string from str that is shorter than length AND character that is not part of multi-byte string or not being middle of shift sequence.

再举个例子,有一段文字, 分别用mb_substr和mb_strcut来做切分:

PLAIN TEXT
CODE:

 代码如下 复制代码

<?php
$str = '我是一串比较长的中文-';

echo "mb_substr:" . mb_substr($str, 0, 6, 'utf-8');

echo "<br>";

echo "mb_strcut:" . mb_strcut($str, 0, 6, 'utf-8');
?>

输出结果如下:

mb_substr:我是一串比较
mb_strcut:我是

测试代码:

 代码如下 复制代码

/**
 * 字符串分割 按字分割
 * @param $content string
 * @param $length int
 * @param $etc string
 * @return string
 */
 function Truncate($content, $length, $etc = '...') {

        if ($length == 0) {
            return '';
        } elseif (mb_strlen($content,'utf-8') > $length) {
            $length -= min($length, mb_strlen($etc));
            $charset = 'utf-8';
            $content = mb_substr($content, 0, $length, $charset) . $etc;
        }
        return $content;
    }

    $str ='伏尔泰(1694~1778)法国资产阶级启蒙思想家,哲学家,史学家,文学家。伏尔泰原名F.M.阿鲁埃。';

    echo strlen($str);//字符串长度
 echo '<hr/>';
    echo mb_strlen($str,'utf-8');//字符串长度
 echo '<hr/>';
 echo mb_strcut($str,0,35,'utf-8');//按字节分割
 echo '<hr/>';
 echo mb_substr($str,0,35,'utf-8');//按字 分割
 echo '<hr/>';
    echo Truncate($str,35);//字符串截取方法

is_writable用来处理,记住 PHP 也许只能以运行 webserver 的用户名(通常为 \'nobody\')来访问文件。不计入安全模式的限制。

Example #1 is_writable() 例子

 代码如下 复制代码

<?php
$filename = 'test.txt';
if (is_writable($filename)) {
  echo 'The file is writable';
} else {
  echo 'The file is not writable';
}
?> 

上面的函数有一个问题就是filename 必需。规定要检查的文件  ,必须是文件啊,目录不可判断,下面我们来判断空目录。

实例1

该功能非常常用,特别在一些需要生成静态文件的项目中,一个目录是否可以,关乎到是否对该目录有创建文件删除文件的权限

 代码如下 复制代码

/*
  问题出现:如何检查一个目录是否可写,如何目录下还有目录和文件,那么都要检查
   
  思路:
   (1)首先先写出检查空目录是否可写的算法:
         在该目录中生成一个文件,如果不能生成,表明该目录没有写的权限
   
   (2)使用递归的办法来进行检查
  
  代码实现:
 */
  set_time_limit(1000);
  function check_dir_iswritable($dir_path){
  $dir_path=str_replace('\','/',$dir_path);
  $is_writale=1;
  if(!is_dir($dir_path)){
    $is_writale=0;
    return $is_writale;
  }else{
   $file_hd=@fopen($dir_path.'/test.txt','w');
   if(!$file_hd){
    @fclose($file_hd);
    @unlink($dir_path.'/test.txt');
    $is_writale=0;
    return $is_writale;
   }
   $dir_hd=opendir($dir_path);
   while(false!==($file=readdir($dir_hd))){
    if ($file != "." && $file != "..") {
     if(is_file($dir_path.'/'.$file)){
      //文件不可写,直接返回
      if(!is_writable($dir_path.'/'.$file)){
       return 0;
      } 
     }else{
      $file_hd2=@fopen($dir_path.'/'.$file.'/test.txt','w');
      if(!$file_hd2){
       @fclose($file_hd2);
       @unlink($dir_path.'/'.$file.'/test.txt');
       $is_writale=0;
       return $is_writale;
      }
      //递归
      $is_writale=check_dir_iswritable($dir_path.'/'.$file);
     }
    }
   }
  }
  return $is_writale;
  }

上面实例主要是fopen去在目录创建文件或在文件中写内容,这样就可以判断目录的读写权限了。

在php中禁止页面缓存的代码相当简单,只要利用 php header()浏览器发送一个Cache-Control: no-cache或设置页面缓存过期时间为你今天之前就可以了。

有朋友说给出下面这句最简单的禁止页面缓存的方法

 代码如下 复制代码
header("Cache-Control: no-cache, must-revalidate");


这里我先给一段可以使用的php代码:

 代码如下 复制代码
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Cache-Control: no-cache, must-revalidate");
header("Pragma: no-cache");

我们先来了解下HTTP响应的消息,其实我们可以使用Telnet命令来查看,下面我给出点HTTP响应内容:HTTP/1.1 200 OK
Server:Microsoft-IIS/6.0
Date: Thu, 31 Oct 2008 11:20:53 GMT
Content-Type: text/html
Set-Cookie: name=value; path=/
Cache-control: private
<html>

下面我们来详细的介绍一下。

 

 代码如下 复制代码
<?php   
  
//设置此页面的过期时间(用格林威治时间表示),只要是已经过去的日期即可。   
header("Expires: Mon, 26 Jul 1970 05:00:00 GMT");     
  
//设置此页面的最后更新日期(用格林威治时间表示)为当天,可以强制浏览器获取最新资料    
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");     
 
//告诉客户端浏览器不使用缓存,HTTP 1.1 协议    
header("Cache-Control: no-cache, must-revalidate");     
  
//告诉客户端浏览器不使用缓存,兼容HTTP 1.0 协议    
header("Pragma: no-cache");   
 


?> 

只要把上面代码放到你的php页面的最开始处就好了,要不header函数可能会出错。所以必须放在文档最开始处。

在php中对数组遍历用得最多要算是foreac,while,for这几种方法了,下面我们来介绍这三种遍历数组的实现程序代码吧。

经常会有人问我, PHP的数组, 如果用foreach来访问, 遍历的顺序是固定的么? 以什么顺序遍历呢?
比如:

 代码如下 复制代码
<?php$arr['laruence'] = 'huixinchen';
$arr['yahoo'] = 2007;
$arr['baidu'] = 2008;
foreach ($arr as $key => $val)
{
//结果是什么?
}

又比如:

 代码如下 复制代码

<?php
$arr[2] = 'huixinchen';
$arr[1] = 2007;$arr[0] = 2008;
foreach ($arr as $key => $val)
{
//现在结果又是什么?
}

HashTable结构示意图

, 当我们使用, each/next系列函数来遍历的时候, 也是通过移动数组的内部指针而实现了顺序遍历, 这里有一个问题, 比如:

 代码如下 复制代码

<?php
$arr = array(1,2,3,4,5);
foreach ($arr as $v) {//可以获取}
while (list($key, $v) = each($arr))

 {//获取不到}
?>

了解到我刚才介绍的知识, 那么这个问题也就很明朗了, 因为foreach会自动reset, 而while这块不会reset, 所以在foreach结束以后, pInternalPointer指向数组最末端, while语句块当然访问不到了, 解决的办法就是在each之前, 先reset数组的内部指针.

也就是说, PHP中遍历数组的顺序, 是和元素的添加先后相关的, 那么, 现在我们就很清楚的知道, 文章开头的问题的输出是:

huixinchen
2007
2008
所以, 如果你想在数字索引的数组中按照索引大小遍历, 那么你就应该使用for, 而不是foreach

 代码如下 复制代码
for($i=0,$l=count($arr); $i<$l; $i++)

{ //这个时候,不能认为是顺序遍历(线性遍历)}

 

在我使用php json_encode()时,如果是英文或数字没一点问题,但是用到中文是居然出现不可识别的中文乱码了,下面看我解决json_encode中文乱码方法。

在网上找到一种解决方法:

 代码如下 复制代码
<?php
/* 处理json_encode中文乱码 */
$data = array ('game' => '冰火国度', 'name' => '刺之灵', 'country' => '冰霜国', 'level' => 45 );
echo json_encode ( $data );
echo "<br>";
$newData = array ();
foreach ( $data as $key => $value ) {
$newData [$key] = urlencode ( $value );
}
echo urldecode ( json_encode ( $newData ) );
?>

后来请教了别人,还可以用base64编码,不过base64编码不可以放在URL中,百度是这样解释的:

标准的Base64并不适合直接放在URL里传输,因为URL编码器会把标准Base64中的“/”和“+”字符变为形如“%XX”的形式,而这些“%”号在存入数据库时还需要再进行转换,因为ANSI SQL中已将“%”号用作通配符。

不过我的数据是要通过POST发送的,并不在HTTP 的head中,而在message-body里,所以不受影响。

json_encode 只能接受utf-8格式的数据


例如:'胥'经过json_encode处理后变为'u80e5',最终的json中中文部分被替换为unicode编码。我们要解决的就是将对象转换为json并保证对象内部的中文在json中仍然是以正常的中文出现,现在看来只使用json_encode是不能达到目的的。
  我的解决方法:先将类中的中文字段进行url编码(urlencode),然后再对对象进行json编码(jsonencode),最后url解码(urldecode)json,即最终的json,里面的中文依旧是那个中文!
测试代码如下:

 代码如下 复制代码
<?php
class myClass {
public $item1 = 1;
public $item2 = '中文';
function to_json() {
//url编码,避免json_encode将中文转为unicode
$this->item2 = urlencode($this->item2);
$str_json = json_encode($this);
//url解码,转完json后将各属性返回,确保对象属性不变
$this->item2 = urldecode($this->item2);
return urldecode($str_json);
}
}
$c = new myClass();
echo json_encode($c);
echo '<br/>';
echo $c->to_json();
echo '<br/>';
echo json_encode($c);
echo '<br/>';
echo json_encode('胥');
?>

程序输出结果:

 代码如下 复制代码
{"item1":1,"item2":"u4e2du6587"}
{"item1":1,"item2":"中文"}
{"item1":1,"item2":"u4e2du6587"}
"u80e5"
[!--infotagslink--]

相关文章

  • mysql_connect与mysql_pconnect的区别详解

    在mysql中我们会看到有两种常用的数据库连接模式,一种是长久连接,另一各是页面访问完之后就断了连接,下面我来分别介绍mysql_connect与mysql_pconnect的区别,有需要了解...2016-11-25
  • C#中out与ref的区别实例解析

    这篇文章主要介绍了C#中out与ref的区别实例解析,对C#初学者有不错的学习借鉴价值,需要的朋友可以参考下...2020-06-25
  • PHP中func_get_args(),func_get_arg(),func_num_args()的区别

    复制代码 代码如下:<?php function jb51(){ print_r(func_get_args()); echo "<br>"; echo func_get_arg(1); echo "<br>"; echo func_num_args(); } jb51("www","j...2013-10-04
  • 谈谈Jquery中的children find 的区别有哪些

    精华:find方法能找子孙,children方法只能找儿子一、Jquery中children 语法.children(selector) 说明expr是表达式,可选参数,所有选择器中的表达式都可以用在这,比如按标签名"div",按类名".class",按序号":first"等等,如果表...2015-10-21
  • PS中像素大小、文档大小的区别

    在PS中像素大小、文档大小有什么区别呢,这个估计很多初学者不清楚,下面我来给大家讲解一下,希望对你有帮助。 1、像素大小 通常用于显示屏显示的图片大小的调整。菜...2016-09-14
  • C#中sleep和wait的区别分析

    这篇文章主要介绍了C#中sleep和wait的区别分析,有助于深入理解C#中线程的原理与使用技巧,非常具有实用价值,需要的朋友可以参考下...2020-06-25
  • uniapp和vue的区别详解

    这篇文章主要介绍了uniapp和vue的区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-10-19
  • list与push的区别

    //函数list while(list($id,$username,$password,$add_date,$mdn,$mobile,$channel,$last_date,$area,$nickname) = mysql_fetch_array($rs)){ ...2016-11-25
  • input框中的name和id的区别

    这篇文章主要介绍了input框中的name和id的区别介绍,非常不错,具有参考借鉴价值,需要的朋友可以参考下...2016-11-22
  • php switch 与 if else 区别

    在php中switch是选择,if else也有同理,但是它们肯定是有区别的,那么我们来看看它们两者的区别在哪里呢,下面先看switch case语句吧。 switch($id){ case 1: ...2016-11-25
  • 浅谈C++中字符串输入get与getline的区别

    这篇文章主要介绍了C++中字符串输入get与getline的区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-04-25
  • php mysql localhost,127.0.0.1和ip区别

    一家之言:localhost与127.0.0.1的区别 localhost与127.0.0.1的区别是什么?相信有人会说是本地ip,曾有人说,用127.0.0.1比localhost好,可以减少一次解析。看来这个入门问题还有人不清楚,其实这两者是有区别的。no1:localhos...2014-05-31
  • C#中类与接口的区别个人总结

    这篇文章主要介绍了C#中类与接口的区别个人总结,本文讲解了类与接口的区别、接口的用处主要体现在下面几个方面、一些接口的疑问等内容,需要的朋友可以参考下...2020-06-25
  • 详解CSS3中nth-child与nth-of-type的区别

    这篇文章详细解析了CSS3中nth-child与nth-of-type的区别,有兴趣的同学可以参考一下 CSS3中nth-child与nth-of-type的区别其实很简单::nth-of-type为什么要叫:nth-of...2017-01-22
  • include包含头文件的语句中,双引号和尖括号的区别(详解)

    下面小编就为大家带来一篇include包含头文件的语句中,双引号和尖括号的区别(详解)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2020-04-25
  • 英语单词state与status的区别

    state倾向于condition,是一种延续性的状态。status常用于描述一个过程中的某阶段(phase),类似于C语言中枚举型变量某一个固定的值,这个值属于一个已知的集合。这篇文章主要介绍了英语单词state与status的区别,需要的朋友可以参考下...2020-06-25
  • php echo print print_r三者区别分析

    php教程 echo print print_r三者区别分析 echo是PHP语句, print和print_r是函数,语句没有返回值,函数可以有返回值(即便没有用) print() 只能打印出简单类型变量的...2016-11-25
  • $i++ ++$i 运行速度与区别

    关于$i++与++$i是什么区别了,下面来看看这些区别的分别。 <?php 方式一: $begin = time(); $i = 0; while(++$i < 10000) { $j = 0; while(++$j < 10000)...2016-11-25
  • php strtr与str_replace区别比较

    php strtr与str_replace区别比较 函数都是具有替换字符功能的。但是strtr比str_replace性能上要块4倍。具体情况请 看如下分解: 首先是strtr函数: 实例1:当 以下为引用的...2016-11-25
  • PHP中file_exists与is_file,is_dir的区别

    在php中file_exists与is_file,is_dir都可以用来检测目录或文件是否存在了,那么它们三者的具体区别在哪里呢,下面我们一起来看看吧。 很显然file_exists是受了asp...2016-11-25