program story

파일 이름 특수 문자를 제거하는 크로스 플랫폼 Java 메서드가 있습니까?

inputbox 2021. 1. 8. 08:11
반응형

파일 이름 특수 문자를 제거하는 크로스 플랫폼 Java 메서드가 있습니까?


온라인에서 검색 한 데이터를 기반으로 파일 이름을 바꾸는 크로스 플랫폼 응용 프로그램을 만들고 있습니다. 현재 플랫폼의 웹 API에서 가져온 문자열을 삭제하고 싶습니다.

플랫폼마다 파일 이름 요구 사항이 다르다는 것을 알고 있으므로이를 수행하는 플랫폼 간 방법이 있는지 궁금합니다.

편집 : Windows 플랫폼에서는 물음표 '?'를 사용할 수 없습니다. 파일 이름에있는 반면 Linux에서는 가능합니다. 파일 이름에는 이러한 문자가 포함될 수 있으며 해당 문자를 지원하는 플랫폼에서 해당 문자를 유지하고 싶지만 그렇지 않으면 제거하십시오.

또한 타사 라이브러리가 필요하지 않은 표준 Java 솔루션을 선호합니다.


다른 곳에서 제안했듯이 이것은 일반적으로 원하는 작업이 아닙니다. 일반적으로 File.createTempFile ()과 같은 보안 메서드를 사용하여 임시 파일을 만드는 것이 가장 좋습니다.

화이트리스트로이 작업을 수행해서는 안되며 '좋은'문자 만 유지해야합니다. 파일이 중국어 문자로만 구성된 경우 모든 파일을 제거합니다. 이러한 이유로 화이트리스트를 사용할 수 없으며 블랙리스트를 사용해야합니다.

리눅스는 정말 고통 스러울 수있는 모든 것을 허용합니다. Windows를 제한하는 것과 동일한 목록으로 Linux를 제한하여 향후 두통을 덜어줍니다.

Windows에서이 C # 스 니펫을 사용하여 Windows에서 유효하지 않은 문자 목록을 생성했습니다. 이 목록에는 당신이 생각하는 것보다 훨씬 더 많은 문자가 있습니다 (41). 그래서 자신의 목록을 만들려고 시도하지 않는 것이 좋습니다.

        foreach (char c in new string(Path.GetInvalidFileNameChars()))
        {
            Console.Write((int)c);
            Console.Write(",");
        }

다음은 파일 이름을 '정리'하는 간단한 Java 클래스입니다.

public class FileNameCleaner {
final static int[] illegalChars = {34, 60, 62, 124, 0, 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, 58, 42, 63, 92, 47};
static {
    Arrays.sort(illegalChars);
}
public static String cleanFileName(String badFileName) {
    StringBuilder cleanName = new StringBuilder();
    for (int i = 0; i < badFileName.length(); i++) {
        int c = (int)badFileName.charAt(i);
        if (Arrays.binarySearch(illegalChars, c) < 0) {
            cleanName.append((char)c);
        }
    }
    return cleanName.toString();
}
}

편집 : Stephen이 제안했듯이 이러한 파일 액세스가 허용 된 디렉토리 내에서만 발생하는지 확인해야합니다.

다음 답변에는 Java에서 사용자 지정 보안 컨텍스트를 설정 한 다음 해당 '샌드 박스'에서 코드를 실행하는 샘플 코드가 있습니다.

보안 JEXL (스크립팅) 샌드 박스는 어떻게 생성합니까?


또는 다음을 수행하십시오.

String filename = "A20/B22b#öA\\BC#Ä$%ld_ma.la.xps";
String sane = filename.replaceAll("[^a-zA-Z0-9\\._]+", "_");

결과: A20_B22b_A_BC_ld_ma.la.xps

설명:

[a-zA-Z0-9\\._] z 소문자 또는 대문자, 숫자, 점 및 밑줄의 문자와 일치합니다.

[^a-zA-Z0-9\\._]역입니다. 즉, 첫 번째 표현식과 일치하지 않는 모든 문자

[^a-zA-Z0-9\\._]+ 첫 번째 표현식과 일치하지 않는 일련의 문자입니다.

따라서 az, 0-9 또는의 문자로 구성되지 않은 모든 문자 시퀀스. _이 (가) 대체됩니다.


This is based on the accepted answer by Sarel Botha which works fine as long as you don't encounter any characters outside of the Basic Multilingual Plane. If you need full Unicode support (and who doesn't?) use this code instead which is Unicode safe:

public class FileNameCleaner {
  final static int[] illegalChars = {34, 60, 62, 124, 0, 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, 58, 42, 63, 92, 47};

  static {
    Arrays.sort(illegalChars);
  }

  public static String cleanFileName(String badFileName) {
    StringBuilder cleanName = new StringBuilder();
    int len = badFileName.codePointCount(0, badFileName.length());
    for (int i=0; i<len; i++) {
      int c = badFileName.codePointAt(i);
      if (Arrays.binarySearch(illegalChars, c) < 0) {
        cleanName.appendCodePoint(c);
      }
    }
    return cleanName.toString();
  }
}

Key changes here:

  • Use codePointCount i.c.w. length instead of just length
  • use codePointAt instead of charAt
  • use appendCodePoint instead of append
  • No need to cast chars to ints. In fact, you should never deal with chars as they are basically broken for anything outside the BMP.

There's a pretty good built-in Java solution - Character.isXxx().

Try Character.isJavaIdentifierPart(c):

String name = "name.é+!@#$%^&*(){}][/=?+-_\\|;:`~!'\",<>";
StringBuilder filename = new StringBuilder();

for (char c : name.toCharArray()) {
  if (c=='.' || Character.isJavaIdentifierPart(c)) {
    filename.append(c);
  }
}

Result is "name.é$_".


Here is the code I use:

public static String sanitizeName( String name ) {
    if( null == name ) {
        return "";
    }

    if( SystemUtils.IS_OS_LINUX ) {
        return name.replaceAll( "/+", "" ).trim();
    }

    return name.replaceAll( "[\u0001-\u001f<>:\"/\\\\|?*\u007f]+", "" ).trim();
}

SystemUtils is from Apache commons-lang3


It is not clear from your question, but since you are planning to accept pathnames from a web form (?) you probably ought block attempts renaming certain things; e.g. "C:\Program Files". This implies that you need to canonicalize the pathnames to eliminate "." and ".." before you make your access checks.

Given that, I wouldn't attempt to remove illegal characters. Instead, I'd use "new File(str).getCanonicalFile()" to produce the canonical paths, next check that they satisfy your sandboxing restrictions, and finally use "File.exists()", "File.isFile()", etc to check that the source and destination are kosher, and are not the same file system object. I'd deal with illegal characters by attempting to do the operations and catching the exceptions.


Paths.get(...) throws a detailed exception with the position of the illegal character.

public static String removeInvalidChars(final String fileName)
{
  try
  {
    Paths.get(fileName);
    return fileName;
  }
  catch (final InvalidPathException e)
  {
    if (e.getInput() != null && e.getInput().length() > 0 && e.getIndex() >= 0)
    {
      final StringBuilder stringBuilder = new StringBuilder(e.getInput());
      stringBuilder.deleteCharAt(e.getIndex());
      return removeInvalidChars(stringBuilder.toString());
    }
    throw e;
  }
}

If you want to use more than like [A-Za-z0-9], then check MS Naming Conventions, and dont forget to filter out "...Characters whose integer representations are in the range from 1 through 31,...", like the example of Aaron Digulla does. The code e.g. from David Carboni would not be sufficient for these chars.

Excerpt containing the list of reserved characters:

Use any character in the current code page for a name, including Unicode characters and characters in the extended character set (128–255), except for the following:

The following reserved characters:

  • < (less than)
  • > (greater than)
  • : (colon)
  • " (double quote)
  • / (forward slash)
  • \ (backslash)
  • | (vertical bar or pipe)
  • ? (question mark)
  • * (asterisk)
  • Integer value zero, sometimes referred to as the ASCII NUL character.
  • Characters whose integer representations are in the range from 1 through 31, except for alternate data streams where these characters are allowed. For more information about file streams, see File Streams.
  • Any other character that the target file system does not allow.

ReferenceURL : https://stackoverflow.com/questions/1155107/is-there-a-cross-platform-java-method-to-remove-filename-special-chars

반응형