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 "";
}
}このメソッドは、引数として1つの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などのサードパーティーライブラリを使えば、より簡単にファイルの種類を取得できます。特殊なファイル形式については、独自のファイル型検出器を実装することで、正確に判別できます。
ファイル形式の取得に適した方法は、具体的な利用場面と要件によって異なります。実際の開発では、ファイルの特徴と要件に応じて最適な判定方法を選び、拡張性と互換性も考慮します。