字符编码些许事,手机短信为什么要限定70个汉字
分类:技术中心

图片 1

编码

关于编码方式,当然可以采用类似ASCII字符集的编码方式——代码点等值转换法(这是我自己起的名字)。既然Unicode代码点的值的范围是0~0x10FFF,那么可以用一个21bit的编码单元来编码,直接把代码点等值转换成21bit的二进制序列。

但是这存在一个空间使用的问题,例如对于使用英语的人而言,ASCII基本可以满足使用。如果使用ASCII码,只需要1个字节来存储字符,但是若使用刚才的思路,需要将近3个字节来存储,这显然是浪费空间的。

如果需要支持的字符集再少一些,仅支持编号0的平面,那至少也有65535个字符,需要16bit的空间(2字节)来存储一个字符,即UCS-2编码,这种编码用来存储ASCII字符也是一种浪费。

Unicode在很长一段时间内无法推广,直到互联网的出现,为解决Unicode如何在网络上传输的问题,于是面向传输的众多 UTF(UCS Transfer Format)标准出现了,顾名思义,UTF-8就是每次8个位传输数据,而UTF-16就是每次16个位。UTF-8就是在互联网上使用最广的一种Unicode的实现方式,这是为传输而设计的编码,并使编码无国界,这样就可以显示全世界上所有文化的字符了。

/*************************************************/

对编程技术有所了解的同学知道,由于字符本身使用编码方式的不同,最终将导致字符个数的不同。对于英文字母而言,一般采用7位ASCII编码,中文则为8位UCS-2编码,需要占用2个字节。

有道翻译

用有道翻译的API来做演示,我们通过API获取单词"word"的中文翻译。

GET http://fanyi.youdao.com/openapi.do?keyfrom=WoxLauncher&key=1247918016&type=data&doctype=json&version=1.1&q=word

返回的JSON如下所示:

{
  "translation": [
    "词"
  ],
  "basic": {
    "us-phonetic": "wɝd",
    "phonetic": "wɜːd",
    "uk-phonetic": "wɜːd",
    "explains": [
      "n. [语] 单词;话语;消息;诺言;命令",
      "vt. 用言辞表达",
      "n. (Word)人名;(英)沃德"
    ]
  },
  "query": "word",
  "errorCode": 0,
  "web": [
    {
      "value": [
        "单词",
        "字",
        "字 (计算机)"
      ],
      "key": "word"
    },
    {
      "value": [
        "构词法",
        "造词法",
        "词性转换"
      ],
      "key": "Word Formation"
    },
    {
      "value": [
        "关键字",
        "中心词",
        "关键词"
      ],
      "key": "key word"
    }
  ]
}

返回的内容包含中文,从响应头我们可以看到返回的JSON使用了UTF-8编码:

图片 2

Paste_Image.png

用Wireshark抓包看看具体内容:

图片 3

Paste_Image.png

如上图所示,translation这个key对应的数组内容应该是"词",所以我们看到高亮区域的内容是22 E8 AF 8D 22,0x22对应ASCII字符",0xE8 0xAF 0x8D正是中文的UTF-8编码。

7位元字符就是指标准ASCII去掉最高位的0。以这种方式进行编码,在美国这样的国家,发送的短信字符都是ASCII码表里的,所以没必要浪费一个字位。

这就是为什么运营商规定单条短信的汉字限制为70个的原因。

GB系列字符集

中文环境下如果要正常显示字符,仅依靠ASCII字符集是不行的,因此我们国家制订了一系列的国标(GB),其中就包括GB2312、GB13000、GBK、GB18030......,最新的标准是GB18030,包含70244个字符。

而短信协议支持7字位、8字位、16字位3种编码,7字位用于美国,可以发送160个字母,8字位用于欧洲国家,16字位用于中日韩俄等国家,使用UCS-2编码。而UCS-2把所有Unicode字符编码为2字节,所以即使英文字母也会编码成2个字节。

P.S 对于没有使用过功能机的人来说,可能一直都不知道原来短信是有字数限制的。返回搜狐,查看更多

UTF-8

UTF-8最大的一个特点,就是它是一种变长的编码方式。它可以使用1~4个字节表示一个符号,根据不同的符号而变化字节长度,当字符在ASCII 码的范围时,就用一个字节表示,保留了ASCII字符一个字节的编码做为它的一部分,注意的是Unicode一个中文字符占2个字节,而UTF-8一个中 文字符占3个字节)。从Unicode到UTF-8并不是直接的对应,而是要过一些算法和规则来转换。

Unicode符号范围(十六进制) UTF-8编码方式(二进制)
0000 0000-0000 007F 0xxxxxxx
0000 0080-0000 07FF 110xxxxx 10xxxxxx
0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx
0001 0000-0010 FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

举个例子:
还是用中文“一”,其Unicode值为0x4E00,落在0800-FFFF的范围内,事实上中文基本上都在这个区域。0x4E00的二进制表示为01001110 00000000,转换成UTF-8就是11100100 10111000 10000000,对应的十六进制表示是0xE4 0xB8 0x80。

 

原标题:手机短信为什么要限定70个汉字?iPhone发短信有字数限制吗?

UTF-32

UTF-32采用代码点等值转换法,将每个代码点编码为1个32bit的编码单元(四字节),因此空间效率较低,不如其它Unicode编码应用广泛。

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.tsh.sms.MainActivity" >

    <TextView
        android:id="@ id/tv_input_number"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:text="@string/input_tel_number" />

    <EditText
        android:id="@ id/et_number"
        android:singleLine="true"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_below="@id/tv_input_number"
        android:ems="10"
        android:inputType="phone" >

        <requestFocus />
    </EditText>

    <TextView
        android:id="@ id/tv_number"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_below="@id/et_number"
        android:text="@string/sms_content" />

    <EditText
        android:id="@ id/et_content"
        android:lines="5"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_below="@id/tv_number"
        android:ems="10" />

    <Button
        android:id="@ id/bt_send"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_below="@id/et_content"
        android:text="@string/send" />

</RelativeLayout>

Friedhelm Hillebrand45岁的时候,他觉得如今手机短信160个字符已经足够使用,于是决定把这个数字定为一条短信内容的字数上线。

ASCII字符集

通常说的ASCII字符集不包括扩展集,只有128个字符,因此其编码的存储只需要使用7个bit,一个字节足够了最高位永远都是0。比如字符'0',其代码是十六进制的0x30,二进制表示为00110000。

这里说个和ASCII字符集有关的编码方案,GSM标准协议规定单条短信最多存储140个字节的内容,如果短信内容只包含ASCII字符,因为ASCII字符的数据首位必定是0,所以GSM标准中规定了7bit编码的短信格式,只用7个bit来连续存储ASCII字符,这样原本140个8bit的存储空间,就可以存储160个7bit的数据。如果谁现在手上还有NOKIA手机,可以拿起来看看只包含ASCII字符的短信是不是可以输入160个字符,如果短信中包含了非ASCII字符(比如中文),那么所有字符都会变成双字节存储的编码(UCS-2编码),一条短信的内容就恢复成只能发送70个字符。现如今的智能手机大多都支持短信拼接,并不是说单条短信的容量增加了,而是将你编写的超过单条短信容量的短信分成多条发送,运营商也是按多条短信计的。

 

原因要追溯到上世纪80年代,Friedhelm Hillebrand是如今手机短信技术的主发明人,70个汉字(160个英文字符)就是他引起的。

基础概念

  • 字符
    字符是各种文字和符号的总称,包括各国家文字、标点符号、图形符号、数字等,甚至还可以包括无法显示的字符(比如ASCII标准定义了128个字符,其中33个字符无法显示)。
  • 字符集
    为了使计算机能够处理字符信息,首先要决定选取哪些字符。这样就形成了一个集合,或者说一个表,称为字符表(character repertoire)。当然,也可以认为这就是一个字符集(character set)。
    例如,将所有的英文字母放在一起可以组成一个字符集,将所有的汉字放在一起可以组成一个字符集,等等。
  • 编码字符集
    对一个字符集中的所有字符进行编号,这种编号后的字符集叫做编码字符集(这里的编码仅仅指编号,不同于下文中的编码)。常见的编码字符集有ASCII、Unicode、GBK等。

可以这样来理解:字符串是由字符构成,字符在计算机硬件中通过二进制形式存储,这种二进制形式就是编码。如果直接使用 “字符串️字符️二进制表示(编码)” ,会增加不同类型编码之间转换的复杂性。所以引入了一个抽象层,“字符串️字符️与存储无关的表示️二进制表示(编码)” ,这样就可以用一种与存储无关的形式表示字符,不同的编码之间转换时可以先转换到这个抽象层,然后再转换为其他编码形式。
举个例子:Unicode 就是 “与存储无关的表示”,UTF-8 就是 “二进制表示”。

使用Windows Mobile 6系统做测试,新建短信后输入一个英文字母,下面显示1/160,再输入一个显示2/160,这就是7字位状态,可以在140字节里装下160个字符。当再输入一个汉字的时候,下面的显示立刻变成3/70,这就是16字位状态,每个字符都占2个字节,140字节只能装下70个字符,哪怕里面是69个英文字符加1个汉字。

责任编辑:

  • 《字符编码的故事:ASCII,GB2312,Unicode,UTF-8,UTF-16》
  • 《unicode,ansi,utf-8,unicodebigendian编码的区别》

 

160个英文字符要用7位ASCII编码来进行表示,需要7*160位。然而换成8位UCS-2编码表示,则需要7*160/8位。同时,由于中文汉字需要占用2个字符,这样中文字符总数就是7*160/8/2,刚好等于70。

举几个栗子

使用139邮箱做测试,里面发送短信无论什么字符都是以UCS-2编码,当输入135个字符时,显示将按3条短信计费。另外,说明里还提到,最多只能支持350字的短信。

随着短信技术的发展,各大运营商也纷纷把160个字符作为单条短信的上线。

工具推荐

这里有个网站提供的转码效果非常好,比起某些站长工具更标准。

图片 4

Paste_Image.png

上图是使用该网站查找中文字符“一”的结果,可以看到其Unicode值为U 4E00,UTF-8编码为0xE4 0xB8 0x80,在URL中需要转码为一,在js脚本中则是u4e00......。

短信都要最大长度的限制的,android提供了一个api用来拆分短信divideMessage(),返回ArrayList<String>,循环发送for(String str:contents){}

其实,是有历史原因的。

Unicode字符集

Unicode字符集由多语言软件制造商组成的统一码联盟(Unicode Consortium)与国际标准化组织的ISO-10646工作组制订,为各种语言中的每个字符指定统一且唯一的代码点,以满足跨语言、跨平台转换和处理文本的要求。中、日、韩的三种文字占用了Unicode中0x3000到0x9FFF的部分 Unicode目前普遍采用的是UCS-2编码,它用两个字节来编码一个字符, 比如汉字"一"的编码是0x4E00。事实上Unicode对汉字支持不怎么好,这也是没办法的,简体和繁体总共有六七万个汉字,而UCS-2最多能表示65536个,所以Unicode只能排除一些几乎不用的汉字,好在GB2312字符集中常用的简体汉字也不过6763个,为了能表示所有汉字,Unicode也有UCS-4规范,就是用 4个字节来编码字符。

Unicode代码点范围为0x00x10FFFF,共计1114112个代码点,划分为编号016的17个字符平面,每个平面包含65536个代码点。其中编号为0的平面最为常用,称为基本多语种平面(Basic Multilingual Plane, BMP);其他平面则称为辅助语言平面。

为了描述一个代码点,可以采用U加十六进制整数的方法。比如,U 0041表示英文大写字母A,U 4E00表示汉字”一”。

 

他当时使用一台打字机随意打出一些由字母组成的信息,令人奇怪的是,这些信息每一条都是只有一两行,而且总字数也不会超过160个,160便成为他感觉颇具神奇的数字。

UTF-16

UTF-16的编码单元是16bit,对于每个代码点,采用1个或者2个编码单元来表示,因此这是一个变长表示。

一则短信能够容纳140字节,也就是约160个7位元的字符、或是140个8-bit的字符,中文字、韩文字与日文字这些占2-byte的字符则可容纳70个。(使用Unicode系统)。这些不包括额外的系统资讯。

图片 5

ONE·一个

这个API是通过抓包抓出来的,谁让他们不走https呢?

GET http://v3.wufazhuce.com:8000/api/reading/index

返回数据太多,仅截取一小段进行分析。

{
  "res": 0,
  "data": {
    "essay": [
      {
        "content_id": "2176",
        "hp_title": "软糖| “白日梦” _ 初夏的味道",
        "hp_makettime": "2017-04-03 06:00:00",
        "guide_word": "我们每周会选择一个主题,由七个作者绘制不同风格的短篇漫画,每天一幅。",
        "start_video": "",
        "author": [
          {
            "user_id": "7742828",
            "user_name": "双麒_宋 ",
            "desc": "因爱而画,美好的作品产生于最压抑的欲望。",
            "wb_name": "",
            "is_settled": "0",
            "settled_type": "0",
            "summary": "因爱而画,美好的作品产生于最压抑的欲望。",
            "fans_total": "574",
            "web_url": "http://image.wufazhuce.com/FoPpyeue8ajoRlZ4Fy39a56o4NO-"
          }
        ],
    ......
    }
......
}

返回的内容包含中文,但从响应头我们看不到返回的JSON使用了什么编码格式:

图片 6

Paste_Image.png

用Wireshark抓包看看具体内容:

图片 7

Paste_Image.png

如上图所示,这个API请求返回的JSON数据输出的是中文的Unicode转义字符,这其实也是JS对中文的标准处理方式,猜测后台可能是NodeJS实现的。

我是咕咕鸡,一个还在不停学习的全栈工程师。
热爱生活,喜欢跑步,家庭是我不断向前进步的动力。

维基百科里「短信」词条如下定义「短信」:

为什么要限制在70个汉字?多设置一点不好吗?

我不想写一篇大而全的文章,也无力去查找那么多资料涵盖所有知识点,如果想了解更多信息,这里有几篇我认为写得不错的文章可以提供参考,本文也部分借鉴了其中的内容。

比如,输入70个中文,下面显示70/70,再加一个时下面显示“71/134(2短信息)”。输入160个英文,下面显示160/160,再加一个显示“161/306(2短信息)”。

用过功能机的小伙伴们都会知道,每一条短信的字数被限制在70个汉字,超过之后就会被拆分为2条短信发送。

知乎:什么是 7 位元的字符? 英文字符难道不是 8 bit 是一个字符?一条短信到底能容下 140 个英文字符还是 160 个?

  1. 拖动控件的话编译器自动加的layout_blow=”@ id/xxx” id那个部分没有 号
    Ctrl f批量替换
    EditText显示的行数android:singleLine="true"一行, android:lines="5" 多行
    模拟器超时原因 电脑配置低,修改超时时间,模拟器socket挂了,重启一下
    短信api SmsManager如果过时,导包的问题gsm 2G时代的,如果一个类无法new对象,那么它一定存在一个getDefaut或者getInstance的静态方法

  2. SmsManager的方法
    sendDataMessage(发送彩信)
    sendMultipartTextMessage(发送多条信息),
    sendTextMessage(目标手机, null(来源手机不支持), text, sentIntent, deliveryIntent)后两个参数,延迟报告和送达报告,不关心填null
    需要这个权限 android.permission.SEND_SMS

 

 

activity代码:

package com.tsh.sms;

import java.util.ArrayList;

import android.app.Activity;
import android.os.Bundle;
import android.telephony.SmsManager;
import android.text.TextUtils;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class MainActivity extends Activity implements OnClickListener {
    private EditText et_number;
    private EditText et_content;
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button bt_send=(Button) findViewById(R.id.bt_send);
        et_number=(EditText) findViewById(R.id.et_number);
        et_content=(EditText) findViewById(R.id.et_content);
        bt_send.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
        case R.id.bt_send:
            String number=et_number.getText().toString().trim();
            String content=et_content.getText().toString().trim();
            if(TextUtils.isEmpty(number)||TextUtils.isEmpty(content)){
                Toast.makeText(this, "电话号码和内容都不能为空", Toast.LENGTH_SHORT).show();
                return;
            }
            SmsManager smsManager=SmsManager.getDefault();
            ArrayList<String> contents = smsManager.divideMessage(content);
            for(String str:contents){
                smsManager.sendTextMessage(number, null, str, null, null);
            }

            break;
        }
    }
}

layout代码

/*****************2016年4月23日 更新********************************/

如果短信超过长度,那么系统就自动分成多条短信来发。因为要加入一些标识性字符以表示顺序,所以英文每条153个,中文每条67个。接收方如果是新一点的手机就会把这几条合并后显示给用户,老一点的手机就会分别显示每条短信。

yskin:

 

还有我的手机怎么是最多 150 个英文字母?这是 7.5 位元的编码方式吗?

divideMessage

需要开启两个模拟器测试,电话号码就是端口号,此功能可以做出短信群发器

 

楼主提到的150字限制没听说过,英文Google没找到,中文Google只搜到09年时电信在测试150字符短信系统。

 

本文由澳门新葡8455最新网站发布于技术中心,转载请注明出处:字符编码些许事,手机短信为什么要限定70个汉字

上一篇:30Pro概念机曝光,屏下指纹【澳门新葡8455最新网 下一篇:没有了
猜你喜欢
热门排行
精彩图文