java jar 以两种不同的字符编码写入

java jar writes in two different character-encoding

所以当从 Eclipse 运行 时我的代码工作正常,但是执行项目的可运行 jar 却不行。

这是我的代码:

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;


public class cc {

    public static HttpURLConnection con;
    public static String url = "http://bac.onec.dz/index.php";
    public static int begin;
    public static int max;
    public static boolean paused=false;
    public static String path="result.csv";

    public static void setData(int b,int m){
        begin=b;max=m;
    }
    public static void main(String[] args)  throws Exception {
            int i =1;
            setData(35043487,2);
            while (i<=max && !paused) {
            sendPost(begin++);
            i++;
        }
    }

    private static void sendPost(int mat) throws Exception {
        String urlParameters ;
        URL obj = new URL(url);
        BufferedReader in;
        StringBuffer response;

        con = (HttpURLConnection) obj.openConnection();
        con.setRequestMethod("POST");
        con.setRequestProperty("Host", "bac.onec.dz");
        con.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:47.0) Gecko/20100101 Firefox/47.0");
        con.setRequestProperty("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
        con.setRequestProperty("Accept-Language", "en-US,en;q=0.5");
        con.setRequestProperty("Accept-Encoding", "gzip, deflate");
        con.setRequestProperty("Referer", "http://bac.onec.dz/");
        con.setRequestProperty("Cookie", "bbbbbbbbbbbbbbb=ANNCLHAEAAAAAAAAJHKBHDAAAAAAAAAAEADAOFFHFHFHAAAADAAANKIFFKIFAAAA; TS1ff960=20859ee226968392c837af0430f21cf0087e23d48701410f5785a62879b49ee6533a75145e5dca68b041d236; aaaaaaaaaaaaaaa=GAABBCCHICBGBAAECAAAAAKCHHAAAAAAEACAALAAKGFHAAAADAAAAGAACKIFAAAA");
        con.setDoOutput(true);
        urlParameters = "matriculebac="+mat+"&dobac=%D8%A7%D8%B3%D8%AA%D8%B8%D9%87%D8%A7%D8%B1+%D8%A7%D9%84%D9%86%D8%AA%D9%8A%D8%AC%D8%A9";

        DataOutputStream wr = new DataOutputStream(con.getOutputStream());
            wr.writeBytes(urlParameters);
            wr.flush();
            wr.close();
         in = new BufferedReader( new InputStreamReader(con.getInputStream()));
         response = new StringBuffer();     
         Object[] aa = in.lines().toArray();

        for (Object object : aa) response.append(object.toString()+"\n");
        in.close();

        Pattern pattern = Pattern.compile("alert\(.*?\);");
        Matcher matcher = pattern.matcher(response.toString());
        String[] person = null;
         if (matcher.find())
        {
            String p =matcher.group(0).substring(7, matcher.group(0).length()-3);
            person = p.split("\\n");
        }
         try {
            String [] pp= 
                 {
                     person[0 ],
                     person[1 ].split(":")[1].substring(1),
                     person[2 ].split(":")[1].substring(1),
                     person[10].split(":")[1].substring(1),
                     person[4 ].split(":")[1].substring(1),
                     person[5 ].split(":")[1].substring(1),
                     person[6 ].split(":")[1].substring(1),
                     person[7 ].split(":")[1].substring(1),

                };

             CvsWrite(pp);
        } catch (Exception e) {

        }
    }
    public static  void CvsWrite(String[] args) throws IOException {
        List<String> pers = new ArrayList<>();
        for (String string : args) pers.add(string);
        String clct1 = pers.stream().collect(Collectors.joining(",")) + "\r\n";
        File f = new File(path);
        if (!f.exists())  
            try {   
                f.createNewFile();
                List<String> test = new ArrayList<>();
                test.add("الملاحظة");
                test.add("رقم التسجيل");
                test.add("الشعبة");
                test.add("المعدل");
                test.add("اللقب");
                test.add("الاسم");
                test.add("مكان الميلاد");
                test.add("تاريخ الميلاد");
                String clct2 = test.stream().collect(Collectors.joining(","))+ "\r\n\r\n";
                Files.write(Paths.get(path),clct2.getBytes(), StandardOpenOption.APPEND);

        } catch (IOException e) {}


        Files.write(Paths.get(path),clct1.getBytes(), StandardOpenOption.APPEND);
    }

}

运行 来自 eclipse,输出文件完美支持 UTF-8 编码。

运行 来自导出的 jar,输出文件的一部分是 ANSI 编码。现在,如果我只写这些词,那不会有问题,但是代码用阿拉伯语写其他内容,输出就像

输出文件是用记事本++打开的 在美国标准 http://i.stack.imgur.com/6RGEj.png 在 UTF-8 中 http://i.stack.imgur.com/Li0qf.png

正如我提到的,当 运行 来自 eclipse

时没有遇到这个问题

嗯,这听起来好像您在 运行 以不同的方式获得不同的默认编码 - 这在某种程度上是可以预料的。

将文本转换为二进制时,只需指定编码即可:

byte[] bytes = col.getBytes(StandardCharsets.UTF_8);
Files.write(Paths.get(path), bytes, StandardOpenOption.Append);

(我建议使用 Files.write 并直接传入文本,但这将使用平台默认换行符,这将是一个单独的问题...)

您在创建 InputStreamReader 时遇到了同样的问题:

in = new BufferedReader( new InputStreamReader(con.getInputStream()));

这是假设数据采用平台默认编码。 永远不要假设。您应该找出数据的 actual 编码是什么,并使用它来读取。然后决定(作为一个单独的问题)你想写什么编码。

使用的是String.getBytes(),它使用当前机器的默认操作系统编码。那不是便携式的。指定编码。

由于现有的旧内容是 ANSI,因此继续使用 ANSI。

   Files.write(Paths.get(path), clct2.getBytes("Windows-1256"), StandardOpenOption.APPEND);

并使用 ANSI 读取文件:

String s = new String(bytes, "Windows-1256");

第一次和第二次写文件操作使用默认的操作系统编码,或者为两者指定相同的编码,遇到同样的问题,即编码冲突。 解决方法是:将第一次写文件的编码指定为UTF-8。

.
.
String clct2 = test.stream().collect(Collectors.joining(","))+ "\r\n\r\n";
Files.write(Paths.get(path),clct2.getBytes("UTF-8"), StandardOpenOption.APPEND);
        } catch (IOException e) {}
Files.write(Paths.get(path),clct1.getBytes(), StandardOpenOption.APPEND);
.
.

This is certainly a dumb solution, since the bug is about portability and default OS encoding, but it worked :)