11

私はこの問題を抱えており、数日間検索に失敗し、回避策を試みました。

私は現在、osx および Windows コンピューター上で、jnlp/webstart によって配布されている内部 Java スイング プログラムを持っています。これは、とりわけ、WebDav からいくつかのファイルをダウンロードします。

最近、OSX 10.8 と Java 7 を搭載したテスト マシンで、アクセント付き文字を含むファイル名とディレクトリ名がクエスチョン マークに置き換えられ始めました。

Java のバージョンが 7 より前の OSX では問題ありません。

例 :

XXXYYYY_è_ABCD/

になる

XXXYYYY_?_ABCD/

元の文字列でjava.text.Normalizer (NFD、NFC、NFKD、NFKC) を使用すると、結果は異なりますが、それでも間違っています。

XXXYYYY_e?_ABCD/

また

XXXYYYY_e_ABCD/

[oracle.com の andrew.brygin] と [gmail.com の mik3hall] の間のやり取りから、

はい、file.encoding は jvm が実行されているロケールに基づいて設定されます。java vm を xxxx.UTF-8 ロケールで実行する場合、file.encoding は UTF-8 である必要があり、MacRoman に設定すると問題が発生します。したがって、Oracle/OpenJDK7 は正しく動作すると思います。そうは言っても、Andrew Thompson が指摘したように、以前のすべての Apple JDK リリースが英語/UTF-8 ロケールの file.encoding として MacRoman を使用している場合、ここに「互換性」の問題があり、リリース ノートに何かを記載する価値があるかもしれません。 Oracle/OpenJDK MacOS ユーザー a が頭を上げます。

元のメール

Joni Salonenブログ ( java-and-file-names-with-invalid-characters )から、私はそれを知っています:

Java が「デフォルトの文字エンコーディング」を使用してバイナリ データを文字列に変換することはおそらくご存知でしょう。別のエンコーディングを使用してテキストを読み書きするには、InputStreamReader または OutputStreamWriter を使用できます。しかし、API の奥深くでデータからテキストへの変換を行うには、デフォルトのエンコーディングを変更するしかありません。

file.encoding はどうですか?

file.encoding システム プロパティを使用して、Java が I/O に使用するデフォルトの文字エンコーディングを設定することもできます。残念ながら、ファイル名が文字列にデコードされる方法には影響がないようです。

jnlp 内から locale を実行すると、必ず出力されます

LANG=
LC_COLLATE="C"
LC_CTYPE="C"
LC_MESSAGES="C"
LC_MONETARY="C"
LC_NUMERIC="C"
LC_TIME="C"
LC_ALL=

解決策を伴うスタックオーバーフローの最も類似した問題はこれです: encoding-issues-on-Java-7-file-names-in-os-x

しかし、解決策は、Javaプログラムの実行をスクリプトでラップすることです

#!/bin/bash
export LC_CTYPE="UTF-8" # Try other options if this doesn't work
exec java your.program.Here

しかし、ウェブスタートのためにこのオプションを利用できないと思います。また、プログラム内から LC_CTYPE 環境変数を設定する方法が見つかりませんでした。

解決策または回避策はありますか?

PS :

シェルからプログラムを直接実行すると、OSX 10+Java 7 でもファイル/ディレクトリが正しく書き込まれます。この問題は、JNLP+OSX+Java7 の組み合わせでのみ発生します。

4

5 に答える 5

5

私は、事実上すべてのエンコーディングで機能する、ファイル名の最大の ASCII 表現を持つことは許容できると考えています。

まず、特に NFKD を使用して、最大の情報が ASCII 形式で保持されるようにします。たとえば、ascii 以外の文字や制御文字以外の文字が除外されると、 だけ で"2⁵"はなく 、 よりもなどになります。"25""2""fi""fi"""

String str = "XXXYYY_è_ABCD/";
str = Normalizer.normalize(str, Normalizer.Form.NFKD);
str = str.replaceAll( "[^\\x20-\\x7E]", "");
//The file name will be XXXYYY_e_ABCD no matter what system encoding

次に、ファイルシステム名を取得するために、常にこのフィルターを介してファイル名を渡します。失われるのはいくつかの一意性だけです。IE ファイルasdé.txtは と同じでasde.txtあり、このシステムではそれらを区別することはできません。

于 2012-12-10T12:53:23.103 に答える
1

暗い場所で撮影: ファイル エンコーディングは、ファイル名の作成方法には影響しません。コンテンツがファイルに書き込まれる方法だけに影響します。この人物を確認してください: http://jonisalonen.com/2012/java-and-file-無効な文字を含む名前/

これは Apple からの短いエントリです: http://developer.apple.com/library/mac/#qa/qa1173/_index.html

これをhttp://docs.oracle.com/javase/tutorial/i18n/text/normalizerapi.htmlと比較すると、使用したいと思います

normalized_string = Normalizer.normalize(target_chars, Normalizer.Form.NFD);

File コンストラクターに渡す前にファイル名を正規化します。これは役に立ちますか?

于 2012-12-10T09:28:37.863 に答える
1

編集:OS Xをもう少し試した後、答えが完全に間違っていることに気付いたので、やり直しました。

-Dfile.encoding=UTF-8JVMが JVM コマンド ラインでサポートしている場合は、問題が解決する可能性があります。それは標準的なプロパティだと思いますが、それについては確信が持てません。

HFS Plus は、他の POSIX 準拠のファイル システムと同様に、ファイル名をバイト単位で保存します。しかし、Linux の ext3 ファイルシステムとは異なり、ファイル名を有効な分解された UTF-8 にする必要があります。これは、空のディレクトリから始まる、私の OS X システムの Python インタープリターでここで確認できます。

$ python
Python 2.7.1 (r271:86832, Jul 31 2011, 19:30:53) 
>>> import os
>>> os.mkdir('\xc3\xa8')
>>> os.mkdir('e\xcc\x80')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OSError: [Errno 17] File exists: 'e\xcc\x80'
>>> os.mkdir('\x8f')
>>> os.listdir('.')
['%8F', 'e\xcc\x80']
>>> ^D
$ ls
%8F è

これは、HFS Plus ファイルシステムである限り、ファイルシステムのディレクトリ名を Mac-Roman エンコード (つまり、が表示さ8Fれる場所にバイト値で) できないことを証明しています。èしかしもちろん、JVM は HFS Plus ファイルシステムを保証されておらず、SMB と NFS は同じエンコーディング保証を持っていないため、JVM はこのスキームを想定すべきではありません。

したがって、名前をjava.lang.Stringオブジェクトとして正しく読み取るために、ファイル名とディレクトリ名を UTF-8 エンコーディングで解釈するように JVM を説得する必要があります。

于 2012-12-07T21:48:53.120 に答える
0

現時点では、この問題に対する真の解決策はないと思います。

その間、プログラム内から出力される "C" 環境変数は Java Web Start サンドボックスからのものであり、(明らかに設計上) jnlp を使用する環境変数に影響を与えることはできないという結論に達しました。

受け入れられた (会社によって受け入れられた) 回避策/妥協案は、bash スクリプトから javaws を使用して jnlp を起動することでした。

どうやら、ブラウザまたはファインダーから jnlp を起動すると、LANG が設定されていない新しいサンドボックス環境が作成されます (したがって、ASCII に等しい「C」に設定されます)。コマンド ラインから jnlp を起動すると、代わりにシステム デフォルトから適切な LANG が出力され、シェルから継承されます。

これにより、少なくとも jnlp と依存関係の自動更新機能を保持できます。

とにかく、バグ レポートを Oracle に送信しましたが、個人的には、すぐに解決されることを望んでいません。

于 2013-03-26T14:52:49.267 に答える