蒂姆布雷在iCal上

蒂姆布雷遇到了iCal中令人讨厌的文件损坏错误

I’ve been using iCal for a couple of years now; never really loved it but it’s OKToday for some reason my PowerBook locked up (no big gripe, this hardly ever happens) and when it came back up, iCal showed a little red splodge next to my calendar which when clicked said “iCal was unable to load the calendarThe file might be corrupted or temporarly (SIC)难以理解you can try again later or reset this calendarResetting the calendar will remove all calendar content.”There are not words to express how much this sucks.A programmer working for me who left this kind of hole in a personal-productivity application would be subject to dismissal.

This does suck, and Bray’s basic criticism as to why this shouldn’t be possible is sound但我不认为他说得对。

布雷写道:

Of course, in a sane world iCal would store a calendar named “Tim” in库/日历/蒂姆,但他们已经离开了Library/Application Support/iCal/Sources/<long-hexadecimal-string>. And mine contained eight hundred thousand null bytes.

我不确定这是值得批评的该Application Support/iCalsub-folder in the Library folder seems like as good a place as any to store your calendar dataI certainly wouldn’t want to see more applications claiming top-level-of-the-Library-folder real estate.

标识日历数据的“长十六进制字符串”是aUUID- 通用唯一标识符For example: “A562936C-62C8-468A-8F2A-E565823CB16B”No two UUIDs should ever be the same, not just on your system, but across所有系统。1They’re useful as file names in this case because they never have to change — you can create a calendar called “John’s Cal”, then a few weeks later change the name of that calendar to “Gruber’s Stuff”, and UUID will remain the same.

That means (a) third party software that reads your iCal data (e.g. Objectpark’s nifty MenuCalendarClock) still knows which calendar is which, even if you change the display name of the calendar in iCal, and (b) iCal doesn’t have to worry about file name collisions if you subscribe to two different calendars with the same title.

It is, admittedly, a bit cryptic-looking, and I’m generally a fan of nice, human-readable non-crufty file namesBut these iCal data file folders aren’t meant to be end-user-serviceable files; you’re meant to interact with them solely through iCal, not the Finder.

Bray’s real beef is with the 800,000 null bytes in the calendar’s ICS file(ICS是一种纯文本,主要是人类可读的格式;参见这个关于iCalendar文件的Apple Developer Connection文章.) It’s unclear to me, though, whether the corrupted ICS file consisted of nothing but the 800,000 null bytes, or whether those spurious null bytes were stuck inside a file that still contained his calendar data, too.

[更新:Tim Bray emailed me to clarify — the entire file consisting of nothing but the null bytes即it was a file that consisted of nothing but 800 KB of zeroes.]

接下来,Bray在“Dear Apple”栏目标题下获得了规定性:

以下是如何安全地更新包含有价值数据的文件:

  1. First, you write out the new version without touching the old version, and carefully check that it worked.

  2. Then, you move the old version aside, giving it name like Tim.ics.backup, and carefully check that the move worked.

  3. Then, you move the new version in to the location of the old version and carefully check that this worked.

  4. 然后,您删除备份Even better, don’t; keep a few generations around.

我不想粗鲁But a personal-productivity application that updates crucial high-value information files in place is Broken As Designed, and evidence of an extreme lack of professionalism.

这是合理的建议 - 但是,我非常肯定iCal就地更新其ICS数据文件在 - 的里面Application Support/iCal/Sources/” folder, each calendar is stored as a bundle, which is really just a folder (the names of which folders are the aforementioned cryptic-looking UUIDs) with a “.calendar” extension. Inside each calendar bundle are three files:

  • corestorage.ics
  • 指数
  • 的Info.plist

的Info.plistfile is a simple property list containing the UUID and display name of the calendar我不确定是什么指数is for. Andcorestorage.icsis the ICS-format file where your actual calendar data is storedThis, presumably, is the file that contained all those stray nulls on Bray’s system.

In the HFS+ file system on Mac OS X, each file has two dates associated with it: a modification date, and a creation date(On some other file systems, there’s just one date associated with each file: the modification date.) My corestorage.ics files all have a creation date of today, which seems to hint that iCaldo something along the lines of what Bray proposes when it writes your data to disk: that is, write the data to a new file, then replace the old file with the new oneIn most applications, when you save, the app just writes the data into the existing file.

为了进一步调查,我安装了阿米特辛格的hfsdebug工具— a command-line tool that allows you to inspect low-level HFS attributes.

为HFS +卷上的每个文件分配一个目录节点IDThis ID uniquely identifies that file on the volume, and it’s how aliases continue to work even if you rename or move a file.hfsdebug允许您检查这些目录节点ID[更新:You can also use the ‘-i’ switch for theLScommand to get the inode for any file; on HFS+ volumes this is almost always the same as the Catalog Node ID.]

If, say, I open a text file in BBEdit, make a change, then save, the Catalog Node ID remains the same, because BBEdit writes the updated file contents back to the same fileThis is true for most applications in which you save document files via File → Save.2[更新:I did not mean to imply, in any way, that Mac apps that preserve file IDs when saving are writing data in an unsafe wayApple recommends several techniques for updating files safely while preserving file IDs; e.g碳FSExchangeObjectsAPIIt’s a lot more involved than just opening the file for writing and overwriting the old content.]

However, if I make a change to an iCal calendar, then quit iCal, then re-inspect the corestorage.ics files withhfsdebug, I can see that the Catalog Node IDs change重点是:我很确定iCal才不是write to its data files in-place; it writes to a new file, then replaces the old file with the new one.

然而,布雷的第四点是问题的症结所在There’s no reason iCal couldn’t keep the previous file aroundThat way, if anything happens that corrupts the current file, iCal could offer the user the option of going back to the previous revisionLosing an entire calendar is potentially devastating; losing the changes from your current iCal session would be, in most cases, merely annoying.

Disk space is cheap, calendar files are small, and calendar data is, in many cases, very importantiCal ought to be as conservative as possible with this data, and the most conservative thing it could do is keep at least one backup revision stored for disaster recovery.3

I don’t think the data corruption itself, in this case, is a reason to criticize iCal — given that it happened after Bray’s system “locked up”, it’s quite possible that the corruption was caused by a low-level problem far outside iCal’s control.

The problem is its meager data corruption recovery capabilities. Wise users take this into their own hands, and back up all of their important data on their own, every dayBut most people don’t back up regularly, nor would most Mac users even know where to look for the calendar data files, which means most users in Bray’s situation probably wind up losing their calendar data.

而Bray对此完全正确:它很糟糕。


  1. 你可以用这个来玩的uuidgenMac OS X附带的命令行工具每次打字的uuidgen在shell提示符下,您将获得一个新的UUID(BBEdit有一个#uuid#glossary标记,可以公开相同的系统API。)↩︎

  2. TextMate具有“执行原子保存”首选项设置 - 默认情况下关闭 - 每次保存时都会写入新文件我不知道为什么这是可取的。↩︎

  3. 另一方面,在某些情况下,自动备份的数据存储系统可能会令人不快Like, say, if you really want to delete a certain event from your calendar, you might not be happy to find out that the event data still resides on your system in the backed-up calendar data files that you didn’t even know existed.↩︎