我的Java程序recursion读取目录的内容。 这是一个示例树(注意非ASCII字符):
./sviluppo ./sviluppo/ciaò ./sviluppo/ciaò/subdir ./sviluppo/pippo ./sviluppo/pippo/prova2.txt <-file ./sviluppo/così
该程序以Upstart服务启动,configuration文件名为/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
它不logging名称中包含非ASCII字符的文件名:
root@mdr:/tmp# cat /tmp/log.txt Found dir: /mnt/sviluppo/pippo
相反,当我运行该命令(以root身份来模仿它作为服务启动时会发生什么情况),它可以正常工作,不pipe是否使用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]); } } }
其中forms参数f
是根目录。 该函数将在每个子目录上recursion调用。
编辑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运行时依赖于语言环境的概念,从文件系统存储的字节blob构建Java String
作为文件名。
当你从一个shell执行一个Java程序(作为一个特权用户或一个非特权用户)时,它将携带一个由变量组成的环境 。 读取变量LANG
以将字节流转码为Java字符串,默认情况下在Ubuntu上与UTF-8编码关联。
请注意,一个进程不需要从任何shell运行,但看看代码看起来,Upstart是聪明的,足以理解配置文件中的命令是否打算从shell执行。 所以,假设JVM是通过一个shell来调用的,问题是变量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
包含像ààà
, èèè
等文件名。 现在你可以移动到数据库部分;)