Java >> Java tutorial >  >> Tag >> char

Ulovlig tegnkompileringsfejl

1. Oversigt

Den ulovlige tegnkompileringsfejl er en filtypekodningsfejl. Det produceres, hvis vi bruger en forkert kodning i vores filer, når de oprettes. Som et resultat, i sprog som Java, kan vi få denne type fejl, når vi forsøger at kompilere vores projekt. I denne øvelse vil vi beskrive problemet i detaljer sammen med nogle scenarier, hvor vi kan støde på det, og derefter præsenterer vi nogle eksempler på, hvordan det løses.

2. Ulovlig tegnkompileringsfejl

2.1. Byte Order Mark (BOM)

Før vi går ind i byte-rækkefølgen, skal vi tage et hurtigt kig på UCS (Unicode) Transformation Format (UTF). UTF er et tegnkodningsformat, der kan kode alle mulige tegnkodepunkter i Unicode . Der er flere slags UTF-kodninger. Blandt alle disse har UTF-8 været den mest brugte.

UTF-8 bruger en 8-bit variabel bredde-kodning for at maksimere kompatibiliteten med ASCII. Når vi bruger denne kodning i vores filer, kan vi finde nogle bytes, der repræsenterer Unicode-kodepunktet. Som et resultat starter vores filer med et U+FEFF-byteordremærke (BOM). Dette mærke, korrekt brugt, er usynligt. I nogle tilfælde kan det dog føre til datafejl.

I UTF-8-kodningen er tilstedeværelsen af ​​styklisten ikke grundlæggende . Selvom det ikke er vigtigt, kan styklisten stadig vises i UTF-8-kodet tekst. Tilføjelsen af ​​stykliste kan ske enten ved en kodningskonvertering eller af en teksteditor, der markerer indholdet som UTF-8.

Teksteditorer som Notepad på Windows kunne producere denne form for tilføjelse. Som en konsekvens, når vi bruger en Notesblok-lignende teksteditor til at oprette et kodeeksempel og forsøger at køre det, kan vi få en kompileringsfejl. I modsætning hertil koder moderne IDE'er oprettede filer som UTF-8 uden styklisten. De næste afsnit vil vise nogle eksempler på dette problem.

2.2. Klasse med ulovlig tegnkompileringsfejl

Typisk arbejder vi med avancerede IDE'er, men nogle gange bruger vi en teksteditor i stedet for. Desværre, som vi har erfaret, kan nogle teksteditorer skabe flere problemer end løsninger, fordi lagring af en fil med en stykliste kan føre til en kompileringsfejl i Java. Fejlen "ulovlig tegn" opstår i kompileringsfasen, så det er ret let at opdage . Det næste eksempel viser os, hvordan det virker.

Lad os først skrive en simpel klasse i vores teksteditor, såsom Notesblok. Denne klasse er kun en repræsentation - vi kunne skrive en hvilken som helst kode for at teste. Dernæst gemmer vi vores fil med styklisten for at teste:

public class TestBOM {
    public static void main(String ...args){
        System.out.println("BOM Test");
    }
}

Nu, når vi prøver at kompilere denne fil ved hjælp af javac kommando:

$ javac ./TestBOM.java

Derfor får vi fejlmeddelelsen:

public class TestBOM {
 ^
.\TestBOM.java:1: error: illegal character: '\u00bf'
public class TestBOM {
  ^
2 errors

Ideelt set, for at løse dette problem, er den eneste ting at gøre at gemme filen som UTF-8 uden BOM-kodning. Herefter er problemet løst. Vi bør altid kontrollere, at vores filer er gemt uden en stykliste .

En anden måde at løse dette problem på er med et værktøj som dos2unix . Dette værktøj vil fjerne styklisten og også tage sig af andre idiosynkrasier af Windows-tekstfiler.

3. Læser filer

Lad os desuden analysere nogle eksempler på læsning af filer kodet med BOM.

I første omgang skal vi oprette en fil med stykliste til brug for vores test. Denne fil indeholder vores eksempeltekst, "Hello world with BOM." – som bliver vores forventede streng. Lad os derefter begynde at teste.

3.1. Læsning af filer ved hjælp af BufferedReader

Først tester vi filen ved hjælp af BufferedReader klasse:

@Test
public void whenInputFileHasBOM_thenUseInputStream() throws IOException {
    String line;
    String actual = "";
    try (BufferedReader br = new BufferedReader(new InputStreamReader(file))) {
        while ((line = br.readLine()) != null) {
            actual += line;
        }
    }
    assertEquals(expected, actual);
}

I dette tilfælde, når vi forsøger at hævde, at strengene er ens, får vi en fejl :

org.opentest4j.AssertionFailedError: expected: <Hello world with BOM.> but was: <Hello world with BOM.>
Expected :Hello world with BOM.
Actual   :Hello world with BOM.

Faktisk, hvis vi skimmer testsvaret, ser begge strenge tilsyneladende lige ud. Alligevel indeholder den faktiske værdi af strengen styklisten. Som et resultat er strengene ikke ens.

Desuden en hurtig løsning ville være at erstatte styklistetegn :

@Test
public void whenInputFileHasBOM_thenUseInputStreamWithReplace() throws IOException {
    String line;
    String actual = "";
    try (BufferedReader br = new BufferedReader(new InputStreamReader(file))) {
        while ((line = br.readLine()) != null) {
            actual += line.replace("\uFEFF", "");
        }
    }
    assertEquals(expected, actual);
}

erstat metoden rydder styklisten fra vores streng, så vores test består. Vi skal arbejde omhyggeligt med erstat metode. Et stort antal filer, der skal behandles, kan føre til ydeevneproblemer.

3.2. Læsning af filer ved hjælp af Apache Commons IO

Derudover tilbyder Apache Commons IO-biblioteket BOMInputStream klasse . Denne klasse er en indpakning, der inkluderer et kodet ByteOrderMark som dens første bytes. Lad os se, hvordan det virker:

@Test
public void whenInputFileHasBOM_thenUseBOMInputStream() throws IOException {
    String line;
    String actual = "";
    ByteOrderMark[] byteOrderMarks = new ByteOrderMark[] { 
      ByteOrderMark.UTF_8, ByteOrderMark.UTF_16BE, ByteOrderMark.UTF_16LE, ByteOrderMark.UTF_32BE, ByteOrderMark.UTF_32LE
    };
    InputStream inputStream = new BOMInputStream(ioStream, false, byteOrderMarks);
    Reader reader = new InputStreamReader(inputStream);
    BufferedReader br = new BufferedReader(reader);
    while ((line = br.readLine()) != null) {
        actual += line;
    }
    assertEquals(expected, actual);
}

Koden ligner tidligere eksempler, men vi videregiver BOMInputStream som en parameter i InputStreamReader .

3.3. Læsning af filer ved hjælp af Google Data (GData)

På den anden side er et andet nyttigt bibliotek til at håndtere styklisten Google Data (GData) . Dette er et ældre bibliotek, men det hjælper med at administrere styklisten inde i filerne. Det bruger XML som dets underliggende format. Lad os se det i aktion:

@Test
public void whenInputFileHasBOM_thenUseGoogleGdata() throws IOException {
    char[] actual = new char[21];
    try (Reader r = new UnicodeReader(ioStream, null)) {
        r.read(actual);
    }
    assertEquals(expected, String.valueOf(actual));
}

Endelig, som vi observerede i de foregående eksempler, er det vigtigt at fjerne styklisten fra filerne. Hvis vi ikke håndterer det korrekt i vores filer, vil der ske uventede resultater, når dataene læses. Det er derfor, vi skal være opmærksomme på eksistensen af ​​dette mærke i vores filer.

4. Konklusion

I denne artikel dækkede vi flere emner vedrørende den ulovlige tegnkompileringsfejl i Java. Først lærte vi, hvad UTF er, og hvordan styklisten er integreret i den. For det andet viste vi en prøveklasse oprettet ved hjælp af en teksteditor - Windows Notesblok, i dette tilfælde. Den genererede klasse kastede kompileringsfejlen for den ulovlige karakter. Til sidst præsenterede vi nogle kodeeksempler på, hvordan man læser filer med en stykliste.

Som sædvanlig kan al den kode, der bruges til dette eksempel, findes på GitHub.


Java tag