15

私の Java プログラムは、ディレクトリの内容を再帰的に読み取ります。これはサンプル ツリーです (非 ASCII 文字に注意してください)。

./sviluppo
./sviluppo/ciaò
./sviluppo/ciaò/subdir
./sviluppo/pippo
./sviluppo/pippo/prova2.txt <-file
./sviluppo/così

プログラムは、次のような名前の構成ファイルを使用して、Upstart サービスとして開始されます。/init/myservice.conf

description "Private Service"
author "AD"
start on runlevel [2345]
stop on runlevel [! 2345]
exec java -jar /home/mainFind.jar >> /tmp/log.txt

サービスを起動すると:

root@mdr:/tmp#  service myservice start
myservice start/running, process 15344

名前に非 ASCII 文字を含むファイル名はログに記録されません。

root@mdr:/tmp#  cat /tmp/log.txt
Found dir: /mnt/sviluppo/pippo

代わりに、コマンドを実行すると (サービスとして開始されたときに何が起こるかを模倣するために、ルートとして)、次のコマンドの有無にかかわらず正常に動作しますexec

root@mdr:/tmp# java -jar /home/mainFind.jar  >> /tmp/log.txt
root@mdr:/tmp# exec java -jar /home/mainFind.jar  >> /tmp/log.txt

root@mdr:/tmp#  cat /tmp/log.txt
Found dir: /mnt/sviluppo/ciaò
Found dir: /mnt/sviluppo/ciaò/subdir
Found dir: /mnt/sviluppo/pippo
Found dir: /mnt/sviluppo/così

同じユーザーが実行する同じプログラムが Upstart サービスでは機能しないのに、コマンド ラインから実行するとすべてのファイル名が正しく処理されるのはなぜですか? ここにJavaコードがあります

public static void aggiungiFileDir(File f){
  File[] lista= f.listFiles();
  for(int i=0;i<lista.length;i++){
    if(lista[i].isDirectory()){
      System.out.println("Found dir: "+lista[i]); 
    }
  }
}

仮パラメータfはルート ディレクトリです。この関数は、各サブディレクトリで再帰的に呼び出されます。

編集 2: ポスト ls

root@mdr:/tmp# ls -al /mnt/sviluppo
totale 20
drwx------ 5 root root 4096 nov 15 15:10 .
drwxr-xr-x 7 root root 4096 nov  9 10:43 ..
drwxr-xr-x 2 root root 4096 nov 15 15:10 ciaò
drwxr-xr-x 2 root root 4096 nov 15 11:23 così
drwxr-xr-x 2 root root 4096 nov 15 17:57 pippo
4

2 に答える 2

20

Java は、ネイティブ呼び出しを使用してディレクトリの内容を一覧表示します。基礎となる C ランタイムは、ロケールの概念に依存してString、ファイルシステムによってファイル名として格納されたバイト BLOB からJava を構築します。

シェルから (特権ユーザーまたは非特権ユーザーとして) Java プログラムを実行すると、変数で構成される環境が実行されます。この変数LANGは、バイト ストリームを Java 文字列にトランスコードするために読み取られます。Ubuntu では、デフォルトで UTF-8 エンコーディングに関連付けられています。

プロセスはシェルから実行する必要はありませんが、コードを見ると、構成ファイル内のコマンドがシェルから実行されることを意図している場合、Upstart は十分に理解できるようです。したがって、JVM がシェルを介して呼び出されると仮定すると、問題は変数LANGが設定されていないことです。そのため、C ランタイムはデフォルトの文字セットを想定しますが、これはたまたまUTF-8ではありません。解決策は Upstart スタンザにあります。

description "List UTF-8 encoded filenames"
author "Raffaele Sgarro"
env LANG=en_US.UTF-8
script
  cd /workspace
  java -jar list.jar test > log.txt
end script

en_US.UTF-8はロケールとして使用しましたが、UTF-8 でサポートされているロケールでも同様に機能します。テストのソースlist.jar

public static void main(String[] args) {
    for (File file : new File(args[0]).listFiles()) {
        System.out.println(file.getName());
    }
}

ディレクトリには、などのファイル/workspace/test名が含まれています。これで、データベース部分に移動できます ;)àààèèè

于 2012-11-16T21:57:42.057 に答える
-1

これを /etc/init.d/script に追加すると、この問題が修正されました (/etc/init.d/tomcat7 からコピーしました):

# Make sure script is started with system locale
if [ -r /etc/default/locale ]; then
    . /etc/default/locale
    export LANG
fi

私のマシンの /etc/default/locale の内容:

LANGUAGE=en_US:en
LANG=en_US.UTF-8
于 2018-03-25T08:06:36.433 に答える