No desenvolvimento em Java, é comum precisar identificar o tipo de um arquivo. Por exemplo, em uma funcionalidade de upload, é necessário verificar se o arquivo enviado pelo usuário corresponde ao tipo exigido. Este artigo apresentará em detalhes métodos para obter o tipo de arquivo usando Java.
I、Identificar o tipo de arquivo pela extensão
A maneira mais comum de identificar o tipo de um arquivo é pela extensão do nome. No sistema operacional, a maioria dos arquivos tem uma extensão específica; por exemplo, a extensão dos arquivos de texto costuma ser .txt,a extensão dos arquivos de imagem geralmente é.jpg ou.png e assim por diante.
Obter a extensão de um arquivo por meio de um programa Java é muito simples, basta usar String da classe substring basta usar o método, conforme o código a seguir:
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 "";
}
}Esse método recebe um File objeto como parâmetro e, em seguida, usar lastIndexOf para encontrar a posição do último ponto no nome do arquivo, ou seja, o início da extensão, e então usar substring o método obtém a string da extensão do arquivo e a retorna. Se o arquivo não tiver extensão, retorna uma string vazia.
É possível testar esse método com o código a seguir:
File file = new File("C:/path/to/file.txt");
String extension = getFileExtension(file);
System.out.println(extension);O resultado da execução é:
txt
Usar esse método para identificar o tipo de arquivo oferece as seguintes vantagens:
Simples de usar, com implementação de código concisa.
Funciona para a grande maioria dos arquivos, pois a grande maioria deles tem uma extensão.
No entanto, esse método também apresenta algumas desvantagens:
A extensão do arquivo pode ter sido alterada, fazendo com que o resultado da identificação seja incorreto.
Alguns arquivos não têm sufixo, como arquivos executáveis sem extensão.
Para identificar o tipo de arquivo com mais precisão, podemos também verificar seus bytes de assinatura.

II、Identificar o tipo de arquivo usando números mágicos
O número mágico de um arquivo é uma sequência de bytes específicos entre os primeiros bytes do arquivo, usada para identificar seu tipo. Ao reconhecer esse número mágico, podemos determinar com precisão o tipo do arquivo, sem a interferência da extensão do nome.
Em Java, é possível obter o número mágico de um arquivo lendo seus dados binários.
2.1 Leitura dos dados binários do arquivo
Podemos usar FileInputStream para ler os dados binários do arquivo com essa classe. O método abaixo retorna um array de bytes contendo os dados binários do arquivo:
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();
}
}
}O método acima utilizou FileInputStream para abrir o arquivo, ler os dados e armazená-los em um vetor de bytes. Observe que, após concluir a leitura do arquivo, é necessário chamar close método para fechar o fluxo do arquivo e liberar recursos do sistema.
2.2 Usar o número mágico do arquivo para identificar seu tipo
Com os dados binários do arquivo, podemos identificar seu tipo. Cada tipo de arquivo tem um número mágico específico, que permite identificá-lo. A seguir estão os números mágicos de alguns tipos comuns de arquivo e os respectivos métodos de identificação:
O número mágico dos arquivos de texto(.txt)é
EF BB BF(arquivos codificados em UTF-8 têm essa sequência de bytes no início), é possível verificar usando o seguinte método:public static boolean isTextFile(byte[] data) { if (data.length >= 3 && data[0] == -17 && data[1] == -69 && data[2] == -65) { return true; } return false; }O número mágico das imagens JPEG (.jpg) é
FF D8 FF,é possível usar os seguintes métodos para verificar:public static boolean isJPEGFile(byte[] data) { if (data.length >= 3 && data[0] == -1 && data[1] == -40 && data[2] == -1) { return true; } return false; }A assinatura das imagens PNG (.png) é
89 50 4E 47 0D 0A 1A 0A,é possível usar os seguintes métodos para verificar: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; }
Conforme necessário, é possível adicionar mais tipos de arquivo e os métodos correspondentes de verificação de números mágicos.
2.3 Exemplo completo
A seguir, um exemplo completo que demonstra como usar os números mágicos dos arquivos para identificar seu tipo:
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;
}
}O código de exemplo acima identifica o tipo de arquivo pelo seu número mágico e exibe o resultado correspondente.
III、Usar bibliotecas de terceiros para identificar o tipo de arquivo
Além dos métodos acima, também é possível usar bibliotecas de terceiros para identificar o tipo de arquivo. Há algumas bibliotecas de código aberto para Java que nos ajudam a obter o tipo de arquivo com mais facilidade.
3.1 Tika
Tika é um projeto da Apache Software Foundation que oferece uma biblioteca Java de código aberto para analisar diversos formatos de arquivo, incluindo texto, imagem, áudio, vídeo e outros. Com o Tika, é possível extrair metadados dos arquivos, incluindo o tipo de arquivo.
Primeiro, é necessário adicionar a dependência da biblioteca Tika. Se você usa Maven para compilar o projeto, pode, em pom.xml adicione as seguintes dependências ao arquivo:
<dependency> <groupId>org.apache.tika</groupId> <artifactId>tika-core</artifactId> <version>1.27</version> </dependency>
Em seguida, você pode usar o código abaixo para obter o tipo do arquivo:
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();
}
}
}Ao executar o código acima, será exibido o tipo do arquivo.
O Tika utiliza vários métodos para identificar tipos de arquivo, incluindo a extensão e os números mágicos. Ele também oferece suporte a detectores personalizados, permitindo adicionar regras próprias de identificação de tipos de arquivo conforme a necessidade.
3.2 FileTypeDetector
Java oferece uma API padrão para detectar tipos de arquivo, que é FileTypeDetector interface e ProbeContentType classe. Ao implementar essa interface, é possível personalizar um detector de tipos de arquivo.
A seguir, um exemplo de detector personalizado de tipos de arquivo:
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 "";
}
}
}Neste exemplo, determinamos o tipo de arquivo pela sua extensão e retornamos o tipo MIME correspondente.
Para usar um detector personalizado de tipos de arquivo, adicione o código a seguir ao ponto de entrada do programa:
File file = new File("C:/path/to/file.jpg");
Path path = file.toPath();
String fileType = Files.probeContentType(path);
System.out.println("File type: " + fileType);Ao executar o código acima, será exibido o tipo do arquivo.
Observe que, para alguns tipos especiais de arquivo, como executáveis sem extensão, esse método baseado na extensão pode não ser suficientemente preciso. Por isso, é mais recomendável usar o método baseado nos números mágicos dos arquivos apresentado anteriormente.
IV、Conclusão
Este artigo apresentou várias formas de identificar o tipo de arquivo em Java. É possível determiná-lo pela extensão ou pelos números mágicos do arquivo. Bibliotecas de terceiros, como Tika, facilitam essa identificação. Para tipos de arquivo específicos, é possível implementar um detector personalizado para identificá-los com precisão.
A escolha do método adequado para identificar o tipo de arquivo depende do cenário de aplicação e das necessidades específicas. No desenvolvimento prático, escolha o método de identificação mais apropriado conforme as características do arquivo e os requisitos, considerando também a extensibilidade e a compatibilidade.