我的Java程序递归地读取目录的内容。这是一个示例树(请注意非ASCII字符):
./sviluppo ./sviluppo/ciaò ./sviluppo/ciaò/subdir ./sviluppo/pippo ./sviluppo/pippo/prova2.txt <-file ./sviluppo/così
该程序作为Upstart服务启动,带有名为like的配置文件 /init/myservice.conf
/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
相反,当我运行命令(以root身份模仿服务启动时发生的情况)时,无论有没有,它都可以正常运行exec:
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是根目录。该函数将在每个子目录上递归调用。
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
Java使用本地调用来列出目录的内容。基础的C运行时依赖于 语言环境 概念,String从文件系统作为文件名存储的字节blob中构建Java 。
String
从外壳程序(特权用户或非特权用户)执行Java程序时,它会承载由变量组成的 环境 。LANG读取该变量可将字节流转码为Java String,默认情况下,在Ubuntu上它将与UTF-8编码关联。
LANG
请注意,不需要从任何外壳运行进程,但是通过查看代码,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
en_US.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包含文件名,如ààà,èèè等等。现在您可以移至数据库部分;)
/workspace/test
ààà
èèè