socket - java在流全部关闭的情况下,删除硬盘中文件会报错?

查看:141
本文介绍了socket - java在流全部关闭的情况下,删除硬盘中文件会报错?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问 题



import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URL;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.UUID;

import org.apache.commons.io.FileUtils;

public class MD5Util {
    private static final String dir = "D:\\";
    

    protected static char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
    protected static MessageDigest messagedigest = null;
    static {
        try {
            messagedigest = MessageDigest.getInstance("MD5");
        } catch (NoSuchAlgorithmException nsaex) {
            System.err.println(MD5Util.class.getName() + "初始化失败,MessageDigest不支持MD5Util。");
            nsaex.printStackTrace();
        }
    }
    
    public static String getFileMD5String(File file) throws IOException {
        FileInputStream in = null;
        try {
            in = new FileInputStream(file);
            FileChannel ch = in.getChannel();
            MappedByteBuffer byteBuffer = ch.map(FileChannel.MapMode.READ_ONLY, 0, file.length());
            messagedigest.update(byteBuffer);
        } finally {
        in.close();
        }
        return bufferToHex(messagedigest.digest());
    }

    public static String getMD5String(String s) {
        return getMD5String(s.getBytes());
    }

    public static String getMD5String(byte[] bytes) {
        messagedigest.update(bytes);
        return bufferToHex(messagedigest.digest());
    }

    private static String bufferToHex(byte bytes[]) {
        return bufferToHex(bytes, 0, bytes.length);
    }

    private static String bufferToHex(byte bytes[], int m, int n) {
        StringBuffer stringbuffer = new StringBuffer(2 * n);
        int k = m + n;
        for (int l = m; l < k; l++) {
            appendHexPair(bytes[l], stringbuffer);
        }
        return stringbuffer.toString();
    }

    private static void appendHexPair(byte bt, StringBuffer stringbuffer) {
        char c0 = hexDigits[(bt & 0xf0) >> 4];
        char c1 = hexDigits[bt & 0xf];
        stringbuffer.append(c0);
        stringbuffer.append(c1);
    }

    public static boolean checkPassword(String password, String md5PwdStr) {
        String s = getMD5String(password);
        return s.equals(md5PwdStr);
    }

    // 下载文件
    public static String downloadFromUrl(String url) {
        try {
            URL httpurl = new URL(url);
            String fileName = getFileNameFromUrl(url);
            File f = new File(dir + fileName);
            f.createNewFile();
            FileUtils.copyURLToFile(httpurl, f);
        } catch (Exception e) {
            e.printStackTrace();
            return "Fault!";
        }
        return getFileNameFromUrl(url);
    }
    //生成文件名
    public static String getFileNameFromUrl(String url) {
        String name = new Long(System.currentTimeMillis()).toString() + ".xml";
        int index = url.lastIndexOf("/");
        if (index > 0) {
            name = url.substring(index + 1);
            if (name.trim().length() > 0) {
                return name;
            }
        }
        return name;
    }

    // 删除文件
    public static void delete(String document) throws IOException {
        File f = new File(dir + document); 
        System.out.println(f.toPath());
        if (f.isFile() && f.exists()){
            java.nio.file.Files.delete(f.toPath());
            System.out.println("OK");
        }
    }

    /*
     * 字符串转MD5
     */
    private static String toMD5(String parameter) {
        try {
            // 拿到一个MD5转换器(如果想要SHA1参数换成SHA1)
            MessageDigest messageDigest = MessageDigest.getInstance("MD5");
            // 输入的字符串转换成字节数组
            byte[] inputByteArray = parameter.getBytes();
            // inputByteArray是输入字符串转换得到的字节数组
            messageDigest.update(inputByteArray);
            // 转换并返回结果,也是字节数组,包含16个元素
            byte[] resultByteArray = messageDigest.digest();
            // 字符数组转换成字符串返回
            return byteArrayToHex(resultByteArray);
        } catch (NoSuchAlgorithmException e) {
            
            return null;
        }
    }

    /*
     * 字节转换字符串
     */
    private static String byteArrayToHex(byte[] byteArray) {
        // 首先初始化一个字符数组,用来存放每个16进制字符
        char[] hexDigits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
        // new一个字符数组,这个就是用来组成结果字符串的(解释一下:一个byte是八位二进制,也就是2位十六进制字符(2的8次方等于16的2次方))
        char[] resultCharArray = new char[byteArray.length * 2];
        // 遍历字节数组,通过位运算(位运算效率高),转换成字符放到字符数组中去
        int index = 0;
        for (byte b : byteArray) {
            resultCharArray[index++] = hexDigits[b >>> 4 & 0xf];
            resultCharArray[index++] = hexDigits[b & 0xf];
        }
        // 字符数组组合成字符串返回
        return new String(resultCharArray);
    }

    /**
     * 根据图片生成新MD5
     */
    public static String picToMD5(String url) {
        String document = downloadFromUrl(url);// 下载文件
        File big = new File(dir + document);// 获取电脑中文件位置
        String documentMD5 = null;
        String uuidMD5 = null;
        try {
            documentMD5 = getFileMD5String(big);// 读取文件MD5
            uuidMD5 = toMD5(UUID.randomUUID().toString());// 生成uuidMD5
        /*    System.out.println(documentMD5+"MD5");
            System.out.println(uuidMD5+"uuid");*/
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                delete(document);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }// 删除文件
        }
        return toMD5(documentMD5 + uuidMD5);//组合新的MD5
    }
    
    
    public static void main(String[] args) {
        String picToMD5 = picToMD5("http://www.itxxz.com/uploads/allimg/150116/1-15011611055M56.png");
        System.out.println(picToMD5);
    }
}

D:1-15011611055M56.png
java.nio.file.FileSystemException: D:1-15011611055M56.png: 另一个程序正在使用此文件,进程无法访问。

at sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:86)
at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:97)
at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:102)
at sun.nio.fs.WindowsFileSystemProvider.implDelete(WindowsFileSystemProvider.java:269)
at sun.nio.fs.AbstractFileSystemProvider.delete(AbstractFileSystemProvider.java:103)
at java.nio.file.Files.delete(Files.java:1077)
at com.yuewuxian.beer.lid.util.MD5Util.delete(MD5Util.java:109)
at com.yuewuxian.beer.lid.util.MD5Util.picToMD5(MD5Util.java:170)
at com.yuewuxian.beer.lid.util.MD5Util.main(MD5Util.java:181)

E43839A85087B623EA97E47508F19076
这个util是下载文件获取md5然后拼装成新的md5,但是永远没法删除硬盘中的源文件,请问是什么情况?唯一的inputstream也关闭了为何还是无法删除?

解决方案

内存映射文件操作完内存以后,还持有文件的句柄,所以如果你需要删除的话就是失败的。
具体可以参照:
How to unmap a file from memory mapped using FileChannel in java?
关于MappedByteBuffer资源释放问题

按照文章说的加上

  public static void clean(final Object buffer) throws Exception {
         AccessController.doPrivileged(new PrivilegedAction() {
             public Object run() {
             try {
                Method getCleanerMethod = buffer.getClass().getMethod("cleaner",new Class[0]);
                getCleanerMethod.setAccessible(true);
                sun.misc.Cleaner cleaner =(sun.misc.Cleaner)getCleanerMethod.invoke(buffer,new Object[0]);
                cleaner.clean();
             } catch(Exception e) {
                e.printStackTrace();
             }
                return null;}});
         
}

或者

public static void unmap(MappedByteBuffer buffer)
{
   sun.misc.Cleaner cleaner = ((DirectBuffer) buffer).cleaner();
   cleaner.clean();
}

都是可以解决的

这篇关于socket - java在流全部关闭的情况下,删除硬盘中文件会报错?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆