You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@commons.apache.org by "Gary Gregory (JIRA)" <ji...@apache.org> on 2017/11/15 18:36:00 UTC

[jira] [Comment Edited] (IO-555) Add org.apache.commons.io.FilenameUtils.isIllegalWindowsFileName(char)

    [ https://issues.apache.org/jira/browse/IO-555?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16253922#comment-16253922 ] 

Gary Gregory edited comment on IO-555 at 11/15/17 6:35 PM:
-----------------------------------------------------------

Hi [~sebb@apache.org] and thank you for the feedback.

- My overall is use-case is that I have to use Strings from an external data source that is out of my control to generate file names to save files in a given directory. The directory is already set up, all I need a clean file names to create files in that directory.
- I added the {{'/'}} character for Mac OS per your correction.
- I added Javadocs to the {{toLegalFileName()}} method for my use-case:
{code:java}
    /**
     * Converts a candidate file name (without a path) like {@code "filename.ext"} or {@code "filename"} to a legal file name. Illegal characters in
     * the candidate name are replaced by the {@code replacement} character.
     * 
     * @param candidate
     *            a candidate file name (without a path) like {@code "filename.ext"} or {@code "filename"}
     * @param replacement
     *            Illegal characters in the candidate name are replaced by this character
     * @return a String without illegal characters
     */
{code}

New version:

{code:java}
/*
 * Copyright 2017-2017 Rocket Software, Inc. All rights reserved.
 */
package com.seagullsw.javax.io;

import java.util.Arrays;

import org.apache.commons.lang3.SystemUtils;

// TODO Apache Commons IO 2.7
public enum FileSystem {

    UNSUPPORTED(Integer.MAX_VALUE, Integer.MAX_VALUE, new char[] {}),

    LINUX(255, 4096, new char[] {
            // KEEP THIS ARRAY SORTED!
            // @formatter:off
            // ASCII NULL
            0,  
             '/'
            // @formatter:on
    }),

    MAC_OSX(255, 1024, new char[] {
            // KEEP THIS ARRAY SORTED!
            // @formatter:off
            // ASCII NULL
            0,  
            '/',
             ':'
            // @formatter:on
    }),

    WINDOWS(255, 32000, new char[] {
            // KEEP THIS ARRAY SORTED!
            // @formatter:off
            // ASCII NULL
            0,  
            // 1-31 may be allowed in file streams
            1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
            29, 30, 31, 
            '"', '*', '/', ':', '<', '>', '?', '\\', '|'
            // @formatter:on
    });

    public static FileSystem getCurrent() {
        if (SystemUtils.IS_OS_LINUX) {
            return LINUX;
        }
        if (SystemUtils.IS_OS_MAC_OSX) {
            return FileSystem.MAC_OSX;
        }
        if (SystemUtils.IS_OS_WINDOWS) {
            return FileSystem.WINDOWS;
        }
        return UNSUPPORTED;
    }

    private final int maxFileNameLength;
    private final int maxPathLength;

    private final char[] illegalFileNameChars;

    private FileSystem(final int maxFileLength, final int maxPathLength, final char[] illegalFileNameChars) {
        this.maxFileNameLength = maxFileLength;
        this.maxPathLength = maxPathLength;
        this.illegalFileNameChars = illegalFileNameChars;
    }

    public char[] getIllegalFileNameChars() {
        return this.illegalFileNameChars.clone();
    }

    public int getMaxFileNameLength() {
        return maxFileNameLength;
    }

    public int getMaxPathLength() {
        return maxPathLength;
    }

    public boolean isIllegalFileNameChar(final char c) {
        return Arrays.binarySearch(illegalFileNameChars, c) >= 0;
    }

    /**
     * Converts a candidate file name (without a path) like {@code "filename.ext"} or {@code "filename"} to a legal file name. Illegal characters in
     * the candidate name are replaced by the {@code replacement} character.
     * 
     * @param candidate
     *            a candidate file name (without a path) like {@code "filename.ext"} or {@code "filename"}
     * @param replacement
     *            Illegal characters in the candidate name are replaced by this character
     * @return a String without illegal characters
     */
    public String toLegalFileName(final String candidate, final char replacement) {
        final String truncated = candidate.length() > maxFileNameLength ? candidate.substring(0, maxFileNameLength) : candidate;
        boolean changed = false;
        final char[] charArray = truncated.toCharArray();
        for (int i = 0; i < charArray.length; i++) {
            if (isIllegalFileNameChar(charArray[i])) {
                charArray[i] = replacement;
                changed = true;
            }
        }
        return changed ? String.valueOf(charArray) : truncated;
    }
}
{code}

- If the parameter is a {{CharSequence}}, the code is _less_ flexible; if you want that, then we can have another method typed to a {{CharSequence}} in addition to the current method using a {{String}}. For example, you cannot convert to a char[], you must call {{charAt()}}.
- The maxPathLength is just there because I found the info but I have not incorporated it yet.




was (Author: garydgregory):
Hi [~sebb@apache.org] and thank you for the feedback.

- My overall is use-case is that I have to use Strings from an external data source that is out of my control to generate file names to save files in a given directory. The directory is already set up, all I need a clean file names to create files in that directory.
- I added the {{'/'}} character for Mac OS per your correction.
- I added Javadocs to the {{toLegalFileName()}} method for my use-case:
{code:java}
    /**
     * Converts a candidate file name (without a path) like {@code "filename.ext"} or {@code "filename"} to a legal file name. Illegal characters in
     * the candidate name are replaced by the {@code replacement} character.
     * 
     * @param candidate
     *            a candidate file name (without a path) like {@code "filename.ext"} or {@code "filename"}
     * @param replacement
     *            Illegal characters in the candidate name are replaced by this character
     * @return a String without illegal characters
     */
{code}

New version:

{code:java}
/*
 * Copyright 2017-2017 Rocket Software, Inc. All rights reserved.
 */
package com.seagullsw.javax.io;

import java.util.Arrays;

import org.apache.commons.lang3.SystemUtils;

// TODO Apache Commons IO 2.7
public enum FileSystem {

    UNSUPPORTED(Integer.MAX_VALUE, Integer.MAX_VALUE, new char[] {}),

    LINUX(255, 4096, new char[] {
            // KEEP THIS ARRAY SORTED!
            // @formatter:off
            // ASCII NULL
            0,  
             '/'
            // @formatter:on
    }),

    MAC_OSX(255, 1024, new char[] {
            // KEEP THIS ARRAY SORTED!
            // @formatter:off
            // ASCII NULL
            0,  
            '/',
             ':'
            // @formatter:on
    }),

    WINDOWS(255, 32000, new char[] {
            // KEEP THIS ARRAY SORTED!
            // @formatter:off
            // ASCII NULL
            0,  
            // 1-31 may be allowed in file streams
            1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
            29, 30, 31, 
            '"', '*', '/', ':', '<', '>', '?', '\\', '|'
            // @formatter:on
    });

    public static FileSystem getCurrent() {
        if (SystemUtils.IS_OS_LINUX) {
            return LINUX;
        }
        if (SystemUtils.IS_OS_MAC_OSX) {
            return FileSystem.MAC_OSX;
        }
        if (SystemUtils.IS_OS_WINDOWS) {
            return FileSystem.WINDOWS;
        }
        return UNSUPPORTED;
    }

    private final int maxFileNameLength;
    private final int maxPathLength;

    private final char[] illegalFileNameChars;

    private FileSystem(final int maxFileLength, final int maxPathLength, final char[] illegalFileNameChars) {
        this.maxFileNameLength = maxFileLength;
        this.maxPathLength = maxPathLength;
        this.illegalFileNameChars = illegalFileNameChars;
    }

    public char[] getIllegalFileNameChars() {
        return this.illegalFileNameChars.clone();
    }

    public int getMaxFileNameLength() {
        return maxFileNameLength;
    }

    public int getMaxPathLength() {
        return maxPathLength;
    }

    public boolean isIllegalFileNameChar(final char c) {
        return Arrays.binarySearch(illegalFileNameChars, c) >= 0;
    }

    /**
     * Converts a candidate file name (without a path) like {@code "filename.ext"} or {@code "filename"} to a legal file name. Illegal characters in
     * the candidate name are replaced by the {@code replacement} character.
     * 
     * @param candidate
     *            a candidate file name (without a path) like {@code "filename.ext"} or {@code "filename"}
     * @param replacement
     *            Illegal characters in the candidate name are replaced by this character
     * @return a String without illegal characters
     */
    public String toLegalFileName(final String candidate, final char replacement) {
        final String truncated = candidate.length() > maxFileNameLength ? candidate.substring(0, maxFileNameLength) : candidate;
        boolean changed = false;
        final char[] charArray = truncated.toCharArray();
        for (int i = 0; i < charArray.length; i++) {
            if (isIllegalFileNameChar(charArray[i])) {
                charArray[i] = replacement;
                changed = true;
            }
        }
        return changed ? String.valueOf(charArray) : truncated;
    }
}
{code}

- If the parameter is a {{CharSequence}}, the code is _less_ flexible; if you want that, then we can have another method typed to a {{CharSequence}} in addition to the current method using a {{String}}. For example, you cannot convert to a char[], you must call {{charAt()}}.



> Add org.apache.commons.io.FilenameUtils.isIllegalWindowsFileName(char)
> ----------------------------------------------------------------------
>
>                 Key: IO-555
>                 URL: https://issues.apache.org/jira/browse/IO-555
>             Project: Commons IO
>          Issue Type: Improvement
>            Reporter: Gary Gregory
>            Assignee: Gary Gregory
>             Fix For: 2.7
>
>
> Add {{org.apache.commons.io.FilenameUtils.isIllegalWindowsFileName(char)}}.
> {code:java}
>     /**
>      * Checks whether the given character is illegal in a Windows file names.
>      * <p>
>      * The illegal character are:
>      * </p>
>      * <ul>
>      * <li>< (less than</li>
>      * <li>> (greater than</li>
>      * <li>: (colon</li>
>      * <li>" (double quote</li>
>      * <li>/ (forward slash</li>
>      * <li>\ (backslash</li>
>      * <li>| (vertical bar or pipe</li>
>      * <li>? (question mark</li>
>      * <li>* (asterisk</li>
>      * <li>ASCII NUL (0)</li>
>      * <li>Integer characters 1 through 31</li>
>      * <li>There may be other characters that the file name does not allow. Please see
>      * <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx">Naming Files, Paths,
>      * and Namespaces</a></li>
>      * </ul>
>      * 
>      * @see <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx">Naming Files,
>      *      Paths, and Namespaces</a>
>      * @param c
>      *            the character to check
>      * @return whether the give character is legal
>      * @since 2.7
>      */
> {code}
> I use this method as a building block to create file names based on Strings from other sources.
> A further contribution could be: {{String toLegalWindowsFileName(String input, char replacementChar)}}



--
This message was sent by Atlassian JIRA
(v6.4.14#64029)