RFC 30:Unicode文件名

作者:弗兰克·温特丹

联系方式:warmerdam@pobox.com

状态:通过

总结

本文档描述了在GDAL/OGR中将文件名作为UTF-8字符串处理的步骤。简言之,将假定传入和由GDAL/OGR接口返回的文件名是UTF-8。在某些操作系统上,特别是Windows,这将需要在低级VSI*L API中使用“宽字符”接口。

关键接口

VSI*L接口

VSI*L API中的所有文件名都将被视为UTF-8,这意味着cpl-VSI L-win32.cpp实现将需要大量更新才能使用宽字符接口。

  • VSIFOpenL()

  • VSIFStatL()

  • VSIReadDir()

  • VSIMkdir()

  • VSIRmdir()

  • VSIUnlink()

  • VSIRename()

旧(小文件)VSI API

旧的VSIFOpen()函数将调整为在windows上使用\u wfopen(),而不是fopen(),以便支持utf-8文件名。

  • VSIFOpen()

  • VSIStat()

文件名分析

因为路径/扩展分隔符字符“.”、“,”、“/”和“:”永远不会出现在utf-8字符串的非ascii部分中,所以我们可以安全地让现有的路径解析函数像现在一样工作。他们不需要知道utf-8路径中外来字符的真实字符边界。以下内容将保持不变。

  • CPLGetPath()

  • CPLGetDirname()

  • CPLGetFilename()

  • CPLGetBasename()

  • CPLGetExtension()

  • CPLResetExtension()

其他

  • CPLStat()

  • CPLGetCurrentDir()

  • GDALDataset::GetFileList()

这些都需要将文件名视为utf-8。

Windows

当前,Windows的cpl_vsil_win32.cpp模块使用CreateFile()和ascii文件名。它需要转换为使用CreateFileW()和其他宽字符函数,用于stat()、rename、mkdir等。原型实现已经开发(r20620)。

Linux/Unix/MacOS X系统

在现代linux、unix和MacOS操作系统上,fopen()、stat()、readdir()函数已经支持UTF-8字符串。目前预计在Linux/Unix/MacOS X上不需要任何工作,尽管对此存在一些问题。根据本RFC的定义,对于旧的和不合格的操作系统(WinCE?)是允许的只支持ASCII,不支持UTF-8文件名。

元数据

在许多地方,一般文本可能包含文件名。一个明显的例子是从子数据集域返回的子数据集文件名。以前这些只是作为纯文本公开的,字符集的解释是未定义的。作为本RFC的一部分,我们声明此类文件名应被视为utf-8格式。

Python更改

我用Python2.6观察到像gdal.Open()这样的函数不接受unicode字符串,但它们接受utf-8字符串对象。一种可能的解决方案是在选择的位置更新绑定,以标识传入的unicode字符串,并将其转换为utf-8字符串。

如。

filename =  u'xx\u4E2D\u6587.\u4E2D\u6587'
if type(filename) == type(u'a'):
    filename = filename.encode('utf-8')

我不确定在绑定中最简单的方法是什么。关键条目包括:

  • gdal.Open()

  • ogr.Open()

  • gdal.ReadDir()

  • gdal.PushFinderLocation()

  • gdal.FindFile()

  • gdal.Unlink()

类似地,所有返回文件名的接口(即gdal.ReadDir())以后都将返回unicode对象,而不是字符串对象。

还要注意,在Python3.x中,字符串始终是unicode。

C# 变更

Tamas注意到,在C#中,我们通常使用PtrToStringAnsi封送拆收器将unicode C#字符串转换为C字符串。我们可能需要为所有被认为是文件名的接口字符串使用utf-8转换器。我要注意,这也应该适用于OGR字符串属性值,这些属性值也将被视为utf-8。

(目前尚不清楚谁将负责这方面的工作,因为主要作者(FrankW)不具备具有约束力的能力。

Perl更改

Perl中的一般规则是,所有字符串在交给Perl之前都应该解码,并在输出时进行编码。在实践中,事情通常只是起作用。当然,我(Ari)已经添加了一个从utf8到FindFile和ReadDir(#20800)的显式解码。

Java更改

Java不需要更改。Java字符串是unicode的,它们已经在Java swig绑定中转换为utf-8。也就是说,java绑定已经假设了向GDAL/OGR传递和接收utf-8字符串。

命令行问题

在windows上,传入main()的argv[]通常无法表示在区域设置字符集中无法表示的外来文件名。可以使用GetCommandLineW()和CommandLinetoArgvW()获取命令行并将其解析为宽字符,以捕获ucs-16文件名(很容易转换为utf-8);但是,这会妨碍使用setargv.obj在windows上展开通配符。

我还没有想出一个好的解决方案,所以目前我不打算对GDAL/OGR命令行实用程序进行任何更改,以允许传递外来文件名。因此,这个RFC的主要目的是确保使用GDAL/OGR的其他应用程序可以利用外来文件名。

文件格式

建议的实现实际上只处理使用VSIFOpenL()、VSIFOpen()和相关函数的文件格式驱动程序。一些依赖于外部库(如netcdf)的驱动程序无法挂接文件IO API,并且可能不支持utf-8文件名。能分辨出这些也许是件好事。

至少任何标记为GDAL_DCAP_VIRTUALIO“是”的驱动程序都支持UTF-8。也许应该利用这个机会更统一地应用这个驱动程序元数据(done)。

测试套件

我们需要引入一些具有多字节utf-8文件名的测试套件测试。为了支持VSI*L API的这些方面,特别是rename、mkdir、rmdir、functions和VSIFOpenL本身已经在python中公开。

文档

适当的API入口点将被记录为获取并返回UTF-8字符串。

实施

执行工作正在进行中,并在罚单3766中进行跟踪。