[英]java read write unicode / UTF-8 filenames (not contents)
[英]Can't read UTF-8 filenames when launched as an Upstart service
我的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
相反,当我运行命令时(以root身份,模仿它作为服务启动时会发生什么)它运行正常,有和没有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
Java使用本机调用来列出目录的内容。 底层C运行时依赖于语言环境概念,从文件系统存储的字节blob中构建Java String
作为文件名。
当您从shell(作为特权用户或非特权用户)执行Java程序时,它会携带由变量组成的环境 。 读取变量LANG
以将字节流转码为Java字符串,并且默认情况下在Ubuntu上它与UTF-8编码相关联。
请注意,不需要从任何shell运行进程,但查看代码似乎Upstart足够聪明,可以了解配置文件中的命令何时从shell执行。 因此,假设通过shell调用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
包含ààà
, èèè
等文件名。 现在您可以移动到数据库部分;)
将此添加到/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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.