UTF-8 中的一个字符可能的长度为 1 到 4 字节,遵循以下的规则:
对于 1 字节的字符,字节的第一位设为0,后面7位为这个符号的unicode码。
对于 n 字节的字符 (n > 1),第一个字节的前 n 位都设为1,第 n+1 位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的unicode码。
这是 UTF-8 编码的工作方式:
Char. number range | UTF-8 octet sequence
(hexadecimal) | (binary)
--------------------±--------------------------------------------
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
给定一个表示数据的整数数组,返回它是否为有效的 utf-8 编码。
注意:
输入是整数数组。只有每个整数的最低 8 个有效位用来存储数据。这意味着每个整数只表示 1 字节的数据。
示例 1:
data = [197, 130, 1], 表示 8 位的序列: 11000101 10000010 00000001.
返回 true 。
这是有效的 utf-8 编码,为一个2字节字符,跟着一个1字节字符。
示例 2:
data = [235, 140, 4], 表示 8 位的序列: 11101011 10001100 00000100.
返回 false 。
前 3 位都是 1 ,第 4 位为 0 表示它是一个3字节字符。
下一个字节是开头为 10 的延续字节,这是正确的。
但第二个延续字节不以 10 开头,所以是不符合规则的。
class Solution:
def validUtf8(self, data: List[int]) -> bool:
# print(data)
if data == None:
return False
data_len = len(data)
# 获取utf-8字符字节的数量
utf_size = self.get_uft_size(data, 0)
res = self.get_is_valid_utf(data, data_len, 0, utf_size)
return res
# data:整数数组
# data_len:整数数组长度
# start:开始位置的索引
# utf_size:utf字符字节的长度
def get_is_valid_utf(self, data, data_len, start, utf_size):
# UTF-8字符的长度大于4或小于,是异常的,直接返回False
# print(start, utf_size, data_len)
if( utf_size < 1 or utf_size > 4):
return False
# 开始位置加上该字符串的长度大于数组的总长度,则说明字符缺数据,直接返回False
if start + utf_size > data_len:
return False
if utf_size != 1:
# 如果该utf-8字符长度大于1,则判断后面的字节前两位是否10
for i in range(start + 1, start + utf_size):
# 将后面的每一个元素都转换成二进制字符串
binary = '{:08b}'.format(data[i])
# print(binary)
if binary[0] != '1' or binary[1] != '0':
return False
# 如果data中所有数据都遍历完,则返回True
if start + utf_size == data_len:
return True
# 更新开始索引
start = start + utf_size
utf_size = self.get_uft_size(data, start)
return self.get_is_valid_utf(data, data_len, start, utf_size)
def get_uft_size(self, data, start):
# 获取第一个字节的二进制字符串
binary = '{:08b}'.format(data[start])
# 对于 1 字节的字符,字节的第一位设为0
if binary[0] == '0':
return 1
else:
# 下面是字符的字节个数大于1的情况
utf_size = 0
# 对于 n 字节的字符 (n > 1),第一个字节的前 n 位都设为1,第 n+1 位设为0
for j in range(8):
# print(binary, binary[j])
if binary[j] == '0':
break
utf_size += 1
# 如果utf_size小于2,则跟规则不相符
if utf_size < 2:
return -1
return utf_size