Làm cách nào để cắt bớt phần mở rộng tệp từ Chuỗi trong Java?


176

Cách hiệu quả nhất để cắt hậu tố trong Java, như thế này:

title part1.txt
title part2.html
=>
title part1
title part2

2
Mã hiệu quả khôn ngoan, là những gì bạn muốn nói, tôi hy vọng, không phải CPU khôn ngoan
mkoryak

3
Anh ta không hỏi làm thế nào để làm điều đó, anh ta hỏi cách hiệu quả nhất. Tôi đến đây để tìm kiếm điều tương tự.
Edward Falk

Câu trả lời:


285

Đây là loại mã mà chúng ta không nên tự làm. Sử dụng các thư viện cho những thứ trần tục, tiết kiệm bộ não của bạn cho những thứ cứng.

Trong trường hợp này, tôi khuyên bạn nên sử dụng FilenameUtils.removeExtension () từ Apache Commons IO


7
Hoàn toàn đập vào.
Joshua Pinter

6
Đối với 95% các dự án, đây sẽ là câu trả lời được chấp nhận. Viết lại mã như thế này là nguyên nhân gốc rễ khiến nhiều người đau đầu!
Carsten Hoffmann

1
Chỉ cần thêm dòng sau vào lớp để thêm phụ thuộc: - biên dịch 'commons-io: commons-io: 2.6'
Deepak Sharma

làm ơn ví dụ
john ktejik

8
Nếu bạn đã có I / O Apache Commons trong dự án của mình, điều đó đúng. Nhưng nếu tất cả những gì bạn cần từ nó, bạn sẽ thêm (ít nhất) 2,5 MB trọng lượng chết vào dự án của mình cho một thứ có thể dễ dàng thực hiện với một dòng duy nhất.
foo

226
str.substring(0, str.lastIndexOf('.'))

8
Điều này nên được gán cho một biến mới vì str không được sửa đổi.
Nathan Feger

51
Xử lý cẩn thận: nó sẽ ném Ngoại lệ cho bạn nếu tên tệp không có hậu tố.
Andreas Dolk

24
Còn về archive.tar.bz2 thì sao?
Antonio

20
if(str.contains(".")) str.substring(0, str.lastIndexOf('.'))
Nicolas Tyler

6
if (str! = null && str.contains (".")) str.sub chuỗi (0, str.lastIndexOf ('.')). FilenameUtils là một phụ thuộc khác và không phải lúc nào cũng có sẵn
ocramot

88

Vì việc sử dụng String.substringString.lastIndextrong một lớp lót là tốt, có một số vấn đề về khả năng đối phó với các đường dẫn tệp nhất định.

Lấy ví dụ đường dẫn sau:

a.b/c

Sử dụng một lớp lót sẽ dẫn đến:

a

Điều đó không chính xác.

Kết quả đáng lẽ phải có c, nhưng vì tệp thiếu phần mở rộng, nhưng đường dẫn có một thư mục có .tên, phương thức one-liner bị lừa đưa ra một phần của đường dẫn là tên tệp, không đúng.

Cần kiểm tra

Lấy cảm hứng từ câu trả lời của skaffman , tôi đã xem FilenameUtils.removeExtensionphương pháp của Apache Commons IO .

Để tạo lại hành vi của nó, tôi đã viết một vài thử nghiệm mà phương thức mới cần thực hiện, đó là:

Tên tệp đường dẫn
-------------- --------
a / b / cc
a / b / c.jpg c
a / b / c.jpg.jpg

ab / cc
ab / c.jpg c
ab / c.jpg.jpg c.jpg

cc
c.jpg c
c.jpg.jpg

(Và đó là tất cả những gì tôi đã kiểm tra - có thể có những kiểm tra khác nên được đặt tại chỗ mà tôi đã bỏ qua.)

Việc thực hiện

Sau đây là triển khai của tôi cho removeExtensionphương pháp:

public static String removeExtension(String s) {

    String separator = System.getProperty("file.separator");
    String filename;

    // Remove the path upto the filename.
    int lastSeparatorIndex = s.lastIndexOf(separator);
    if (lastSeparatorIndex == -1) {
        filename = s;
    } else {
        filename = s.substring(lastSeparatorIndex + 1);
    }

    // Remove the extension.
    int extensionIndex = filename.lastIndexOf(".");
    if (extensionIndex == -1)
        return filename;

    return filename.substring(0, extensionIndex);
}

Chạy removeExtensionphương pháp này với các thử nghiệm trên mang lại kết quả được liệt kê ở trên.

Phương pháp đã được thử nghiệm với mã sau đây. Vì điều này đã được chạy trên Windows, trình phân tách đường dẫn là một lối \thoát phải được thoát với \khi được sử dụng như một phần của Stringnghĩa đen.

System.out.println(removeExtension("a\\b\\c"));
System.out.println(removeExtension("a\\b\\c.jpg"));
System.out.println(removeExtension("a\\b\\c.jpg.jpg"));

System.out.println(removeExtension("a.b\\c"));
System.out.println(removeExtension("a.b\\c.jpg"));
System.out.println(removeExtension("a.b\\c.jpg.jpg"));

System.out.println(removeExtension("c"));
System.out.println(removeExtension("c.jpg"));
System.out.println(removeExtension("c.jpg.jpg"));

Kết quả là:

c
c
c.jpg
c
c
c.jpg
c
c
c.jpg

Kết quả là kết quả mong muốn được nêu trong thử nghiệm mà phương pháp cần thực hiện.


4
Câu trả lời chính xác. Có một lý do cụ thể tại sao bạn sử dụng System.getProperty("file.separator")và không chỉ File.separator?
halirusan

2
Một lời cảnh báo: Giải pháp này cũng loại bỏ đường dẫn trước, không chỉ phần mở rộng, không giống như phương thức IO Commons IO.
DHa

3
Có vẻ như điều này sẽ thất bại cho/path/to/.htaccess
Kuzeko

17

BTW, trong trường hợp của tôi, khi tôi muốn một giải pháp nhanh chóng để loại bỏ một phần mở rộng cụ thể, đây là khoảng những gì tôi đã làm:

  if (filename.endsWith(ext))
    return filename.substring(0,filename.length() - ext.length());
  else
    return filename;

16
String foo = "title part1.txt";
foo = foo.substring(0, foo.lastIndexOf('.'));

4
Không, có thể có nhiều hơn một '.'; bạn muốn Last IndexOf ('.')
Adam Jaskiewicz

-1 vì không sử dụng phương pháp tôi nghĩ bạn đang sử dụng. Đó là tổng cộng +0 từ tôi. Thay đổi nó nhanh chóng! ;)
Michael Myers

7
String fileName="foo.bar";
int dotIndex=fileName.lastIndexOf('.');
if(dotIndex>=0) { // to prevent exception if there is no dot
  fileName=fileName.substring(0,dotIndex);
}

Đây có phải là một câu hỏi lừa? : p

Tôi không thể nghĩ ra một cách nhanh hơn atm.


7

Sử dụng một phương thức trong com.google.common.io.Fileslớp nếu dự án của bạn đã phụ thuộc vào thư viện lõi của Google. Phương pháp bạn cần là getNameWithoutExtension.


Tại sao ai đó chống lại câu trả lời của tôi ??
Toby

Lưu ý rằng điều này chỉ trả về tên cơ sở, do đó, đường dẫn cũng bị xóa: google.github.io/guava/release/19.0/api/docs/com/google/common/ trộm
thSoft

6

bạn có thể thử chức năng này, rất cơ bản

public String getWithoutExtension(String fileFullPath){
    return fileFullPath.substring(0, fileFullPath.lastIndexOf('.'));
}

5

Tôi thấy câu trả lời của coolbird đặc biệt hữu ích.

Nhưng tôi đã thay đổi báo cáo kết quả cuối cùng thành:

if (extensionIndex == -1)
  return s;

return s.substring(0, lastSeparatorIndex+1) 
         + filename.substring(0, extensionIndex);

như tôi muốn tên đường dẫn đầy đủ được trả về.

Vì vậy, "C: \ Users \ mroh004.COM \ Documents \ Test \ Test.xml" trở thành 
   "C: \ Users \ mroh004.COM \ Documents \ Test \ Test" và không
   "Kiểm tra"

5
filename.substring(filename.lastIndexOf('.'), filename.length()).toLowerCase();

3
Đối diện với những gì đã được hỏi và không cần phải vượt qua độ dài, chỉ cần sử dụng một chuỗi con arg

4

Sử dụng một regex. Cái này thay thế dấu chấm cuối cùng, và mọi thứ sau nó.

String baseName = fileName.replaceAll("\\.[^.]*$", "");

Bạn cũng có thể tạo một đối tượng Mẫu nếu bạn muốn biên dịch trước biểu thức chính quy.


1
String[] splitted = fileName.split(".");
String fileNameWithoutExtension = fileName.replace("." + splitted[splitted.length - 1], "");

Cần phải phân chia "\\."thành "." là đặc biệt cho regex.
La bàn

1

tạo một tệp mới với đường dẫn hình ảnh chuỗi

String imagePath;
File test = new File(imagePath);
test.getName();
test.getPath();
getExtension(test.getName());


public static String getExtension(String uri) {
        if (uri == null) {
            return null;
        }

        int dot = uri.lastIndexOf(".");
        if (dot >= 0) {
            return uri.substring(dot);
        } else {
            // No extension.
            return "";
        }
    }

1

org.apache.commons.io.FilenameUtils phiên bản 2.4 cho câu trả lời sau

public static String removeExtension(String filename) {
    if (filename == null) {
        return null;
    }
    int index = indexOfExtension(filename);
    if (index == -1) {
        return filename;
    } else {
        return filename.substring(0, index);
    }
}

public static int indexOfExtension(String filename) {
    if (filename == null) {
        return -1;
    }
    int extensionPos = filename.lastIndexOf(EXTENSION_SEPARATOR);
    int lastSeparator = indexOfLastSeparator(filename);
    return lastSeparator > extensionPos ? -1 : extensionPos;
}

public static int indexOfLastSeparator(String filename) {
    if (filename == null) {
        return -1;
    }
    int lastUnixPos = filename.lastIndexOf(UNIX_SEPARATOR);
    int lastWindowsPos = filename.lastIndexOf(WINDOWS_SEPARATOR);
    return Math.max(lastUnixPos, lastWindowsPos);
}

public static final char EXTENSION_SEPARATOR = '.';
private static final char UNIX_SEPARATOR = '/';
private static final char WINDOWS_SEPARATOR = '\\';

1
 private String trimFileExtension(String fileName)
  {
     String[] splits = fileName.split( "\\." );
     return StringUtils.remove( fileName, "." + splits[splits.length - 1] );
  }

0

Tôi sẽ làm như thế này:

String title_part = "title part1.txt";
int i;
for(i=title_part.length()-1 ; i>=0 && title_part.charAt(i)!='.' ; i--);
title_part = title_part.substring(0,i);

Bắt đầu từ cuối cho đến khi '.' sau đó gọi chuỗi con.

Chỉnh sửa: Có thể không phải là một golf nhưng nó hiệu quả :)


7
Về cơ bản, đó là những gì Last IndexOf vẫn làm; Tại sao phải phát minh lại bánh xe?
Michael Myers

Cho vui và để một chút mô tả. chỉ vậy thôi. (và tôi đã quên về Last IndexOf khi tôi đang viết bài này)
fmsf

0

Hãy ghi nhớ các tình huống không có phần mở rộng tệp hoặc có nhiều phần mở rộng tệp

ví dụ Tên tệp: tệp | file.txt | file.tar.bz2

/**
 *
 * @param fileName
 * @return file extension
 * example file.fastq.gz => fastq.gz
 */
private String extractFileExtension(String fileName) {
    String type = "undefined";
    if (FilenameUtils.indexOfExtension(fileName) != -1) {
        String fileBaseName = FilenameUtils.getBaseName(fileName);
        int indexOfExtension = -1;
        while (fileBaseName.contains(".")) {
            indexOfExtension = FilenameUtils.indexOfExtension(fileBaseName);
            fileBaseName = FilenameUtils.getBaseName(fileBaseName);
        }
        type = fileName.substring(indexOfExtension + 1, fileName.length());
    }
    return type;
}

0
String img = "example.jpg";
// String imgLink = "http://www.example.com/example.jpg";
URI uri = null;

try {
    uri = new URI(img);
    String[] segments = uri.getPath().split("/");
    System.out.println(segments[segments.length-1].split("\\.")[0]);
} catch (Exception e) {
    e.printStackTrace();
}

Điều này sẽ xuất ví dụ cho cả imgimgLink


0
public static String removeExtension(String file) {
    if(file != null && file.length() > 0) {
        while(file.contains(".")) {
            file = file.substring(0, file.lastIndexOf('.'));
        }
    }
    return file;
}

Điều này sẽ chuyển đổi "a.jpg.jpg" thành "a" thay vì (chính xác) "a.jpg". Mục đích gì phục vụ file.length() > 0kiểm tra?
Klaus Gütter

Câu hỏi chính là "làm thế nào để loại bỏ phần mở rộng?", Vì vậy, có biến đổi "a.txt.zip" thành "a" và ".htaccess" thành trống rỗng. Hàm này hoạt động với Chuỗi, vì vậy tên tệp có thể không rỗng nhưng vẫn có thể có độ dài 0, kiểm tra nhanh hơn nếu nó có giá trị trước khi phân tích cú pháp biểu tượng. Trân trọng.
Alexey
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.