Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id 1A708200D3A for ; Wed, 15 Nov 2017 19:36:07 +0100 (CET) Received: by cust-asf.ponee.io (Postfix) id 1914F160BF4; Wed, 15 Nov 2017 18:36:07 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 11990160BE4 for ; Wed, 15 Nov 2017 19:36:05 +0100 (CET) Received: (qmail 47671 invoked by uid 500); 15 Nov 2017 18:36:05 -0000 Mailing-List: contact issues-help@commons.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: issues@commons.apache.org Delivered-To: mailing list issues@commons.apache.org Received: (qmail 47660 invoked by uid 99); 15 Nov 2017 18:36:05 -0000 Received: from pnap-us-west-generic-nat.apache.org (HELO spamd3-us-west.apache.org) (209.188.14.142) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 15 Nov 2017 18:36:05 +0000 Received: from localhost (localhost [127.0.0.1]) by spamd3-us-west.apache.org (ASF Mail Server at spamd3-us-west.apache.org) with ESMTP id 630AC1807D1 for ; Wed, 15 Nov 2017 18:36:04 +0000 (UTC) X-Virus-Scanned: Debian amavisd-new at spamd3-us-west.apache.org X-Spam-Flag: NO X-Spam-Score: -99.202 X-Spam-Level: X-Spam-Status: No, score=-99.202 tagged_above=-999 required=6.31 tests=[KAM_ASCII_DIVIDERS=0.8, RP_MATCHES_RCVD=-0.001, SPF_PASS=-0.001, USER_IN_WHITELIST=-100] autolearn=disabled Received: from mx1-lw-eu.apache.org ([10.40.0.8]) by localhost (spamd3-us-west.apache.org [10.40.0.10]) (amavisd-new, port 10024) with ESMTP id 3tJF7gNMMOGI for ; Wed, 15 Nov 2017 18:36:02 +0000 (UTC) Received: from mailrelay1-us-west.apache.org (mailrelay1-us-west.apache.org [209.188.14.139]) by mx1-lw-eu.apache.org (ASF Mail Server at mx1-lw-eu.apache.org) with ESMTP id 485D75FBB0 for ; Wed, 15 Nov 2017 18:36:01 +0000 (UTC) Received: from jira-lw-us.apache.org (unknown [207.244.88.139]) by mailrelay1-us-west.apache.org (ASF Mail Server at mailrelay1-us-west.apache.org) with ESMTP id 6871EE0C18 for ; Wed, 15 Nov 2017 18:36:00 +0000 (UTC) Received: from jira-lw-us.apache.org (localhost [127.0.0.1]) by jira-lw-us.apache.org (ASF Mail Server at jira-lw-us.apache.org) with ESMTP id 2644E240D6 for ; Wed, 15 Nov 2017 18:36:00 +0000 (UTC) Date: Wed, 15 Nov 2017 18:36:00 +0000 (UTC) From: "Gary Gregory (JIRA)" To: issues@commons.apache.org Message-ID: In-Reply-To: References: Subject: [jira] [Comment Edited] (IO-555) Add org.apache.commons.io.FilenameUtils.isIllegalWindowsFileName(char) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit X-JIRA-FingerPrint: 30527f35849b9dde25b450d4833f0394 archived-at: Wed, 15 Nov 2017 18:36:07 -0000 [ 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. > *

> * The illegal character are: > *

> *
    > *
  • < (less than
  • > *
  • > (greater than
  • > *
  • : (colon
  • > *
  • " (double quote
  • > *
  • / (forward slash
  • > *
  • \ (backslash
  • > *
  • | (vertical bar or pipe
  • > *
  • ? (question mark
  • > *
  • * (asterisk
  • > *
  • ASCII NUL (0)
  • > *
  • Integer characters 1 through 31
  • > *
  • There may be other characters that the file name does not allow. Please see > * Naming Files, Paths, > * and Namespaces
  • > *
> * > * @see Naming Files, > * Paths, and Namespaces > * @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)