|
|
--[[
起因是我的手机/storage/emulated/0/下突然出现了个文件"@?@"
这个文件非常奇怪,只能知道有这个文件,无法对其进行任何操作
读取 重命名 修改日期 删除 复制 移动 均报错File not found: /storage/emulated/0/@?@: open failed: ENOENT (No such file or directory)
并且这个文件的修改日期是1970-01-01 08:00:00,是时间戳0的日期,仿佛这个文件就是不存在的,但是能读取到存在
很有趣是吧 我看了他的名字的unicode "\u001\u0010\u001a\u0040\ue00c\udc38\u00b\u0040"
他名字很有趣,它的倒数第三个字符"\udc38"
是 Unicode 编码范围 DC00 到 DFFF 中的一个编码点。这个范围被称为 “低代理区”。
Unicode 规定,高代理区 的码点和 低代理区 的码点必须成对出现,才能共同表示一个“增补平面”的字符(如许多不常用的汉字、emoji、古文字等)。
一个单独的 \udc38 是无效的、未定义的。它就像是半截密码,本身不表示任何字符。
所以呢我发现创建一个名字包含这个字符的文件"MT管理器"无法将起删除,复制,剪切 但可以重命名,写入文本,修改时间
引用ai说的:
------------
当它出现在字符串中时,会发生什么?
在程序的内存中:它就是一个占两个字节的数据 0xDC 0x38 。
当程序试图将它转换为字节流(如UTF-8)以便与系统交互时,问题就爆发了。
UTF-8编码器遇到这个孤立的低代理项时会“懵掉”。根据标准,它可以有几种处理方式:
抛出错误/异常:程序直接崩溃或返回错误。
替换为“�”:用U+FFFD(替换字符)代替它。
原样输出:但会输出一个非法的UTF-8字节序列。
大多数稳健的系统或库在遇到无效字符时,最终会把它编码成一个合法的、但表示“无效”的UTF-8字节序列。这个序列在之后解码时,可能会被解释为一个或多个“�”。
这与文件管理器的删除失败有何关联?:
关键故障点就在“解码”和“再编码”这两个环节:
显示环节:文件管理器从文件系统读到原始字节(包含 \xDC\x38 ),尝试用UTF-8解码成字符串以便在屏幕上显示。解码器遇到无效序列,可能将其显示为“�” 或一个空白框。这时,屏幕上显示的名字,已经不是内存中存储的名字的精确映射了。
传递环节(致命环节):当你选中这个文件并点击“删除”,App需要将文件名重新编码成字节流,传递给底层的 unlink 系统调用。
如果App在内部用一个特殊的占位符(如 � )代表了那个无效序列,那么重新编码后传递出去的字节就变成了 � 对应的合法UTF-8字节( 0xEF 0xBF 0xBD )。
系统内核拿着这个新的、合法的字节序列去找文件,发现和磁盘上记录的原始字节序列( 0xDC 0x38 以及其他部分)完全不匹配,所以会返回“文件不存在”的错误。这就是删除失败的根本原因。
-----------------
有趣 我手机自带的文件管理器也无法将它删除 但别怕np管理器(可能是删除逻辑与Mt不同)和重命名后它可以将其删除 如果想用Termux里的rm删除它的话直接输这个字符Termux会闪退,但可以用Tab补全rm -f后的名称就可以删掉了
如果想复制这个字符 粘贴是时候不要用输入法的剪切板粘贴,因为大部分输入法都会处理这样的字符 可以用长按粘贴,这样子就能粘贴这个字符
虽然到这了,但是我手机/storage/emulated/0/@??@ 这个文件不是因为这个,我还是无法删除它
--[[这是创建的lua代码
在 /storage/emulated/0/测试/ 下创建一个包含?的文件
]]
-- Unicode字符串(\uXXXX)转普通字符
function unicode2char(unicodeStr)
local res = unicodeStr:gsub("\\u(%x%x%x%x)", function(x)
return utf8.char(tonumber(x, 16))
end)
return res
end
local str = unicode2char("\\udf91")
--print(str) |
|