Presentation is loading. Please wait.

Presentation is loading. Please wait.

GTK+/GLibのファイル名エンコーディング

Similar presentations


Presentation on theme: "GTK+/GLibのファイル名エンコーディング"— Presentation transcript:

1 GTK+/GLibのファイル名エンコーディング

2 岩本 一樹

3

4 GTK+

5 GUI ツールキット

6 GLib

7 GTK+の下で働くライブラリ

8 2.8.17が最新版

9 1.0系と 2.0系に 分かれる

10 1.0→2.0

11 このとき、いくつかの特長がアピールされた

12 Pangoによる 多言語 テキスト出力

13 新テーマエンジン

14 ATKによる アクセシビリティ サポートの向上

15 UTF-8

16 例えば こんな 感じ

17

18 すべてUTF-8に?

19

20 例えば...

21 GtkFileChooser

22 開くファイルを選択したり入力するGUI

23

24 gtk_file_chooser_get_filename
ファイル名を取得するAPI gtk_file_chooser_get_filename

25 gtk_file_chooser_set_filename
ファイル名を設定するAPI gtk_file_chooser_set_filename

26 これらのAPIの文字列 ≠UTF-8

27 GTK+/GLib以外のAPI 例えば...

28 fopen open stat readdir

29 ↓ gtk_file_chooser_get_filename gtk_file_chooser_set_filename
これらのAPIで使える文字列

30 この文字列の 文字符号化方式を file name encoding と呼ぶ

31 file name encoding の実体は?

32 GLib-2.4以降 環境変数 G_FILENAME_ENCODING

33 G_FILENAME_ENCODING=ISO-8859-1

34 GLib-2.6以降ならば 複数指定可能

35 G_FILENAME_ENCODING=EUC-JP,CP932

36 GLib-2.4で 複数指定すると 先頭のみ有効

37 @localeという 特殊な設定も

38 G_FILENAME_ENCODING=@locale,CP932

39 ロケールの文字符号化方式

40 その実体は?

41 優先順位が高い順に...

42 nl_langinfoの返値 setlocaleの返値 環境変数LC_ALL 環境変数LC_CTYPE 環境変数LANG

43 いずれか1つ

44 環境変数G_FILENAME_ENCODINGが未定義
or GLib-2.2以前

45 環境変数 G_BROKEN_FILENAMES

46 g_get_charsetの返値

47 即ち、ロケールの文字符号化方式

48 環境変数G_FILENAME_ENCODING未定義 環境変数G_BROKEN_FILENAMES未定義

49 UTF-8

50 ただし

51 Microsoft Windowsでは別

52

53 file name encodingの変換

54 file name ncoding からUTF-8に変換する g_filename_to_utf8

55 file name ncoding をUTF-8に変換する g_filename_from_utf8

56 2.6以降 g_filename_display_name g_filename_display_basename

57 g_filename_to_utf8 g_filename_display_name の違い

58 g_get_filename_charsets
2.6以降 g_get_filename_charsets

59 g_get_filename_charsets
環境変数 G_FILENAME_ENCODING

60 G_FILENAME_ENCODINGで複数指定
環境変数 G_FILENAME_ENCODINGで複数指定 複数の文字符号化方式を返す

61 g_filename_to_utf8 最初だけ

62 g_filename_display_name
順番に試みる

63 順番に試みる =変換に失敗したら次の文字符号化方式を試す

64 g_filename_display_name
の方が変換できる可能性が高い

65 g_filename_display_name
では元の文字符号化方式が不明

66 file name encoding UTF-8 一方通行

67 g_filename_display_name
表示のための変換

68 とg_filename_from_utf8
では g_filename_to_utf8 とg_filename_from_utf8 の使い所は?

69 独自にファイル名を入力する場合

70 HDDオーディオプレイヤーのデータ管理ソフトの場合

71 曲(ファイル)の リストを作ります

72

73 リスト項目を 編集する ダイアログ

74

75 このダイアログの ファイル名を 入力する部分

76

77 1.file name encodingをUTF-8にする

78 2.エントリーウィジェットで編集

79 3.UTF-8をfile name encodingにする

80 g_filename_to_utf8 ↑↓ g_filename_from_utf8 可逆?

81

82 変換の実装はlibiconv

83 例えば CP932→UTF-8→CP932

84

85 CP932 ED 61

86 UTF-8 E

87 CP932 FA 7D

88 ED 61 FA 7D

89 CP932は 歴史的経緯により 同じ文字が重複して登録されている

90 NECのPC-9801とIBMのDOS/Vの それぞれの文字を統合した

91 変換で元に戻るとは限らない

92

93 UTF-8と file name encoding が混在

94 混在=面倒

95 gtk_file_chooser_get_filename
g_dir_read_name 取得

96 取得 即UTF-8に変換

97 &file name encoding破棄

98 fopen open stat readdir を呼び出す時

99 必要に応じて その場でUTF-8からfile name encodingへ変換

100 不要になったら file name encoding は即破棄

101 文字列は すべて UTF-8 で統一

102 統一=楽

103 しかし

104 UTF-8に変換できない可能性

105 環境変数G_FILENAME_ENCODING
G_BROKEN_FILENAME が正しくない

106 libiconvが file name encodingと UTF-8 の変換に未対応

107 対応する 文字が ない

108 変換できない 不正なファイル名 ?

109

110 UTF-8に変換できなくてもファイル名として使える

111 ゆえに file name encoding のまま保持

112 表示する時

113 必要に応じて その場で file name encoding からUTF-8へ変換

114

115

116 ファイルの履歴

117

118 検索の履歴

119

120 これらは 再起動しても 保存される

121 通常はファイルに保存

122 ホームディレクトリの .tmaid とか

123 .tmaidとかは テキスト形式

124 文字符号化方式は?

125 ファイルの履歴 =file name encoding

126 検索の履歴 =UTF-8

127 そのままファイルに書き出す

128 UTF-8で開く

129

130 file name encodingの文字列が文字化け

131 file name encodingで開く

132

133 UTF-8の文字列が 文字化け

134 閲覧困難

135 編集困難

136 file name encodingをUTF-8に変換してファイルに書き出す

137

138 人にやさしい

139 しかし前述の変換に関する問題が...

140 g_strescapeとg_strcompressを使う

141 g_strescapeは 7FhからFFhを 8進数表記に変換

142 08h \b 09h \t 0Ah \n 0Ch \f 0Dh \r 22h \" 5Ch \\ も変換

143 g_strcompressはその反対の変換

144

145 変換に関する問題は生じない

146 閲覧/編集は やや困難

147 1.そのまま 2.UTF-8に変換 3.g_strescape

148 どの方法が正しいとは言えない

149 状況に応じて 選択する必要あり

150

151 Microsoft Windows

152 文字列を扱うAPI

153 ANSIコードページとUNICODEの2種類

154 ソースコードレベルでは CreateFile

155 実際には CreateFileA または CreateFileW

156 ヘッダで決まる

157 #ifdef UNICODE #define CreateFile CreateFileW #else #define CreateFile CreateFileA #endif

158 マクロUNICODEが定義されていれば CreateFileはCreateFileW

159 マクロUNICODEが定義されなければ CreateFileはCreateFileA

160 ANSIコードページは8ビット単位

161 1文字は1バイト または2バイト

162 実際には CP932など 言語環境によって 異なる

163 UNICODEは 16ビット単位

164 1文字は2バイト

165 言語環境による 違いはない

166 NT系ではUNICODEが ネイティブ

167 ファイル名に ANSIコードページにない文字も使える

168

169 À.txt 가.txt

170 これらのファイルに アクセスできるのは ~WのAPIのみ

171 ~AのAPIでは ファイルを 正しく扱えない

172 同様にopenやstatなどに対応する wopenやwstatがある

173

174 環境変数G_FILENAME_ENCODING 環境変数G_BROKEN_FILENAMES

175 Microsoft Windowsでは両方とも未対応

176 GLib-2.4以前では

177 file name encodingはANSIコードページに固定

178 ANSIコードページはopenやstat、readdir
などのAPIで使える

179 file name encodingはopenやstat、readdir
などのAPIで使える

180 この実装は UNIX系OSでの 実装と矛盾しない

181 Microsoft WindowsではGLib-2.4まで

182 2.6以降は煩雑

183 ANSIコードページだとファイルを正しく扱うことができない

184 UNICODE であるべき

185 しかし Microsoft Windowsの 16ビット単位のUNICODE形式は GTK+/GLibにそぐわない

186 だから file name encodingはUTF-8になった

187 GtkFileChooserやg_dir_read_name

188 可能ならば UNICODEの APIを呼ぶ

189 可能ならば =NT系OSならば

190 UNICODEからUTF-8に変換

191 不可能ならば ANSIコードページ のAPIを呼ぶ

192 不可能ならば =95/98/ME

193 ANSIコードページからUTF-8に変換

194 UTF-8は openやstat、readdir などのAPIで使ない

195 file name encodingはopenやstat、readdir
などのAPIで使ない

196 GLib-2.6では 新しいAPIを追加

197 g_openやg_statなど

198 機能はopenやstatなどと同じ

199 UNIX系OSでは 単に名前が 変わっただけ

200 UNIX系OS では引数のファイル名は file name encoding

201 Microsoft Windows では引数のファイル名は UTF-8

202 Microsoft Windows では引数のファイル名は file name encoding

203 即ち、g_openやg_statなどは常に
file name encoding

204 ソースコードに 一貫性あり

205 UNIX系OSとMicrosoft Windowsで共通のソースコード

206 2.4以下との 互換性がなくなる

207 必要に応じて 2.4以下のために g_openやg_stat などをマクロ定義

208 #if ! GLIB_CHECK_VERSION(2,6,0)
#define g_open open #endif

209 g_~を使わない =正しく動作しない

210 Microsoft Windowsでは g_~はw~を使う

211 例えばg_openは UTF-8をUNICODEに 変換してwopenを 呼び出す

212 ファイル名の 劣化なし

213 À.txtや 가.txtも OK

214

215 GLib-2.6にあるg_~なAPI

216 g_open、g_rename、 g_mkdir、g_stat、g_lstat、 g_unlink、g_remove、 g_rmdir、g_fopen、 g_freopen

217 GLib-2.8で追加された g_~なAPI

218 g_chmod、g_access、g_creat、g_chdir

219 ここにないAPIを 使う時には?

220 2.6で chmod、access、 creat、chdirを 使うには?

221 file name encoding をANSIコードページ に変換

222 UTF-8 をANSIコードページ に変換

223 Microsoft Windowsでは ロケールの文字符号化方式がANSIコードページ

224 g_locale_from_utf8

225 file name encoding≠UTF-8
通常 file name encoding≠UTF-8

226 ロケールの文字符号化方式=ANSIコードページ
はmicrosoft Windowsのみ

227 file name encodingを g_locale_to_utf8で 変換してファイル名として使う

228 Microsoft Windowsの 特別な処理

229 GLib-2.8以降

230 g_win32_locale_filename_from_utf8
新設

231 UTF-8 ロケールの文字符号化方式 専用API

232 file name encoding ANSIコードページ 専用API

233 g_locale_from_utf8 変換を試みるだけ

234 変換は 失敗するかも

235 例えばCP932で À.txtや가.txtは 変換できない

236 g_win32_locale_filename_from_utf8 は失敗したらGetShortPathNameW

237

238

239 가.txt 74E2~1.TXT

240 74E2~1.TXT ならばANSIコードページに変換可

241 À.txt 短いファイル名に 変換できていない

242 変換に成功する 可能性は高まる

243 でも失敗する 可能性もある

244 Microsoft Windowsならば g_locale_from_utf8や g_win32_locale_filename_from_utf8 で変換するよりも g_utf8_to_utf16

245 UNICODEに変換してUNICODEのAPIを呼ぶべき

246 CreateFileWとか wopenなど

247

248 パスの区切り

249 UNIX系OS / スラッシュ (2Fh)

250 Microsoft Windows \ バックスラッシュ (5Ch)

251 マクロ G_DIR_SEPARATOR G_DIR_SEPARATOR_S

252 G_DIR_SEPARATOR は文字

253 G_DIR_SEPARATOR_S は文字列

254 #define G_DIR_SEPARATOR '/'
#define G_DIR_SEPARATOR_S ”/”

255 GLib-2.6以降 マクロ G_IS_DIR_SEPARATOR (c)

256 文字がパスの 区切りならば真

257 Microsoft Windowsでは特別な実装

258 「/」と「\」 の両方で真

259 GLibのパスを扱うAPI

260 g_path_get_basename g_path_get_dirname

261 /home/iwm/test.txt g_path_get_basename test.txt

262 /home/iwm/test.txt g_path_get_dirname /home/iwm

263 Microsoft Windows GLib-2.2.3以降 g_path_get_basename g_path_get_dirname 「/」と「\」の両方を区切り

264 マクロ G_IS_DIR_SEPARATOR (c) の導入よりも前

265 複数のパスを区切る

266 UNIX系OS : コロン (3Ah)

267 Microsoft Windows ; セミコロン (3Bh)

268 G_SEARCHPATH_SEPARATOR G_SEARCHPATH_SEPARATOR_S
マクロ G_SEARCHPATH_SEPARATOR G_SEARCHPATH_SEPARATOR_S

269 G_SEARCHPATH_SEPARATOR
は文字

270 G_SEARCHPATH_SEPARATOR_S
は文字列

271 #define G_SEARCHPATH_SEPARATOR ':'
#define G_SEARCHPATH_SEPARATOR_S ”:”

272 マクロを使わない ハードコード

273 移植性に問題が...

274

275 5Ch問題

276 5Ch=パスの区切り

277 5Ch=2バイト目

278 単純に5Chを検索

279 strchr、strcspn、 strpbrk、strrchr、 strspn、strstr、 strtok

280 2バイトの文字が 分断される可能性

281

282 CP932 95h 5Ch

283 C:\doc\表1.txt

284

285 「表」という文字の 途中で分断

286 C:\doc\表1.txt ファイル名 1.txt

287 C:\doc\表1.txt ディレクトリ C:\doc\?

288 先頭から見て 2バイト文字の 先頭かどうか 判別しながら探す

289 GLibの実装は?

290 GLib-2.6以降 file name encoding UTF-8

291 UTF-8は 2バイト目以降に5Chはない

292 UTF-8 安全

293 GLib-2.6以降 安全

294 GLib-2.6以降 file name encoding ANSIコードページ

295 ANSIコードページは 2バイト目以降に5Chがあるかも

296 GLib-2.0.0~GLib-2.4.8 すべての実装で 単純に5Chで分割

297 GLib-2.4以前 危険

298 Microsoft Windowsでは GLib-2.4以前の g_path_get_basename g_path_get_dirname は使えない

299

300 実際のアプリケーションでは?

301 GImageView

302 画像閲覧ソフト

303

304

305 まったく変換を行っていない

306 gFTP

307 FTPクライアント

308

309

310 変換を忘れている?

311

312 結局 file name encoding とは...

313 file name encoding はネイティブなAPIの ファイル名としては 使えない

314 file name encoding はGTK+のウィジェットで表示できない

315 file name encoding は文字列としての体裁を整えてはいるが単なるデータでしかない

316 中途半端に 文字列だから 混乱を生じる

317 誤った使い方をしてもコンパイル時に警告は出ない

318 ASCIIな環境だと 問題が発覚しにくい

319 プログラマ側が きっちり管理する 必要がある

320 プログラマの負担が大きい

321 変換し忘れることも...

322 隠せ

323 例えば、構造体 GFileName

324 メンバはgchar型の配列かもしれない

325 struct _GFileName { gchar *file; }; typedef struct _GFileName GFileName;

326 Microsoft Windowsならばメンバはgunichar2型の配列かもしれない

327 struct _GFileName { gunichar2 *file; }; typedef struct _GFileName GFileName;

328 メンバは16ビットの数値かもしれない

329 struct _GFileName { guint16 id; }; typedef struct _GFileName GFileName;

330 gtk_file_chooser_get_filename
GFileName

331 gtk_file_chooser_set_filename
GFileName

332 g_open、g_fopen、g_dir_open...
GFileName

333 GFileName *g_filename_get_basename (GFileName *fn)
GFileName *g_filename_get_dirname (GFileName *fn) gchar *g_filename_get_display_name (GFileName *fn) GFileName *g_filename_copy (GFileName *fn) void g_filename_free (GFileName *fn) gboolean g_filename_compare (GFileName *fn1, GFileName *fn2) gchar *g_filename_get_native_name (GFileName *fn) gboolean g_filename_set_native_name (GFileName *fn, const gchar *file) gunichar2 *g_filename_get_win32_name (GFileName *fn) gboolean g_filename_set_win32_name (GFileName *fn, const gunichar2 *file)

334 GFileName構造体を ネイティブなAPIに使う エラー

335 GFileName構造体を GTK+のウィジェットで 表示 エラー

336 コンパイル時に ミスが発覚する

337 プログラマの 負担が軽くなる

338 実は既に近いものがある

339

340 GtkFileChooser gtkfilesystem.[ch]

341 gtkfilesystemunix.[ch] や gtkfilesystemwin32.[ch] がある

342 GtkFilePathという 構造体を定義している

343 GtkFilePathを使うAPIもある

344 しかしこれは GtkFileChooser 向け

345 手直ししてGLib側に移したら...

346

347 UNIX系OSが一般に普及 ファイル名に非ASCII文字を使う

348 GTK+はマルチプラットホーム

349 file name encoding への対応が不十分 UNIX系OSでしか 動作しない

350 がっかり

351 日本語が母国語 問題を理解しやすい

352


Download ppt "GTK+/GLibのファイル名エンコーディング"

Similar presentations


Ads by Google