方便移动端阅读:
Base64编码,你一定知道的,先来看看她在前端的一些常见应用: 当然绝部分场景都是基于Data URLs[1]
canvas的 toDataURL[2]可以把canvas的画布内容转base64编码格式包含图片展示的 data URI[3]。
const ctx = canvasEl.getContext("2d");
// ...... other code
const dataUrl = canvasEl.toDataURL();
// data:image/png;base64,iVBORw0KGgoAAAANSUhE.........
你画我猜,新用户加入,要获取当前的最新的绘画界面,也可以通过Base64格式的消息传递。
FileReader的 readAsDataURL[4]可以把上传的文件转为base64格式的data URI,比较常见的场景是用户头像的剪裁和上传。
function readAsDataURL() {
const fileEl = document.getElementById("inputFile");
return new Promise((resolve, reject) => {
const fd = new FileReader();
fd.readAsDataURL(fileEl.files[0]);
fd.onload = function () {
resolve(fd.result);
// data:image/png;base64,iVBORw0KGgoAAAA.......
}
fd.onerror = reject;
});
}
jwt由header, payload,signature三部分组成,前两个解码后,都是可以明文看见的。拿 国服最强JWT生成Token做登录校验讲解,看完保证你学会![5] 里面的token做测试。
image.png
<link rel="icon" href="data:," />
<link rel="icon" href="data:;base64,=" />
至于怎么获得这个值data:,
的:
<canvas height="0" width="0" id="canvas"></canvas>
<script>
const canvasEl = document.getElementById("canvas");
const ctx = canvasEl.getContext("2d");
dataUrl = canvasEl.toDataURL();
console.log(dataUrl); // data:,
</script>
这个就有很多场景了,比如img标签,背景图等
img标签:
<img src="data:image/png;base64,iVBORw0KGgoAAAA......." />
css背景图:
.bg{
background: url(data:image/png;base64,iVBORw0KGgoAAAA.......)
}
当然这不是好方法,但是至少让你不好解读。
const username = document.getElementById("username").vlaue;
const password = document.getElementById("password").vlaue;
const secureKey = "%%S%$%DS)_sdsdj_66";
const sPass = utf8_to_base64(password + secureKey);
doLogin({
username,
password: sPass
})
借用阮大神的一段代码, 注意mappings字段,这实际上就是bas64编码格式的内容,当然你直接去解,是会失败的。
{
version : 3,
file: "out.js",
sourceRoot : "",
sources: ["foo.js", "bar.js"],
names: ["src", "maps", "are", "fun"],
mappings: "AAgBC,SAAQ,CAAEA"
}
具体的实现请看官方的base64-vlq.js[6]文件。
著名的代码混淆库, javascript-obfuscator[7],其也是有应用base64几码的,一起看看选项: webpack-obfuscator[8]也是基于其封装的。
--string-array-indexes-type '<list>' (comma separated) [hexadecimal-number, hexadecimal-numeric-string]
--string-array-encoding '<list>' (comma separated) [none, base64, rc4]
--string-array-index-shift <boolean>
--string-array-wrappers-count <number>
--string-array-wrappers-chained-calls <boolean>
image.png
X.509公钥证书, github SSH key, mht文件,邮件附件等等,都有Base64的影子。
早期邮件传输协议基于 ASCII 文本,对于诸如图片、视频等二进制文件处理并不好。ASCII 主要用于显示现代英文,到目前为止只定义了 128 个字符,包含控制字符和可显示字符。为了解决上述问题,Base64 编码顺势而生。
Base64是编解码,主要的作用不在于安全性,而在于让内容能在各个网关间无错的传输,这才是Base64编码的核心作用。
除了Base64数据编码,其实还有Base32数据编码, Base16数据编码,可以参见 RFC 4648[9]。
64就是64个字符的意思。
base64对照表, 借用 Base64原理[10]的一张图:
A-Z
26a-z
260-9
10+ /
226 + 26 + 10 + 2
= 64
当然还有一个字符=
,这是填充字符,后面会提到,不属于64里面的范畴。
对照表的索引值,注意一下,后面的base64编码和解码会用到。
说完优缺点,回到正题:
我们今天的重点是 uf8编码转Base64编码:
基本流程
char => 码点 => utf-8编码 => base64编码
在之前要解一下编码的知识, 了解编码知识,又要先了解一些计算机的基础知识。
比特又叫位。在计算机的世界里,信息的表示方式只有 0 和 1, 其可以表示两种状态。
一位二进制可以表示两状态, N位可以表示2^N
种状态。
一个字节(Byte)
有8位(Bit)
所以一个字节可以表示 2^8
= 256种状态;
String.prototype.charCodeAt[11] 可以获取字符的码点,获取范围为0
~ 65535
。这个地方注意一下,关系到后面的utf-8字节数。
"a".charCodeAt(0) // 97
"中".charCodeAt(0) // 20013
0b
开头,可以表示二进制 注意0b10000000
= 128 ,0b11000000
=92,之后会用到.0b11111111 // 255
0b10000000 // 128 后面会用到
0b11000000 // 192 后面会用到
image.png
2 . 0x
开头,可以表示16进制
0x11111111 // 286331153
image.png
0o
开头可以表示8进制,就不多说了,本来不会涉及。
10进制转其他进制 Number.prototype.toString(radix)[12]可以把十进制转为其他进制。
100..toString(2) // 1100100
100..toString(16) // 64, 也等于 ox64
其他进制转为10进制 parseInt(string, radix)[13]可以把其他进制,转为10进制。
parseInt("10000000", 2) // 128
parseInt("10",16) // 16
这里额外提一下一元操作符号+
可以把字符串转为数字,后面也会用到,之前提到的0b
,0o
,0x
这里都会生效。
+"1000" // 1000
+"0b10000000" // 128
+"0o10" // 8
+"0x10" // 16
本文只涉及右移操作,就只讲右移,右移相当于除以2,如果是整数,简单说是去低位,移动几位去掉几位,其实和10进制除以10是一样的。
64 >> 2 = 16
我们一起看一下过程
0 1 0 0 0 0 0 0 64
-------------------
0 1 0 0 0 0 | 0 0 16
&
操作和 一元|
操作一元&
当两者皆为1的时候,值为1。本文的作用可用来去高位, 具体看代码。
3553 & 36
= 0b110111100001 & 0b111111
= 100001
因为高位缺失,不可能都为1,故均为0, 而低位相当于复制一遍而已。
110111 100001
111111
------------
000000 100001
一元|
当任意一个为1,就输出为1. 本文用来填补0
。比如,把3补成8位二进制
3 | 256
= 11 | 100000000
= 100000011
100000011.substring(1)
是不是就等于8位二进制呢00000011
具备了这些基本知识,我们就开始先了解编码相关的知识。
ASCII码第一位始终是0, 那么实际可以表示的状态是 2^7
= 128种状态。
ASCII 主要用于显示现代英文,到目前为止只定义了 128 个字符,包含控制字符和可显示字符。
完整的 ASCII码对应表,可以参见 基本ASCII码和扩展ASCII码[14]
接下来是Unicode和UTF-8编码,请先记住这个重要的知识:
Unicode 为世界上所有字符都分配了一个唯一的编号(码点),这个编号范围从 0x000000 到 0x10FFFF (十六进制),有 100 多万,每个字符都有一个唯一的 Unicode 编号,这个编号一般写成 16 进制,在前面加上 U+。例如:掘
的 Unicode 是U+6398。
Unicode有平面的概念,这里就不拓展了。
Unicode只规定了每个字符的码点,到底用什么样的字节序表示这个码点,就涉及到编码方法。
UTF-8 是互联网使用最多的一种 Unicode 的实现方式。还有 UTF-16(字符用两个字节或四个字节表示)和 UTF-32(字符用四个字节表示)等实现方式。
UTF-8 是它是一种变长的编码方式, 使用的字节个数从 1 到 4 个不等,最新的应该不止4个, 这个1-4不等,是后面编码和解码的关键。
UTF-8的编码规则:
0
,后面 7 位为这个符号的 Unicode 码。此时,对于英语字母UTF-8 编码和 ASCII 码是相同的。n
字节的符号(n > 1
),第一个字节的前 n
位都设为 1
,第 n + 1
位设为0
,后面字节的前两位一律设为 10
。剩下的没有提及的二进制位,全部为这个符号的 Unicode 码,如下表所示:Unicode 码点范围(十六进制) | 十进制范围 | UTF-8 编码方式(二进制) | 字节数 |
---|---|---|---|
0000 0000 ~ 0000 007F | 0 ~ 127 | 0xxxxxxx | 1 |
0000 0080 ~ 0000 07FF | 128 ~ 2047 | 110xxxxx 10xxxxxx | 2 |
0000 0800 ~ 0000 FFFF | 2048 ~ 65535 | 1110xxxx 10xxxxxx 10xxxxxx | 3 |
0001 0000 ~ 0010 FFFF | 65536 ~ 1114111 | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx | 4 |
我们可能没见过字节数为2
或者为4
的字符, 字节数为2
的可以去Unicode对应表[15]这里找,而等于4
的可以去这看看Unicode® 13.0 Versioned Charts Index[16]
下面这些码点都处于0000 0080 ~ 0000 07FF
, utf-8编码需要2个字节
下面这些码点都处于0001 0000 ~ 0010 FFFF
, utf-8编码需要4个字节
可能这里光说不好理解,我们分别以英文字符a
和中文字符掘
来讲解一下:
为了验证结果,可以去 Convert UTF8 to Binary Bits - Online UTF8 Tools[17]
a
"a".charCodeAt(0)
等于 97
1
个字节97..toString(2)
得到编码 1100001
0xxxxxxx
进行填充, 最终结果01100001
掘
"掘".charCodeAt(0)
等于 25496
3
个字节25496..toString(2)
得到编码 110 001110 011000
1110xxxx 10xxxxxx 10xxxxxx
进行填充, 最终结果如下11100110 10001110 10011000
Convert UTF8 to Binary Bits - Online UTF8 Tools[18]执行结果:完全匹配
image.png
基于上面的表格和转换过程,我们抽象一个方法,这个方法在之后的Base64编码和解码至关重要:
先看看功能,覆盖utf8编码1-3字节范围
console.log(to_binary("A")) // 11100001
console.log(to_binary("س")) // 1101100010110011
console.log(to_binary("掘")) // 111001101000111010011000
方法如下
function to_binary(str) {
const string = str.replace(/\r\n/g, "\n");
let result = "";
let code;
for (var n = 0; n < string.length; n++) {
//获取麻点
code = str.charCodeAt(n);
if (code < 0x007F) { // 1个字节
// 0000 0000 ~ 0000 007F 0 ~ 127 1个字节
// (code | 0b100000000).toString(2).slice(1)
result += (code).toString(2).padStart(8, '0');
} else if ((code > 0x0080) && (code < 0x07FF)) {
// 0000 0080 ~ 0000 07FF 128 ~ 2047 2个字节
// 0x0080 的二进制为 10000000 ,8位,所以大于0x0080的,至少有8位
// 格式 110xxxxx 10xxxxxx
// 高位 110xxxxx
result += ((code >> 6) | 0b11000000).toString(2);
// 低位 10xxxxxx
result += ((code & 0b111111) | 0b10000000).toString(2);
} else if (code > 0x0800 && code < 0xFFFF) {
// 0000 0800 ~ 0000 FFFF 2048 ~ 65535 3个字节
// 0x0800的二进制为 1000 00000000,12位,所以大于0x0800的,至少有12位
// 格式 1110xxxx 10xxxxxx 10xxxxxx
// 最高位 1110xxxx
result += ((code >> 12) | 0b11100000).toString(2);
// 第二位 10xxxxxx
result += (((code >> 6) & 0b111111) | 0b10000000).toString(2);
// 第三位 10xxxxxx
result += ((code & 0b111111) | 0b10000000).toString(2);
} else {
// 0001 0000 ~ 0010 FFFF 65536 ~ 1114111 4个字节
// https://www.unicode.org/charts/PDF/Unicode-13.0/U130-2F800.pdf
throw new TypeError("暂不支持码点大于65535的字符")
}
}
return result;
}
方法中有三个地方稍微难理解一点,我们一起来解读一下:
(code >> 6) | 0b11000000
其作用是生成高位二进制。
我们以实际的一个栗子来讲解,以س
为例,其码点为0x633
,在0000 0080 ~ 0000 07FF
之间,占两个字节, 在其二进制编码为11 000110011
, 其填充格式如下, 低位要用6位。110xxxxx 10xxxxxx
为了方便观察,我们把 11 000110011
重新调整一下 11000 110011
。
(code >> 6) 等于 00110011 >> 6,右移6位, 直接干掉低6位。为什么是6呢,因为低位需要6位,右移动6位后,剩下的就是用于高位操作的位了。
11000000
11000 | 110011
--------------
11011000
2 . 二字节 (code & 0b111111) | 0b10000000
作用,用于生成低位二进制。以س
为例,11000 110011
, 填充格式
110xxxxx 10xxxxxx
(code & 0b111111)这步的操作是为了干掉6位以上的高位,仅仅保留低6位
。一元&
符号,两边都是1的时候才会是1,妙啊。
11000 110011
111111
------------------
110011
接着进行 | 0b10000000
, 主要是按照格式10xxxxxx
进行位数填补, 让其满8位。
11000 110011
111111 (code & 0b111111)
------------------
110011
10 000000 (code & 0b111111) | 0b10000000
-------------------
10 110011
4
步的值作为索引,去ASCII码表找对应的值2
步添加字节数个数的 =
比如第2
添加了2个字节,后面是2个=
以大掘A
为例, 我们通过上面的utf8_to_binary
方法得到utf8的编码
11100110 10001110 10011000 11000001
, 其字节数不能被3整除,后面填补
11100110
10001110
10011000
01000001
--------
00000000
00000000
6位一组分为四组, 高位补0
, 用|
分割一下填补的。
00 | 111001 => 57 => 5
00 | 101000 => 40 => o
00 | 111010 => 58 => 6
00 | 011000 => 24 => Y
00 | 110000 => 16 => Q
00 | 010000 => 16 => Q
00 | 000000 => => =
00 | 000000 => => =
结果是:5o6YQQ==
, 完美。
基于上面的to_binary
方法和base64的转换规则,就很简单啦:
先看看执行效果,very good, 和 base64.us[19] 结果完全一致。
console.log(utf8_to_base64("a")); // YQ==
console.log(utf8_to_base64("Ȃ")); // yII=
console.log(utf8_to_base64("中国人")); // 5Lit5Zu95Lq6
console.log(utf8_to_base64("Coding Writing 好文召集令|后端、大前端双赛道投稿,2万元奖池等你挑战!"));
//Q29kaW5nIFdyaXRpbmcg5aW95paH5Y+s6ZuG5Luk772c5ZCO56uv44CB5aSn5YmN56uv5Y+M6LWb6YGT5oqV56i/77yMMuS4h+WFg+WlluaxoOetieS9oOaMkeaImO+8gQ==
完整代码如下:
const BASE64_CHARTS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
function utf8_to_base64(str: string) {
let binaryStr = to_binary(str);
const len = binaryStr.length;
// 需要填补的=的数量
let paddingCharLen = len % 24 !== 0 ? (24 - len % 24) / 8 : 0;
//6个一组
const groups = [];
for (let i = 0; i < binaryStr.length; i += 6) {
let g = binaryStr.slice(i, i + 6);
if (g.length < 6) {
g = g.padEnd(6, "0");
}
groups.push(g);
}
// 求值
let base64Str = groups.reduce((b64str, cur) => {
b64str += BASE64_CHARTS[+`0b${cur}`]
return b64str
}, "");
// 填充=
if (paddingCharLen > 0) {
base64Str += paddingCharLen > 1 ? "==" : "=";
}
return base64Str;
}
至于解码,是其逆过程,留给大家去实现吧。
1 . 当然是基于已有的 btoa
和atob
, 但是 unescape是不被推荐使用的方法
function utf8_to_b64( str ) {
return window.btoa(unescape(encodeURIComponent( str )));
}
function b64_to_utf8( str ) {
return decodeURIComponent(escape(window.atob( str )));
}
// Usage: utf8_to_b64('✓ à la mode'); // "4pyTIMOgIGxhIG1vZGU=" b64_to_utf8('4pyTIMOgIGxhIG1vZGU='); // "✓ à la mode"
2 . MDN的 [rewriting atob()
and btoa()
using TypedArray
s and UTF-8](https://developer.mozilla.org/en-US/docs/Glossary/Base64#solution_2_%E2%80%93_rewriting_atob_and_btoa_using_typedarrays_and_utf-8 "Permalink to Solution #2 – rewriting atob( "rewriting atob()
and btoa()
using TypedArray
s and UTF-8") and btoa() using TypedArrays and UTF-8") 其支持到6字节,但是可读性并不好。
3 . 第三方库 base64-js[20] 与 js-base64[21]都是周下载量过百万的库。
虽然有那么多成熟的,但是我们理解和自己实现,才能更明白Base64的编码原理。
1 . 编码关系图 借用[你真的了解 Unicode 和 UTF-8 吗?[22]]一张图:
image.png
2 . DOMString[23] 是utf-16
编码
Version-Specific Charts[24] Unicode13.0.0[25] Unicode® 13.0 Versioned Charts Index[26] RFC 4648 \| The Base16, Base32, and Base64 Data Encodings[27] Base64 encoding and decoding[28] 字符编码笔记:ASCII,Unicode 和 UTF-8[29] Unicode与JavaScript详解[30] Base64 编码入门教程[31]Base64原理[32] 详解base64原理[33] 一文读懂base64编码[34] JS 中关于 base64 的一些事[35] Base64 的原理、实现及应用[36] 图片与Base64换算关系[37] [你真的了解 Unicode 和 UTF-8 吗?[38]] Unicode中UTF-8与UTF-16编码详解[39] Unicode对应表[40] JavaScript Source Map 详解[41]
[1]Data URLs: https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs
[2]toDataURL: https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLCanvasElement/toDataURL
[3]data URI: https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs
[4]readAsDataURL: https://developer.mozilla.org/zh-CN/docs/Web/API/FileReader/readAsDataURL
[5]国服最强JWT生成Token做登录校验讲解,看完保证你学会!: https://blog.csdn.net/u011277123/article/details/78918390
[6]base64-vlq.js: https://github.com/mozilla/source-map/blob/master/lib/base64-vlq.js
[7]javascript-obfuscator: https://github.com/javascript-obfuscator/javascript-obfuscator#javascript-obfuscator-options
[8]webpack-obfuscator: https://github.com/javascript-obfuscator/webpack-obfuscator
[9]RFC 4648: https://datatracker.ietf.org/doc/html/rfc4648
[10]Base64原理: https://juejin.cn/post/6844903698045370376
[11]String.prototype.charCodeAt: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/charCodeAt
[12]Number.prototype.toString(radix): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toString
[13]parseInt(string, radix): https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/parseInt
[14]基本ASCII码和扩展ASCII码: https://www.asciim.cn/
[15]Unicode对应表: http://titus.uni-frankfurt.de/unicode/unitestx.htm
[16]Unicode® 13.0 Versioned Charts Index: https://www.unicode.org/charts/PDF/Unicode-13.0/
[17]Convert UTF8 to Binary Bits - Online UTF8 Tools: https://onlineutf8tools.com/convert-utf8-to-binary
[18]Convert UTF8 to Binary Bits - Online UTF8 Tools: https://onlineutf8tools.com/convert-utf8-to-binary
[19]base64.us: https://base64.us/
[20]base64-js: https://www.npmjs.com/package/base64-js
[21]js-base64: https://www.npmjs.com/package/js-base64
[22][你真的了解 Unicode 和 UTF-8 吗?: https://www.cnblogs.com/reycg-blog/p/10021658.html
[23]DOMString: https://developer.mozilla.org/zh-CN/docs/Web/API/DOMString
[24]Version-Specific Charts: https://www.unicode.org/charts/About.html
[25]Unicode13.0.0: https://www.unicode.org/versions/Unicode13.0.0
[26]Unicode® 13.0 Versioned Charts Index: https://www.unicode.org/charts/PDF/Unicode-13.0/
[27]RFC 4648 | The Base16, Base32, and Base64 Data Encodings: https://datatracker.ietf.org/doc/html/rfc4648
[28]Base64 encoding and decoding: https://developer.mozilla.org/en-US/docs/Glossary/Base64
[29]字符编码笔记:ASCII,Unicode 和 UTF-8: http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html?20110621174302
[30]Unicode与JavaScript详解: http://www.ruanyifeng.com/blog/2014/12/unicode.html
[31]Base64 编码入门教程: https://juejin.cn/post/6898104998547161096
[32]Base64原理: https://juejin.cn/post/6844903698045370376
[33]详解base64原理: https://juejin.cn/post/6946169611461066789
[34]一文读懂base64编码: https://juejin.cn/post/6844904197519835150
[35]JS 中关于 base64 的一些事: https://juejin.cn/post/6844903838286102536
[36]Base64 的原理、实现及应用: https://juejin.cn/post/6844903663459106829
[37]图片与Base64换算关系: https://juejin.cn/post/6913814643618086925
[38][你真的了解 Unicode 和 UTF-8 吗?: https://www.cnblogs.com/reycg-blog/p/10021658.html
[39]Unicode中UTF-8与UTF-16编码详解: https://juejin.cn/post/6844903590155272199
[40]Unicode对应表: http://titus.uni-frankfurt.de/unicode/unitestx.htm
[41]JavaScript Source Map 详解: https://www.ruanyifeng.com/blog/2013/01/javascript_source_map.html
本文由哈喽比特于3年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/dWR8Pp2suNlYGKnm9Qvs7g
京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。
日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。
据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。
今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。
日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。
近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。
据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。
9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...
9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。
据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。
特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。
据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。
近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。
据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。
9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。
《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。
近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。
社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”
2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。
罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。