Java >> Java tutorial >  >> Tag >> String

Valider streng som filnavn i Java

1. Oversigt

I dette selvstudie vil vi diskutere forskellige måder at validere om en given streng har et gyldigt filnavn til OS, ved hjælp af Java . Vi ønsker at kontrollere værdien mod begrænsede tegn eller længdegrænser.

Gennem eksempler vil vi blot fokusere på kerneløsninger uden at bruge nogen eksterne afhængigheder. Vi tjekker SDK'ens java.io og NIO2-pakker, og endelig implementere vores egne løsninger.

2. Brug af java.io.File

Lad os starte med det allerførste eksempel ved at bruge java.io.File klasse. I denne løsning skal vi oprette en fil instans med en given streng og opret derefter en fil på den lokale disk:

public static boolean validateStringFilenameUsingIO(String filename) throws IOException {
    File file = new File(filename);
    boolean created = false;
    try {
        created = file.createNewFile();
        return created;
    } finally {
        if (created) {
            file.delete();
        }
    }
}

Når det givne filnavn er forkert, kaster det en IOException . Lad os bemærke, på grund af filoprettelsen indeni, kræver denne metode, at det givne filnavn String svarer ikke til den allerede eksisterende fil.

Vi ved, at forskellige filsystemer har deres egne filnavnebegrænsninger . Således ved at bruge java.io.File metoder, vi behøver ikke at specificere reglerne pr. OS , fordi Java automatisk tager sig af det for os.

Vi skal dog oprette en dummy-fil. Når det lykkes, skal vi huske at slette det i slutningen. Desuden skal vi sikre, at vi har de rigtige tilladelser til at udføre disse handlinger. Eventuelle fejl kan også forårsage en IOException , så det er også bedre at tjekke fejlmeddelelsen:

assertThatThrownBy(() -> validateStringFilenameUsingIO("baeldung?.txt"))
  .isInstanceOf(IOException.class)
  .hasMessageContaining("Invalid file path");

3. Bruger NIO2 API

Som vi kender java.io pakken har mange ulemper, fordi den blev oprettet i de første versioner af Java. NIO2 API, efterfølgeren til java.io pakke, bringer mange forbedringer, hvilket også i høj grad forenkler vores tidligere løsning:

public static boolean validateStringFilenameUsingNIO2(String filename) {
    Paths.get(filename);
    return true;
}

Vores funktion er nu strømlinet, så det er den hurtigste måde at udføre sådan en test på. Vi opretter ingen filer, så vi behøver ikke at have nogen disktilladelser og udføre rensning efter testen.

Det ugyldige filnavn kaster InvalidPathException , som udvider RuntimeException . Fejlmeddelelsen indeholder også flere detaljer end den forrige:

assertThatThrownBy(() -> validateStringFilenameUsingNIO2(filename))
  .isInstanceOf(InvalidPathException.class)
  .hasMessageContaining("character not allowed");

Denne løsning har enalvorlig ulempe forbundet med filsystemets begrænsninger . stien klasse kan repræsentere filstien med undermapper. I modsætning til det første eksempel kontrollerer denne metode ikke filnavnets overløbsgrænse. Lad os tjekke det mod en tilfældig streng på fem hundrede tegn genereret ved hjælp af randomAlphabetic() metode fra Apache Commons:

String filename = RandomStringUtils.randomAlphabetic(500);
assertThatThrownBy(() -> validateStringFilenameUsingIO(filename))
  .isInstanceOf(IOException.class)
  .hasMessageContaining("File name too long");

assertThat(validateStringFilenameUsingNIO2(filename)).isTrue();

For at rette op på det, bør vi, som tidligere, oprette en fil og kontrollere resultatet.

4. Brugerdefineret Implementeringer

Lad os endelig prøve at implementere vores egen brugerdefinerede funktion til at teste filnavne. Vi vil også forsøge at undgå enhver I/O-funktionalitet og kun bruge kerne Java-metoder.

Denne slags løsninger giver mere kontrol og giver os mulighed for atimplementere vores egne regler . Vi skal dog overveje mange yderligere begrænsninger til forskellige systemer.

4.1. Brug af String.contains

Vi kan bruge String.contains() metode for at kontrollere, om den givne streng har nogen af ​​de forbudte tegn. Først og fremmest skal vi manuelt angive nogle eksempelværdier:

public static final Character[] INVALID_WINDOWS_SPECIFIC_CHARS = {'"', '*', '<', '>', '?', '|'};
public static final Character[] INVALID_UNIX_SPECIFIC_CHARS = {'\000'};

I vores eksempel, lad os kun fokusere på disse to OS. Som vi ved, er Windows-filnavne mere begrænsede end UNIX . Nogle mellemrumstegn kan også være problematiske .

Efter at have defineret de begrænsede tegnsæt, lad os bestemme det aktuelle OS:

public static Character[] getInvalidCharsByOS() {
    String os = System.getProperty("os.name").toLowerCase();
    if (os.contains("win")) {
        return INVALID_WINDOWS_SPECIFIC_CHARS;
    } else if (os.contains("nix") || os.contains("nux") || os.contains("mac")) {
        return INVALID_UNIX_SPECIFIC_CHARS;
    } else {
        return new Character[]{};
    }
}

Og nu kan vi bruge det til at teste den givne værdi:

public static boolean validateStringFilenameUsingContains(String filename) {
    if (filename == null || filename.isEmpty() || filename.length() > 255) {
        return false;
    }
    return Arrays.stream(getInvalidCharsByOS())
      .noneMatch(ch -> filename.contains(ch.toString()));
}

Denne Strøm prædikat returnerer sandt, hvis nogen af ​​vores definerede tegn ikke er i et givet filnavn. Derudover implementerede vi support til null værdier og forkert længde.

4.2. Regex-mønstermatchning

Vi kan også bruge regulære udtryk direkte på den givne streng . Lad os implementere et mønster, der kun accepterer alfanumeriske tegn og punkttegn, med længden ikke større end 255:

public static final String REGEX_PATTERN = "^[A-za-z0-9.]{1,255}$";

public static boolean validateStringFilenameUsingRegex(String filename) {
    if (filename == null) {
        return false;
    }
    return filename.matches(REGEX_PATTERN);
}

Nu kan vi teste den givne værdi mod det tidligere forberedte mønster. Vi kan også nemt ændre mønsteret. Vi sprunget over OS-kontrolfunktionen i dette eksempel.

5. Konklusion

I denne artikel fokuserede vi på filnavne og deres begrænsninger. Vi introducerede forskellige algoritmer til at opdage et ugyldigt filnavn ved hjælp af Java.

Vi startede fra java.io pakke, som tager sig af de fleste af systembegrænsningerne for os, men udfører yderligere I/O-handlinger og kræver muligvis nogle tilladelser. Derefter tjekkede vi NIO2 API, som er den hurtigste løsning, med begrænsning af filnavnlængdekontrol .

Endelig implementerede vi vores egne metoder, uden at bruge nogen I/O API, men kræver tilpasset implementering af filsystemregler .

Du kan finde alle eksemplerne med yderligere test på GitHub.


Java tag