终极FileUtils

使用Commons IO进行文件操作

FileUtils Api 

http://commons.apache.org/proper/commons-io/javadocs/api-release/index.html?overview-summary.html

1 第三方jar导入

    implementation 'commons-io:commons-io:2.6'

2 使用(对于我来说主要操作 IOUtils,FileUtils)

import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;

import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        String msg = "123";
        String path = Environment.getExternalStorageDirectory() + File.separator + "aaa" + File.separator + "aaaa.txt";
        File file = new File(path);
        try {
            IOUtils.toInputStream(msg,Charset.defaultCharset());
            FileUtils.writeStringToFile(file, msg, Charset.defaultCharset());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

<think>我们正在分析用户提供的代码片段:ClassLoaderclassLoader= FileUtils.class.getClassLoader();URL resourceUrl =classLoader.getResource("Fonts/simhei.ttf");simheiFontPath= URLDecoder.decode(resourceUrl.getFile(),StandardCharsets.UTF_8.toString()); 根据引用[2]和引用[4]的提示,使用`URL.getFile()`并解码的方式获取资源路径存在以下问题:1.当路径中包含空格、特殊字符(如%,#等)或中文时,URL会进行编码(如空格变成%20),解码后可能不完全还原(例如+号会被解码成空格)。2.如果路径中含有+号,解码后变成空格,导致路径错误。3.即使使用`URLDecoder.decode`,也不能保证所有字符都被正确还原。此外,引用[3]指出:`ClassLoader.getResource`方法参数不支持以"/"开头,否则返回null。用户代码中路径为`"Fonts/simhei.ttf"`(没有以"/"开头),这是正确的。但是,更根本的问题是:当资源位于JAR包内时,通过URL解码得到的字符串(如`file:/path/to/jar!/Fonts/simhei.ttf`)并不是文件系统中的有效路径,无法用`File`或`FileInputStream`直接访问(引用[2]提到类似问题)。因此,用户代码存在两个层面的问题: 1.路径解码可能不完整(特殊字符问题)。 2.即使解码成功,得到的路径可能不是有效的文件系统路径(当资源在JAR包内时)。解决方案: 1.推荐使用资源流(`getResourceAsStream`)直接加载字体,避免使用文件路径。2.如果必须使用文件路径(如某些API要求文件路径),则应将资源复制到临时文件,然后使用临时文件的路径。根据引用[2]的第三种解决方法,也可以尝试使用`toURI()`的方式,但同样需要处理资源在JAR包内的情况(因为JAR包内的资源URI是`jar:file:...`格式,不能直接作为文件路径使用)。 结论:用户当前的写法存在潜在问题,特别是在资源包含特殊字符或中文,以及资源打包在JAR内时。改进建议:1.使用资源流加载字体(推荐)。2.如果必须使用文件路径,则创建临时文件。下面给出两种改进方案:</think>### 深入分析 `ClassLoader.getResource()` 获取字体路径的问题 您提供的代码存在 **三个关键风险点**,尤其在处理字体文件时需特别注意: ```java ClassLoader classLoader = FileUtils.class.getClassLoader(); URL resourceUrl = classLoader.getResource("Fonts/simhei.ttf"); simheiFontPath = URLDecoder.decode(resourceUrl.getFile(), StandardCharsets.UTF_8.toString()); // 存在隐患 ``` #### 🔥 核心问题解析 1. **特殊字符解码缺陷** `URLDecoder.decode()` 无法正确处理所有特殊字符: - `+` 会被错误转换为空格(如 `file+name.ttf` → `file name.ttf`)[^2] - `%23` (#) 等编码字符可能无法完全还原[^4] - 中文路径在 Windows 系统可能仍显示乱码 2. **JAR 内资源路径无效** 当资源打包在 JAR 中时,`getFile()` 返回伪路径: `jar:file:/app.jar!/Fonts/simhei.ttf` → **这不是真实文件路径**,无法直接用于 `File` 操作[^2] 3. **空指针风险** 若资源不存在,`classLoader.getResource()` 返回 `null`,导致: ```java resourceUrl.getFile() // NullPointerException ``` #### ✅ 改进方案(四层防御) ##### 方案1:直接使用资源流(推荐首选⭐) ```java try (InputStream fontStream = getClass().getResourceAsStream("/Fonts/simhei.ttf")) { if (fontStream == null) throw new FileNotFoundException("字体文件缺失"); Font font = Font.createFont(Font.TRUETYPE_FONT, fontStream); GraphicsEnvironment.getLocalGraphicsEnvironment().registerFont(font); } ``` > ✅ 优点:完全避开路径问题,支持 JAR 包 > ⚠️ 注意:路径需加前缀 `/`(表示 classpath 根目录)[^3] ##### 方案2:URI 安全解码(需文件路径时) ```java URL resourceUrl = getClass().getResource("/Fonts/simhei.ttf"); if(resourceUrl == null) throw new FileNotFoundException(); // 使用 URI 代替 URL 解码 Path fontPath = Paths.get(resourceUrl.toURI()); Font font = Font.createFont(Font.TRUETYPE_FONT, fontPath.toFile()); ``` > 💡 原理:`toURI()` 自动处理编码问题,避免手动解码错误[^2] ##### 方案3:临时文件桥接(兼容第三方库) ```java try (InputStream in = getClass().getResourceAsStream("/Fonts/simhei.ttf")) { Path tempFile = Files.createTempFile("font_", ".ttf"); Files.copy(in, tempFile, StandardCopyOption.REPLACE_EXISTING); // 获得真实文件路径 String validPath = tempFile.toAbsolutePath().toString(); // 使用后删除: tempFile.toFile().deleteOnExit(); } ``` ##### 方案4:防御性解码(特殊情况) ```java String rawPath = resourceUrl.getFile(); // 处理特殊编码 String decodedPath = URLDecoder.decode(rawPath, "UTF-8") .replace("+", "%2B") // 保护+号 .replace("%20", " "); // 可选空格还原 // 但!JAR内路径仍无效:需判断是否包含"!/" if(decodedPath.contains("!/")) { throw new IllegalStateException("资源在JAR包内,不能直接获取路径"); } ``` #### 📊 路径处理方案对比 | 方法 | 特殊字符支持 | JAR内资源 | 易用性 | 推荐度 | |---------------------|-------------|-----------|--------|--------| | 直接使用资源流 | ✅ 完美 | ✅ 支持 | ⭐⭐⭐⭐ | 首选 | | URI 转换 | ✅ 自动处理 | ❌ 失败 | ⭐⭐⭐ | 次选 | | 临时文件 | ✅ 完美 | ✅ 支持 | ⭐⭐ | 兼容库 | | URLDecoder 解码 | ❌ 部分失败 | ❌ 失败 | ⭐ | 不推荐 | #### ⚠️ 关键验证点 1. **资源存在性检查** ```java // 必须前置检查! if(classLoader.getResource("Fonts/simhei.ttf") == null) { throw new FileNotFoundException("字体文件未找到"); } ``` 2. **路径格式验证** ```java System.out.println("原始URL路径: " + resourceUrl); // 输出示例:jar:file:/app.jar!/Fonts/simhei.ttf (说明在JAR内) ``` 3. **字符集显式指定** ```java // 避免平台依赖 URLDecoder.decode(..., StandardCharsets.UTF_8.name()) // 显式声明UTF-8 ``` > **终极建议**:优先采用资源流方案,这是处理 JAR 内字体资源的 **唯一可靠方式**[^2][^4]。若必须获取路径,临时文件方案是次优解。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值