字符集转换
字符集转换
g_convert()
系列函数封装了 iconv() 的功能。除了纯字符集转换之外,GLib 还有函数可以处理文件名编码这类复杂情况。
文件名编码
从历史上看,UNIX 没有为文件名定义编码:只要文件名不含有路径分隔符(“/”),它就是有效的。但是,显示文件名时可能需要转换:从创建时使用的字符集转换为应用程序运行所使用的字符集。考虑西班牙语文件名“Presentación.sxi”。如果创建它的应用程序使用 ISO-8859-1 进行编码,
Character: P r e s e n t a c i ó n . s x i
Hex code: 50 72 65 73 65 6e 74 61 63 69 f3 6e 2e 73 78 69
不过,如果应用程序使用 UTF-8,磁盘上的实际文件名将如下所示
Character: P r e s e n t a c i ó n . s x i
Hex code: 50 72 65 73 65 6e 74 61 63 69 c3 b3 6e 2e 73 78 69
Glib 对其字符串使用 UTF-8,而使用 GLib 的 GUI 工具包(例如 GTK)也这样做。如果你从文件系统(例如从 readdir()
或 g_dir_read_name()
)中获取文件名,并且希望向用户显示该文件名,则需要将其转换为 UTF-8。相反的情况是用户键入想要保存的文件的名称:工具包将使用 UTF-8 对该字符串进行编码并提供给你,你需要在使用 open()
或 fopen()
创建文件之前将其转换为文件名所用的字符集。
默认情况下,GLib 假定磁盘上的文件名使用 UTF-8 编码。这对于最近创建的文件系统来说是一个合理的假设:大多数应用程序都对字符串使用 UTF-8 编码,它们创建的文件名也使用该编码。但是,较旧的文件系统中可能仍然包含使用“旧”编码(例如 ISO-8859-1)创建的文件名。在这种情况下,出于兼容性原因,你可能希望指示 GLib 对文件名使用特定的编码,而不是 UTF-8。你可以通过在 G_FILENAME_ENCODING
环境变量中指定文件名编码来做到这一点。例如,如果你的安装对文件名使用 ISO-8859-1,你可以将以下内容放入 ~/.profile
中
export G_FILENAME_ENCODING=ISO-8859-1
GLib 提供了 g_filename_to_utf8()
和 g_filename_from_utf8()
函数来执行必要的转换。这些函数将文件系统中 G_FILENAME_ENCODING
指定的编码中的文件名转换为 UTF-8,反之亦然。此图说明了这些函数是如何用于在 UTF-8 和文件系统中文件名编码之间进行转换的。
文件名编码之间的转换
应用程序编写人员清单
本节是对详细事项的实用总结,以确保你的应用程序正确处理文件名编码。
- 如果你从 `readdir()` 或 `gtk_file_chooser_get_filename()` 等函数中从文件系统获取文件名,则不必进行任何转换即可将该文件名传递给 `open()`、`rename()` 或 `fopen()` 等函数 — 这些是“原始”文件名,文件系统会对其进行理解。
- 如果您需要显示文件名称,请首先使用
g_filename_to_utf8()
将其转换为 UTF-8。如果转换失败,则显示类似“未知文件名称”的字符串。如果您希望将其传递给文件系统,则不要将此字符串转换回用于文件名的编码;而应使用原始文件名称。 - 例如,文字处理器的文档窗口可以在标题栏中显示“未知文件名称”,但仍然允许用户保存文件,因为它会在内部保留原始文件名称。当用户没有设置
G_FILENAME_ENCODING
环境变量而其文件名称未使用 UTF-8 进行编码时,就会发生这种情况。 - 如果您的用户界面允许用户键入文件名称以便进行保存或重命名,请使用
g_filename_from_utf8()
将其转换为文件系统中用于文件名的编码。将转换后的文件名称传递给fopen()
之类的函数。如果转换失败,请要求用户输入不同的文件名称。例如,在将G_FILENAME_ENCODING
设置为 ISO-8859-1 时,用户键入日语字符时会发生这种情况。