运用差别的文件体系
Node公开了文件体系的很多功用,但并不是一切文件体系都相似,以下是发起的最好实践,以便在运用差别的文件体系时坚持代码简朴和平安。
文件体系行动
在运用文件体系之前,你须要晓得它的行动体式格局,差别的文件体系表现差别,而且具有比其他或多或少的功用:辨别大小写、不辨别大小写、大小写保存、Unicode情势保存、时候戳理会、扩大属性、inode、Unix权限、备用数据流等。
小心从process.platform
揣摸文件体系行动,比方,不要假定由于你的顺序在Darwin上运转,因而你正在处置惩罚不辨别大小写的文件体系(HFS+),由于用户能够正在运用辨别大小写的文件体系(HFSX)。相似地,不要假定由于你的顺序在Linux上运转,因而你正在处置惩罚支撑Unix权限和inode的文件体系,由于你能够位于特定的外部驱动器、USB或收集驱动器上。
操纵体系能够不容易揣摸文件体系行动,但并不会丧失一切内容,你能够探测文件体系以检察它的现实行动,而不是保存每一个已知文件体系和行动的列表(老是不完整),某些易于探测的特性的存在或缺失,每每足以揣摸其他更难探测的特性的行动。
请记着,某些用户能够在事情树中的种种途径上安装了差别的文件体系。
防止运用最低公分母要领
你能够想让你的顺序像最低公分母文件体系一样,经由过程将一切文件名范例化为大写,将一切文件名范例化为NFC Unicode花样,并将一切文件时候戳规范化为1秒分辨率,这是最小公分母的要领。
不要如许做,你只能平安地与文件体系举行交互,该文件体系在各个方面具有完全雷同的最小公分母特性,你将没法以用户希冀的体式格局运用更高等的文件体系,而且你将碰到文件名或时候戳争执,你肯定会经由过程一系列庞杂的相干事宜来丧失和损坏用户数据,而且你将建立纵然不是不能够处理也很难题的bug。
当你今后须要支撑仅具有2秒或24小时时候戳分辨率的文件体系时会发作什么?当Unicode规范愿望到包括轻微差别的范例化算法时(如过去发作的那样)会发作什么?
最小公分母要领倾向于尝试仅运用“可移植”体系调用来建立可移植顺序,这会致使顺序涌现破绽,而且现实上是不可移植的。
采纳超集要领
经由过程采纳超集要领充分利用你支撑的每一个平台,比方,一个可移植备份顺序应当在Windows体系之间准确地同步btimes(文件或文件夹的建立时候),而且不该当烧毁或变动btimes,纵然Linux体系不支撑btimes。雷同的可移植备份顺序应当在Linux体系之间准确同步Unix权限,而且不该当烧毁或变动Unix权限,纵然在Windows体系上不支撑Unix权限。
经由过程使顺序像更高等的文件体系一样处置惩罚差别的文件体系,支撑一切能够功用的超集:大小写敏感、大小写保存、Unicode情势敏感、Unicode情势保存、Unix权限、高分辨率纳秒时候戳、扩大属性等。
在顺序中保存大小写后,假如须要与不辨别大小写的文件体系举行交互,则能够一直完成大小写不敏感。然则,假如你摒弃了顺序中的大小写保存,你就没法平安地与保存大小写的文件体系举行交互,关于Unicode情势保存和时候戳分辨率保存也是云云。
假如文件体系为你供应小写和大写夹杂的文件名,则将文件名保存在给定的确切大小写中,假如文件体系为你供应夹杂Unicode花样或NFC或NFD(或NFKC或NFKD)的文件名,则将文件名保存在给定的确切字节序列中,假如文件体系为你供应毫秒时候戳,则坚持时候戳以毫秒为单元。
当你运用较小的文件体系时,你能够一直适当地举行下采样,运用运转顺序的文件体系的行动所需的比较函数。假如你晓得文件体系不支撑Unix权限,那末你不该当希冀读取你编写的雷同Unix权限。假如你晓得文件体系不保存大小写,那末你应当预备在顺序建立abc
时在目次列表中看到ABC
。然则,假如你晓得文件体系确切保存了大小写,那末在检测文件重命名或文件体系辨别大小写时,你应当将ABC
视为与abc
差别的文件名。
大小写保存
你能够建立一个名为test/abc
的目次,偶然会惊异地发明fs.readdir('test')
返回['ABC']
,这不是Node中的bug,Node返回文件体系存储它的文件名,并不是一切文件体系都支撑大小写保存,某些文件体系将一切文件名转换为大写(或小写)。
Unicode情势保存
大小写保存和Unicode情势保存是相似的观点,要明白为何应当保存Unicode情势,请确保起首明白为何要保存大小写,假如准确明白,Unicode情势保存就一样简朴。
Unicode能够运用几个差别的字节序列对雷同的字符举行编码,几个字符串能够看起来雷同,但具有差别的字节序列。运用UTF-8字符串时,请注重你的希冀与Unicode的事情体式格局一致。正如你不愿望一切UTF-8字符编码为单个字节一样,你不该希冀几个在人眼看起来雷同的UTF-8字符串具有雷同的字节示意,这多是你能够具有ASCII而不是UTF-8的希冀。
你能够建立一个名为test/café
的目次(NFC Unicode情势,字节序列<63 61 66 c3 a9>
而且string.length === 5
)而且偶然你会惊奇地发明fs.readdir('test')
返回['café']
(NFD Unicode情势,字节序列<63 61 66 65 cc 81>
而且string.length === 6
),这不是Node中的bug。Node返回文件体系存储时的文件名,并不是一切文件体系都支撑Unicode情势保存。
比方,HFS+会将一切文件名范例化为险些老是与NFD情势雷同的情势,不要希望HFS+的行动与NTFS或EXT4雷同,反之亦然。不要试图经由过程范例化永久地变动数据作为掩饰文件体系之间Unicode差别的破绽笼统,这会发生题目而不处理任何题目,相反,保存Unicode形似并仅运用范例化作为比较函数。
Unicode情势不敏感
Unicode情势不敏感和Unicode情势保存是两种差别的文件体系行动,常常相互误会。正如在存储和传输文件名时将文件名永久范例化为大写一样,偶然不准确地完成了大小写不敏感,因而,在存储和传输文件名时,经由过程将文件名永久范例化为某种Unicode花样(在HFS+的状况下为NFD),偶然会毛病地完成Unicode花样不敏感性。经由过程运用Unicode范例化举行比较,能够而且更好地完成Unicode情势不敏感而不捐躯Unicode情势保存。
比较差别的Unicode情势
Node供应string.normalize('NFC' / 'NFD')
,你能够运用它将UTF-8字符串范例化为NFC或NFD,你永久不该当存储此函数的输出,而只是将其用作比较函数的一部分,以测试两个UTF-8字符串关于用户是不是看起来雷同。
你能够运用string1.normalize('NFC') === string2.normalize('NFC')
或string1.normalize('NFD') === string2.normalize('NFD')
作为比较函数,你运用哪一种情势并不主要。
范例化很快但你能够愿望运用缓存作为比较函数的输入,以防止屡次范例化雷同的字符串,假如该字符串不在缓存中,则对其举行范例化并对其举行缓存,注重不要存储或保存缓存,只能将其用作缓存。
请注重,运用normalize()
请求你的Node版本包括ICU(不然normalize()
将返回原始字符串),假如你从网站下载最新版本的Node,那末它将包括ICU。
时候戳分辨率
你能够将文件的mtime
(修正时候)设置为1444291759414
(毫秒分辨率),并偶然惊奇地发明fs.stat
将新mtime
返回为1444291759000
(1秒分辨率)或1444291758000
(2秒分辨率),这不是Node中的bug。Node返回文件体系存储它的时候戳,并不是一切文件体系都支撑纳秒、毫秒或1秒时候戳分辨率。有些文件体系以至对atime
时候戳的分辨率异常粗拙,比方,关于一些FAT文件体系,分辨率为24小时。
不要经由过程范例化来损坏文件名和时候戳
文件名和时候戳是用户数据,正如你永久不会自动重写用户文件数据以使数据大写或将CRLF
范例化为LF
行完毕一样,因而你不该当经由过程大小写/Unicode花样/时候戳范例化来变动、滋扰或损坏文件名或时候戳,范例化只应用于比较,绝不能用于转变数据。
范例化现实上是有损哈希码,你能够运用它来测试某些范例的等价性(比方,纵然它们具有差别的字节序列,几个字符串看起来雷同)但你永久不能将它用作现实数据的替代品,你的顺序应按原样通报文件名和时候戳数据。
你的顺序能够在NFC中建立新数据(或许以其喜好的任何Unicode情势组合)或运用小写或大写文件名,或许运用2秒的分辨率时候戳,然则你的顺序不该当经由过程强加大小写/Unicode情势/时候戳范例化来损坏现有的用户数据。相反,采纳超集要领并在顺序中保存大小写、Unicode花样和时候戳分辨率,如许,你就能够平安地与实行雷同操纵的文件体系举行交互。
适当地运用规范化比较功用
确保准确运用大小写/Unicode情势/时候戳比较功用,假如你正在处置惩罚辨别大小写的文件体系,请不要运用不辨别大小写的文件名比较函数。假如你正在运用Unicode情势敏感文件体系(比方NTFS和大多数保存NFC和NFD或夹杂Unicode情势的Linux文件体系),请不要运用Unicode情势不敏感的比较函数。假如你正在运用纳秒时候戳分辨率文件体系,请不要以2秒分辨率比较时候戳。
为比较功用的细小差别做好预备
请注重你的比较函数与文件体系的比较函数婚配(或许假如能够的话探测文件体系以检察它现实比较的体式格局),比方,不辨别大小写比简朴的toLowerCase()
比较庞杂,事实上,toUpperCase()
一般比toLowerCase()
更好(由于它以差别的体式格局处置惩罚某些外语字符)。但更好的要领是探测文件体系,由于每一个文件体系都有本身的大小写比较表。
比方,Apple的HFS+将文件名范例化为NFD花样,但这类NFD花样现实上是当前NFD花样的旧版本,偶然能够与最新的Unicode规范的NFD花样略有差别,不要希望HFS+ NFD一直与Unicode NFD完全雷同。