Download presentation
Presentation is loading. Please wait.
1
GTK+/GLibのファイル名エンコーディング
2
岩本 一樹
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
例えば こんな 感じ
18
すべてUTF-8に?
19
否
20
例えば...
21
GtkFileChooser
22
開くファイルを選択したり入力するGUI
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では別
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
曲(ファイル)の リストを作ります
73
リスト項目を 編集する ダイアログ
75
このダイアログの ファイル名を 入力する部分
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 可逆?
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
変換で元に戻るとは限らない
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へ変換
116
ファイルの履歴
118
検索の履歴
120
これらは 再起動しても 保存される
121
通常はファイルに保存
122
ホームディレクトリの .tmaid とか
123
.tmaidとかは テキスト形式
124
文字符号化方式は?
125
ファイルの履歴 =file name encoding
126
検索の履歴 =UTF-8
127
そのままファイルに書き出す
128
UTF-8で開く
130
file name encodingの文字列が文字化け
131
file name encodingで開く
133
UTF-8の文字列が 文字化け
134
閲覧困難
135
編集困難
136
file name encodingをUTF-8に変換してファイルに書き出す
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はその反対の変換
145
変換に関する問題は生じない
146
閲覧/編集は やや困難
147
1.そのまま 2.UTF-8に変換 3.g_strescape
148
どの方法が正しいとは言えない
149
状況に応じて 選択する必要あり
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コードページにない文字も使える
169
À.txt 가.txt
170
これらのファイルに アクセスできるのは ~WのAPIのみ
171
~AのAPIでは ファイルを 正しく扱えない
172
同様にopenやstatなどに対応する wopenやwstatがある
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
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
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など
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
移植性に問題が...
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
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 は使えない
300
実際のアプリケーションでは?
301
GImageView
302
画像閲覧ソフト
305
まったく変換を行っていない
306
gFTP
307
FTPクライアント
310
変換を忘れている?
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
実は既に近いものがある
340
GtkFileChooser ↑ gtkfilesystem.[ch]
341
gtkfilesystemunix.[ch] や gtkfilesystemwin32.[ch] がある
342
GtkFilePathという 構造体を定義している
343
GtkFilePathを使うAPIもある
344
しかしこれは GtkFileChooser 向け
345
手直ししてGLib側に移したら...
347
UNIX系OSが一般に普及 ↓ ファイル名に非ASCII文字を使う
348
GTK+はマルチプラットホーム
349
file name encoding への対応が不十分 ↓ UNIX系OSでしか 動作しない
350
がっかり
351
日本語が母国語 ↓ 問題を理解しやすい
Similar presentations
© 2024 slidesplayer.net Inc.
All rights reserved.