2010-06-13 12 views
5

Ho un piccolo progetto Java in cui ho impostato le proprietà dei file di classe su UTF-8 (utilizzo un sacco di caratteri stranieri non trovati sul CP1252 predefinito) .Creazione di file UTF-8 in Java da un Jar eseguibile

L'obiettivo è creare un file di testo (in Windows) contenente un elenco di elementi. Quando si esegue il file di classe da Eclipse stesso (premendo Ctrl + F11) crea il file in modo impeccabile e aprendolo in un altro editor (sto usando Notepad ++) Posso vedere i personaggi come volevo.

┌──────────────────────────────────────────────────┐ 
│       Universidade2010 (18/18)│ 
│           hidden: 0│ 
├──────────────────────────────────────────────────┤ 

Ma, quando ho esportare il progetto (con Eclipse) come Jar eseguibile ed eseguirlo usando 'javaw -jar project.jar' il nuovo file creato è un pasticcio di punti interrogativi

???????????????????????????????????????????????????? 
?       Universidade2010 (19/19)? 
?           hidden: 0? 
???????????????????????????????????????????????????? 

ho seguito alcuni suggerimenti su come utilizzare UTF-8 (che sembra essere rotto di default su Java) per cercare di correggere questo modo ora sto usando

Writer w = new OutputStreamWriter(fos, "UTF-8"); 

e scrivendo l'intestazione della distinta base alla file come in questo question already answered ma ancora senza fortuna durante l'esportazione in Jar

Mi mancano alcuni comandi di proprietà o riga di comando, quindi Java sa che voglio creare file UTF-8 per impostazione predefinita?


il problema non è sulla creazione del file stesso, perché mentre in via di sviluppo il file viene emesso correttamente (con i caratteri Unicode)

La classe che crea il file è ora (e seguendo il suggerimento di utilizzando la classe Charset) come questo:

public class Printer { 

    File f; 
    FileOutputStream fos; 
    Writer w; 
    final byte[] utf8_bom = { (byte) 0xEF, (byte) 0xBB, (byte) 0xBF }; 

    public Printer(String filename){ 
     f = new File(filename); 
     try { 
      fos = new FileOutputStream(f); 
      w = new OutputStreamWriter(fos, Charset.forName("UTF-8")); 
      fos.write(utf8_bom); 
     } catch (FileNotFoundException e) { 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

    public void print(String s) { 
     if(fos != null){ 
      try { 
       fos.write(s.getBytes()); 
       fos.flush(); 
      } catch (IOException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
     } 
    } 

} 

E tutti i caratteri in uso sono definiti come tali:

private final char pipe = '\u2502';   /* │ */ 
private final char line = '\u2500';   /* ─ */ 
private final char pipeleft = '\u251c';  /* ├ */ 
private final char piperight = '\u2524'; /* ┤ */ 
private final char cupleft = '\u250c';  /* ┌ */ 
private final char cupright = '\u2510';  /* ┐ */ 
private final char cdownleft = '\u2514'; /* └ */ 
private final char cdownright = '\u2518'; /* ┘ */ 

Il problema rimane, quando si esegue l'output su un file semplicemente eseguendo il progetto su Eclipse, il file risulta perfetto, ma dopo aver distribuito il progetto in un Jar e averlo eseguito il file emesso ha la formattazione distrutta (ho scoperto che sono sostituiti dal carattere "?")

Sono arrivato a pensare che questo non sia un problema con il codice, è un problema se lo si distribuisce in un file Jar, penso che Eclipse stia compilando i file sorgente per CP1252 o qualcosa del genere, ma anche sostituendo tutti i caratteri unicode per le loro costanti di codice non ha aiutato

+2

Cosa stai usando per vedere i punti interrogativi? Un'utilità che uso molto sotto Linux è 'od -c nome-file' che scarica il file byte per byte. Dovresti essere in grado di vedere se il file generato all'interno di eclipse e dalla riga di comando è lo stesso. Sospetto che siano tutti uguali e il tuo editore stia ostacolando. – Gray

+0

Sto usando il Notepad ++ per aprire i 2 file di testo generati (quello dal pacchetto jar e quello dal progetto in eclissi), quando apro i file notepad ++ indica che è un "UNIX UTF-8" file per entrambi, ma i file sembrano diversi, anche se è lo stesso codice in esecuzione, solo impacchettato come un Jar eseguibile – RuntimeError

+0

Analizzando i due file su un editor esadecimale il file creato dal Jar sembra aver sostituito tutti i non ANSI caratteri con 0x3F (punto interrogativo), ma il codice BOM viene scritto con successo all'inizio. – RuntimeError

risposta

6

ho seguito alcuni suggerimenti su come utilizzare UTF-8 (che sembra essere rotto per default su Java)

Per motivi storici, la codifica di Java ha come valore predefinito la codifica del sistema (qualcosa che ha più senso in Windows 95). È probabile che questo comportamento non cambi. Per quanto ne so, non c'è nulla di rotto nell'implementazione dell'encoder di Java.

private static final String BOM = "\ufeff"; 

    public static void main(String[] args) throws IOException { 
    String data = "\u250c\u2500\u2500\u2510\r\n\u251c\u2500\u2500\u2524"; 
    OutputStream out = new FileOutputStream("data.txt"); 
    Closeable resource = out; 
    try { 
     Writer writer = new OutputStreamWriter(out, Charset.forName("UTF-8")); 
     resource = writer; 
     writer.write(BOM); 
     writer.write(data); 
    } finally { 
     resource.close(); 
    } 
    } 

Il codice di cui sopra emetterà il seguente testo preceduto da un segno di ordine di byte:

& # x250c; & # X2500; & # X2500; & # x2510;
& # x251c; & # x2500; & # x2500; & # x2524;

Le app di Windows come Blocco note possono dedurre la codifica dalla distinta componenti e decodificare correttamente il file.

Senza codice, non è possibile individuare alcun errore.

Mi manca qualche proprietà o comando da riga di comando, quindi Java sa che voglio creare file UTF-8 per impostazione predefinita?

No - non esiste questa impostazione. Alcuni potrebbero suggerire di impostare file.encoding sulla riga di comando, ma questo è un bad idea.


ho scritto un post del blog più completa sull'argomento here.


Questa è una rielaborazione di your code:

public class Printer implements Closeable { 
    private PrintWriter pw; 
    private boolean error; 

    public Printer(String name) { 
    try { 
     pw = new PrintWriter(name, "UTF-8"); 
     pw.print('\uFEFF'); // BOM 
     error = false; 
    } catch (IOException e) { 
     error = true; 
    } 
    } 

    public void print(String s) { 
    if (pw == null) return; 
    pw.print(s); 
    pw.flush(); 
    } 

    public boolean checkError() { return error || pw.checkError(); } 

    @Override public void close() { if (pw != null) pw.close(); } 
} 

maggior parte delle funzionalità che si desidera già esiste in PrintWriter. Si noti che è necessario fornire un meccanismo per controllare gli errori sottostanti e chiudere lo stream (o si rischia di perdere gli handle di file).

+0

+1 per usare gli escape Unicode ('\ u250c' ecc.) Per scrivere quei caratteri speciali nel file sorgente Java. Questo elimina una possibile fonte di problemi: diversi editor di testo potrebbero salvare il file sorgente Java in diverse codifiche. – cygri

+0

Sfortunatamente il problema rimane, ho aggiunto il codice parziale in una nuova risposta – RuntimeError

Problemi correlati