[
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 [[email protected]] 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 [[email protected]] 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)