编码问题; .jar不能使用UTF-8文件中的西里尔字符

时间:2017-12-13 22:06:53

标签: java encoding

所以我在我的代码中将此正则表达式作为字符串文字:

private static final String FILE_PATTERN = "((\\s*\".*НЕКОТОРЫЕ СИМВОЛЫ .*\"\\R)([^\"].* (?!-)\\d+\\s*)+)+";

此外,我还输入了UTF-8编码的测试文件。

问题是,当我在IDE中测试我的程序时(在我的情况下是IntelliJ IDEA),一切正常。特别是,正则表达式与测试文件中的西里尔字符一起使用。

但是,当我构建我的程序(Maven)并使用相同的测试文件测试.jar文件时,结果发现很可能正则表达式不能与西里尔字符一起使用。

然后我再次使用Windows 1251编码的文件对其进行了测试,并且运行良好。

所以我的问题是 - 如何让我的.jar使用UTF-8文件,就像在IDE中一样?

提前致谢。

[UPDATE1]

two test files, one in UTF-8 and another in Windows 1251

我试图用\ u代码替换西里尔字符,如下所示:

private static final String FILE_PATTERN = "((\\s*\".*\\u041E\\u0442\\u0434\\u0435\\u043B .*\"\\R)([^\"].* (?!-)\\d+\\s*)+)+";

这不起作用:(

[UPDATE2]

文件处理开始如下:

static void processFile(String inputFile) {
    try {
        String fileStr = FileHandler.readFile(inputFile).toString();
        if (!FileParser.validateFile(fileStr)) {
            System.out.println("Sorry, input file format is invalid");
            ...

文件验证如下所示:

public class FileParser {
private static final String FILE_PATTERN = "((\\s*\".*Отдел .*\"\\R)([^\"].* (?!-)\\d+\\s*)+)+";

public static boolean validateFile(String fileStr) {
    return Pattern.compile(FILE_PATTERN).matcher(fileStr).matches();
}
...

我认为文件阅读很常见:

public class FileHandler {
public static StringBuilder readFile(String fileName) {
    StringBuilder res = new StringBuilder();
    String temp;
    try (BufferedReader r = new BufferedReader(new FileReader((fileName)))) {
        while ((temp = r.readLine()) != null) {
            res.append(temp).append("\n");
        }
    } catch (FileNotFoundException e) { 
        System.out.println("Input file not found!");
    } catch (IOException e) {
        // log exception
    }
    return res;
}
...

1 个答案:

答案 0 :(得分:1)

我会在这个问题上抛出一些可能性。

类FileReader和FileWriter使用默认的平台编码,而不会过载指定的编码。我不确定这是否是有意的,而是其中一种选择:

public static StringBuilder readFile(String fileName) {
    StringBuilder res = new StringBuilder();
    String temp;
    Charset charset = StandardCharsets.UTF_8;
    //Charset charset = Charset.fromName("Windows-1251");
    try (BufferedReader r = Files.newBufferedReader(fileName, charset)) {
        while ((temp = r.readLine()) != null) {
            res.append(temp).append("\n");
        }
    } catch (FileNotFoundException e) { 
        System.out.println("Input file not found!");
    } catch (IOException e) {
        // log exception
    }
    return res;
}

或者:

String readFile(String fileName) throws IOException {
    byte[] content = Files.readAllBytes(Paths.get(fileName));
    return new String(content, StandardCharsets.UTF_8);
}

然后,java源代码的编辑器编码必须与 javac编译器的编码编码相同。可以通过使用此类特殊字符的\uXXXX ASCII表示来检查这一点:如果它突然起作用,......

您使用了两个反斜杠,但\u0063(字母c)使用java源代码级别,实际上代替public class,您可以编写publi\u0063 \u0063lass

private static final String FILE_PATTERN =
    "((\\s*\".*\u041E\u0442\u0434\u0435\u043B .*\"\\R)([^\"].* (?!-)\\d+\\s*)+)+";

然后有一个正则表达式,它有两个Unicode标志,(?u)(?U)更多的字母构成。这应该不是问题。