在Java開發中,經常會遇到需要判斷檔案類型的情況,例如在檔案上傳功能中需要判斷使用者上傳的檔案是否符合要求的類型。本文將詳細介紹如何使用Java取得檔案類型的方法。
一、使用副檔名判斷檔案類型
最常見的判斷檔案類型的方法是根據檔案的副檔名來判斷。大部分檔案在作業系統中都有一個特定的副檔名,比如文字檔案的副檔名通常是.txt,圖片檔案的副檔名通常是.jpg或.png等等。
透過Java程式取得檔案的副檔名非常簡單,只需使用String類別的substring方法即可,程式碼如下所示:
public static String getFileExtension(File file) {
String fileName = file.getName();
if (fileName.lastIndexOf(".") != -1 && fileName.lastIndexOf(".") != 0) {
return fileName.substring(fileName.lastIndexOf(".") + 1);
} else {
return "";
}
}該方法接收一個File物件作為參數,然後使用lastIndexOf方法找到檔案名稱中最後一個點的位置,即副檔名的起始位置,然後使用substring方法取得副檔名字串並回傳。如果檔案沒有副檔名,則回傳空字串。
可以透過以下程式碼來測試這個方法:
File file = new File("C:/path/to/file.txt");
String extension = getFileExtension(file);
System.out.println(extension);執行結果為:
txt
使用這種方法判斷檔案類型有以下優點:
簡單易用,程式碼實作簡潔。
對絕大多數檔案有效,因為絕大多數檔案都有副檔名。
然而,這種方法也存在一些缺點:
檔案的副檔名有可能被修改,導致判斷的結果錯誤。
有些檔案沒有副檔名,例如沒有副檔名的執行檔。
為了更準確地判斷檔案類型,我們可以結合檔案的魔術數字進行判斷。

二、使用檔案魔數判斷檔案類型
檔案魔數是檔案開頭幾個位元組中的一些特定位元組,用來識別檔案類型。透過識別檔案魔數,我們可以準確地判斷檔案的類型,不受副檔名的干擾。
在Java中,可以透過讀取檔案的二進位資料,取得檔案的魔數。
2.1 讀取檔案二進位資料
我們可以使用FileInputStream類別來讀取檔案的二進位資料。下面的方法會傳回一個位元組陣列,包含了檔案的二進位資料:
public static byte[] readFileToByteArray(File file) throws IOException {
FileInputStream fis = null;
try {
fis = new FileInputStream(file);
byte[] data = new byte[(int)file.length()];
fis.read(data);
return data;
} finally {
if (fis != null) {
fis.close();
}
}
}以上方法使用了FileInputStream來開啟檔案,讀取資料,並將資料儲存到一個位元組陣列中。請注意,在完成檔案讀取後,需要呼叫close方法關閉檔案串流,以釋放系統資源。
2.2 使用檔案魔術數字判斷檔案類型
有了檔案的二進位資料,我們就可以判斷檔案類型了。對於每種檔案類型,都有一個特定的魔術數字,根據這個魔術數字就可以判斷檔案的類型。以下是一些常見檔案類型的魔術數字以及對應的判斷方法:
文字檔(.txt)魔術數字為
EF BB BF(UTF-8編碼的檔案開頭有這個位元組序列),可以使用以下方法判斷:public static boolean isTextFile(byte[] data) { if (data.length >= 3 && data[0] == -17 && data[1] == -69 && data[2] == -65) { return true; } return false; }JPEG圖片(.jpg)魔術數字為
FF D8 FF,可以使用以下方法判斷:public static boolean isJPEGFile(byte[] data) { if (data.length >= 3 && data[0] == -1 && data[1] == -40 && data[2] == -1) { return true; } return false; }PNG圖片(.png)魔術數字為
89 50 4E 47 0D 0A 1A 0A,可以使用以下方法判斷:public static boolean isPNGFile(byte[] data) { if (data.length >= 8 && data[0] == -119 && data[1] == 80 && data[2] == 78 && data[3] == 71 && data[4] == 13 && data[5] == 10 && data[6] == 26 && data[7] == 10) { return true; } return false; }
根據需要,可以新增更多的檔案類型和對應的魔術數字判斷方法。
2.3 完整範例
下面是一個完整的範例,示範如何使用檔案魔數來判斷檔案類型:
import java.io.File;import java.io.FileInputStream;import java.io.IOException;public class FileTypeChecker {
public static void main(String[] args) {
File file = new File("C:/path/to/file.jpg");
try {
byte[] data = readFileToByteArray(file);
if (isJPEGFile(data)) {
System.out.println("This is a JPEG file.");
} else if (isPNGFile(data)) {
System.out.println("This is a PNG file.");
} else if (isTextFile(data)) {
System.out.println("This is a text file.");
} else {
System.out.println("Unknown file type.");
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static byte[] readFileToByteArray(File file) throws IOException {
FileInputStream fis = null;
try {
fis = new FileInputStream(file);
byte[] data = new byte[(int)file.length()];
fis.read(data);
return data;
} finally {
if (fis != null) {
fis.close();
}
}
}
public static boolean isTextFile(byte[] data) {
if (data.length >= 3 && data[0] == -17 && data[1] == -69 && data[2] == -65) {
return true;
}
return false;
}
public static boolean isJPEGFile(byte[] data) {
if (data.length >= 3 && data[0] == -1 && data[1] == -40 && data[2] == -1) {
return true;
}
return false;
}
public static boolean isPNGFile(byte[] data) {
if (data.length >= 8 && data[0] == -119 && data[1] == 80 && data[2] == 78 && data[3] == 71 &&
data[4] == 13 && data[5] == 10 && data[6] == 26 && data[7] == 10) {
return true;
}
return false;
}
}以上範例程式碼會根據檔案的魔術數字判斷檔案類型,並輸出對應的結果。
三、使用第三方函式庫判斷檔案類型
除了上述方法,還可以使用第三方函式庫來判斷檔案類型。Java 中有一些開源的第三方函式庫可以幫助我們更方便地取得檔案類型。
3.1 Tika
Tika 是 Apache Software Foundation 的一個專案,它提供了一個開源的 Java 程式庫,用於解析各種檔案格式,包括文字、影像、音訊、影片等。使用 Tika 可以擷取檔案的中繼資料,包括檔案類型。
首先,需要引入 Tika 程式庫的相依套件。如果使用 Maven 建置專案,可以在 pom.xml 檔案中新增以下相依套件:
<dependency> <groupId>org.apache.tika</groupId> <artifactId>tika-core</artifactId> <version>1.27</version> </dependency>
然後,可以使用以下程式碼來取得檔案的類型:
import org.apache.tika.Tika;
public class FileTypeChecker {
public static void main(String[] args) {
Tika tika = new Tika();
try {
File file = new File("C:/path/to/file.jpg");
String fileType = tika.detect(file);
System.out.println("File type: " + fileType);
} catch (IOException e) {
e.printStackTrace();
}
}
}執行以上程式碼,將輸出檔案的類型。
Tika 使用了各種方法來識別檔案類型,包括副檔名、魔術數字等。它還支援自訂的偵測器,可以根據需要新增自訂的檔案類型判斷規則。
3.2 FileTypeDetector
Java提供了一個標準的API進行檔案類型偵測,即FileTypeDetector介面和ProbeContentType類別。透過實作這個介面,可以自訂檔案類型偵測器。
以下是一個自訂的檔案類型偵測器範例:
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.spi.FileTypeDetector;
public class CustomFileTypeDetector extends FileTypeDetector {
@Override
public String probeContentType(Path path) throws IOException {
String extension = getFileExtension(path.toFile());
if ("txt".equals(extension)) {
return "text/plain";
} else if ("jpg".equals(extension) || "jpeg".equals(extension)) {
return "image/jpeg";
} else if ("png".equals(extension)) {
return "image/png";
} else {
return null;
}
}
private String getFileExtension(File file) {
String fileName = file.getName();
if (fileName.lastIndexOf(".") != -1 && fileName.lastIndexOf(".") != 0) {
return fileName.substring(fileName.lastIndexOf(".") + 1);
} else {
return "";
}
}
}在這個範例中,我們根據檔案的副檔名判斷檔案類型,並回傳相應的 MIME 類型。
為了使用自訂的檔案類型偵測器,請將以下程式碼新增至程式的進入點:
File file = new File("C:/path/to/file.jpg");
Path path = file.toPath();
String fileType = Files.probeContentType(path);
System.out.println("File type: " + fileType);執行以上程式碼,將輸出檔案的類型。
請注意,對於一些特殊的檔案類型,比如不帶副檔名的可執行檔,這種基於副檔名的方法可能不夠準確,因此更建議使用前面介紹的基於檔案魔術數字的方法。
四、總結
本文介紹了在Java中取得檔案類型的幾種方法。可以透過檔案的副檔名判斷檔案類型,也可以透過檔案的魔術數字判斷檔案類型。使用第三方函式庫如Tika可以更方便地取得檔案類型。對於特殊的檔案類型,可以透過自訂檔案類型偵測器來實現精確的判斷。
選擇合適的方法來取得檔案類型取決於具體的應用情境和需求。在實際開發中,根據檔案的特點和需求來選擇最合適的判斷方法,並考量可擴充性和相容性。