我编写了一个像这样的方法。但我想这应该进行重构。 任何人都可以建议避免使用这多个if语句的最佳方法吗?
private String getMimeType(String fileName){
if(fileName == null) {
return "";
}
if(fileName.endsWith(".pdf")) {
return "application/pdf";
}
if(fileName.endsWith(".doc")) {
return "application/msword";
}
if(fileName.endsWith(".xls")) {
return "application/vnd.ms-excel";
}
if(fileName.endsWith(".xlw")) {
return "application/vnd.ms-excel";
}
if(fileName.endsWith(".ppt")) {
return "application/vnd.ms-powerpoint";
}
if(fileName.endsWith(".mdb")) {
return "application/x-msaccess";
}
if(fileName.endsWith(".rtf")) {
return "application/rtf";
}
if(fileName.endsWith(".txt")) {
return "txt/plain";
}
if(fileName.endsWith(".htm") || fileName.endsWith(".html")) {
return "txt/html";
}
return "txt/plain";
}
我不能在这里使用switch-case,因为我的'条件'是java.lang.String
。
答案 0 :(得分:34)
您可以使用Map
来解决问题:
Map<String,String> extensionToMimeType = new HashMap<String,String>();
extensionToMimeType.put("pdf", "application/pdf");
extensionToMimeType.put("doc", "application/msword");
// and the rest
int lastDot = fileName.lastIndexOf(".");
String mimeType;
if (lastDot==-1) {
mimeType = NO_EXTENSION_MIME_TYPE;
} else {
String extension = fileName.substring(lastDot+1);
mimeType = extensionToMimeType.get(extension);
if (mimeType == null) {
mimeType = UNKNOWN_EXTENSION_MIME_TYPE;
}
}
要使此代码有效,您需要在课堂上定义NO_EXTENSION_MIME_TYPE
和UNKNOWN_EXTENSION_MIME_TYPE
,有点像这样:
private static final String NO_EXTENSION_MIME_TYPE = "application/octet-stream";
private static final String UNKNOWN_EXTENSION_MIME_TYPE = "text/plain";
答案 1 :(得分:11)
或许使用HashMap?
这样你就可以myMap.get(mystr);
答案 2 :(得分:4)
我个人对if语句没有问题。代码是可读的,只需几毫秒即可理解您正在做的事情。无论如何,这是一个私有方法,如果mime类型列表是静态的,那么就没有迫切需要将映射移动到属性文件并使用查找表(map)。 Map会减少代码行,但要理解代码,那么你就不得不阅读代码和映射的实现 - 无论是静态初始化器还是外部文件。
您可以稍微更改代码并使用枚举:
private enum FileExtension { NONE, DEFAULT, PDF, DOC, XLS /* ... */ }
private String getMimeType(String fileName){
String mimeType = null;
FileExtension fileNameExtension = getFileNameExtension(fileName);
switch(fileNameExtension) {
case NONE:
return "";
case PDF:
return "application/pdf";
// ...
case DEFAULT:
return "txt/plain";
}
throw new RuntimeException("Unhandled FileExtension detected");
}
getFileNameExtension(String fileName)
方法只返回fileName的拟合枚举值,FileExtension.NONE
如果fileName为空(或null?)和FileExtension.DEFAULT
,如果文件扩展名未映射到a哑剧型。
答案 3 :(得分:4)
使用 MIME检测库呢?
(随意添加更多,有这么多的库..)
答案 4 :(得分:2)
我认为你的方法是最好的整体。在我自己测试了许多不同的方法之后。
我认为您当前的方法有很多好处,即:
无论如何,我可以提出一些建议:
pdf=application/pdf doc=application/msword
你可以得到一个非常相似的结果:
public static String getMimeType(String fileName){
if(fileName == null) return "";
if(fileName.endsWith(".pdf")) return "application/pdf";
if(fileName.endsWith(".doc")) return "application/msword";
if(fileName.endsWith(".xls")) return "application/vnd.ms-excel";
return "txt/plain";
}
这也是许多基于地图的实现的样子。
答案 5 :(得分:2)
命令模式是要走的路。以下是使用java 8的一个示例:
<强> 1。定义界面:
public interface ExtensionHandler {
boolean isMatched(String fileName);
String handle(String fileName);
}
<强> 2。使用每个扩展程序实现界面:
public class PdfHandler implements ExtensionHandler {
@Override
public boolean isMatched(String fileName) {
return fileName.endsWith(".pdf");
}
@Override
public String handle(String fileName) {
return "application/pdf";
}
}
和
public class TxtHandler implements ExtensionHandler {
@Override public boolean isMatched(String fileName) {
return fileName.endsWith(".txt");
}
@Override public String handle(String fileName) {
return "txt/plain";
}
}
依旧.....
第3。定义客户端:
public class MimeTypeGetter {
private List<ExtensionHandler> extensionHandlers;
private ExtensionHandler plainTextHandler;
public MimeTypeGetter() {
extensionHandlers = new ArrayList<>();
extensionHandlers.add(new PdfHandler());
extensionHandlers.add(new DocHandler());
extensionHandlers.add(new XlsHandler());
// and so on
plainTextHandler = new PlainTextHandler();
extensionHandlers.add(plainTextHandler);
}
public String getMimeType(String fileExtension) {
return extensionHandlers.stream()
.filter(handler -> handler.isMatched(fileExtension))
.findFirst()
.orElse(plainTextHandler)
.handle(fileExtension);
}
}
<强> 4。这是样本结果:
public static void main(String[] args) {
MimeTypeGetter mimeTypeGetter = new MimeTypeGetter();
System.out.println(mimeTypeGetter.getMimeType("test.pdf")); // application/pdf
System.out.println(mimeTypeGetter.getMimeType("hello.txt")); // txt/plain
System.out.println(mimeTypeGetter.getMimeType("my presentation.ppt")); // "application/vnd.ms-powerpoint"
}
答案 6 :(得分:1)
总的来说,没有办法逃避这种情况。在你的情况下 - 如果有一组允许的扩展名 - 你可以创建一个枚举,通过valueOf()将扩展名转换为枚举类型,然后你可以切换你的枚举。
答案 7 :(得分:1)
我会通过将关联放在地图中,然后使用地图进行查找来完成此操作:
Map<String, String> map = new HashMap<String, String>();
map.put(".pdf", "application/pdf");
map.put(".doc", "application/msword");
// ... etc.
// For lookup:
private String getMimeType(String fileName) {
if (fileName == null || fileName.length() < 4) {
return null;
}
return map.get(fileName.substring(fileName.length() - 4));
}
请注意,在字符串上使用switch
语句是下一版Java的新功能之一;有关更多详细信息,请参阅this page以及Java 7中的外观示例:
switch (fileName.substring(fileName.length() - 4)) {
case ".pdf": return "application/pdf";
case ".doc": return "application/msword";
// ...
default: return null;
(编辑:我的解决方案假定文件扩展名总是3个字母;如果它可以更长或更短,则必须稍微更改它。)
答案 8 :(得分:1)
这个特定问题的最简单和最简单的方法是使用内置的Java SE或EE方法。
在“普通的vanilla”客户端应用程序中(从底层平台获取此信息):
String mimeType = URLConnection.guessContentTypeFromName(filename);
或者在JSP / Servlet Web应用程序中(从web.xml
文件中获取此信息):
String mimeType = getServletContext().getMimeType(filename);
答案 9 :(得分:0)
你总是可以在这里使用Groovy类,因为它允许在字符串上使用switch-case:)
答案 10 :(得分:0)
如何将扩展名映射到MIME类型,然后使用循环?类似的东西:
Map<String,String> suffixMappings = new HashMap<String,String>();
suffixMappings.put(".pdf", "application/pdf");
...
private String getMimeType(String fileName){
if (fileName == null) {
return "";
}
String suffix = fileName.substring(fileName.lastIndexOf('.'));
// If fileName might not have extension, check for that above!
String mimeType = suffixMappings.get(suffix);
return mimeType == null ? "text/plain" : mimeType;
}
答案 11 :(得分:0)
创建一个名为MimeType的枚举,其中包含2个String变量:extension和type。创建一个适当的构造函数并传入“.xxx”和“application / xxx”值。创建一个方法来执行查找。您可以在开关中使用枚举。
答案 12 :(得分:0)
提一下:直接等同于你的代码不会使用地图进行直接查找(因为这需要每个扩展名正好有3个字符),而是for循环:
...
Map<String, String> extmap = GetExtensionMap();
for (Map.Entry<String,String> entry: extmap.entrySet())
if (fileName.endsWith(entry.getKey))
return entry.getValue();
...
此解决方案适用于任何长度的扩展,但当然不如哈希查找(并且性能略低于原始解决方案)
Algorithmic-Design-Guy解决方案
更高效的方法是实现从扩展的 last 字符开始的树结构,并在相应的节点上存储适当的MIME类型。 然后,您可以从文件名的最后一个字符开始向下走树。但这可能是一种矫枉过正......