java 基礎之圖片的多執行緒處理和大檔案的多執行緒拷貝

hogen發表於2017-12-29

圖片的多執行緒處理

public class PhotoHandle {
    public static void main(String[] args) {
        File file = new File("D:\\photo.bmp");
        photoHandle(file, 4);//把檔案分成4個執行緒來處理
    }
    public static void photoHandle(File file, int threadNumber) {
        long length = file.length();
        long unitLength = length/threadNumber;//把圖片長度按執行緒數等分
        for(int i=0; i<threadNumber; i++){
            long begin = 54;//圖片一開始都不從零開始的
            long end = length;
            if (i != 0){
                begin = unitLength*i;
            }
            if(i!=threadNumber-1){
                end = unitLength*(i+1)-1;
            }
            String name = "執行緒"+i;
            MyThread myThreads = new MyThread(name, file, begin, end);
            new Thread(myThreads).start();
            System.out.println(name + "已開啟");
        }
    }
}
複製程式碼

MyThread類

public class MyThread implements Runnable {
    private String name;//執行緒名
    private File file;//檔名
    private long begin;//起始位置
    private long end;//讀取的結束位置
    public MyThread(String name, File file, long begin, long end) {
        this.name = name;
        this.file = file;
        this.begin = begin;
        this.end = end;
    }

    @Override
    public void run() {
        RandomAccessFile raf = null;
        try {
            raf = new RandomAccessFile(file, "rw");
            raf.seek(begin);// raf指標定位到最開始
            while (begin <= end) {//還沒到最後,則繼續
                int i = 255 - raf.read();
                raf.seek(raf.getFilePointer() - 1);// 或raf.seek(begin)
                raf.write(i);
                begin++;
            }
            System.out.println(name + "拷貝完成!");
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            IOUtils.closeRandomAccessFile(raf);
        }
    }
}
複製程式碼

多執行緒分段示意圖如下

多執行緒分割示意圖

此圖同樣適用於下例的檔案拷貝

(大)檔案的的多執行緒拷貝

public class MultiThreadCopy{
    public static void main(String[] args) {
        File sourceFile = new File("E:\\javaIO\\myeclipse.exe");//原始檔地址
        File targetDir = new File("e:/javaFile");//目標檔案地址
        int threadNumber = 4;
        copyFile(sourceFile, targetDir, threadNumber);
    }

    public static void copyFile(File sourceFile, File targetDir, int threadNumber) {
        // TODO Auto-generated method stub
        if(!targetDir.exists()){
            targetDir.mkdirs();
        }
        File targetFile = new File(targetDir, sourceFile.getName());
        long length = sourceFile.length();
        long unitLength = length/threadNumber;
        for(int i=0; i<threadNumber; i++){
            long begin = 0;
            long end = length;
            if(i!=0){
                begin = unitLength*i;
            }
            if(i!=threadNumber-1){
                end = unitLength*(i+1)-1;
            }
            String name = "執行緒"+i;
            new MyThread(name, sourceFile, targetFile, begin, end).start();
            System.out.println(name+"啟動完成!");
        }
    }
}
複製程式碼

MyThread類

public class MyThread extends Thread{
    private String name;
    private File sourceFile;
    private File targetDir;
    private long begin;
    private long end;
    public MyThread(String name, File sourceFile, File targetDir, long begin, long end) {
        this.name = name;
        this.sourceFile = sourceFile;
        this.targetDir = targetDir;
        this.begin = begin;
        this.end = end;
    }
    @Override
    public void run() {
        //定義讀寫的檔案訪問流
        RandomAccessFile rafRead = null;
        RandomAccessFile rafWrite = null;
        try {
            rafRead = new RandomAccessFile(sourceFile, "r");
            rafWrite = new RandomAccessFile(targetDir, "rw");
            //設定檔案指標的開始位置和檔案長度
            rafWrite.setLength(end);
            rafRead.seek(begin);
            rafWrite.seek(begin);
            int buffSize = 1024*6;
            byte[] buff = new byte[buffSize];
            while((begin+buffSize)<=end){
                //把資料讀入到buff緩衝陣列中
                rafRead.read(buff);
                //把buff緩衝陣列的資料寫入到目標檔案
                rafWrite.write(buff);
                //起始位置再向前移
                begin+=buffSize;
            }
            //begin+buffSize超出了每一段的結尾,最後那一撮另外讀
            long lastSize = end-begin;
            rafRead.read(buff, 0, (int) lastSize);
            rafWrite.write(buff, 0, (int) lastSize);
            System.out.println(this.name+"拷貝完成!");
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally{
            IOUtils.closeRandomAccessFile(rafRead);
            IOUtils.closeRandomAccessFile(rafWrite);
        }
    }
}
複製程式碼

IOUtils工具類

public class IOUtils {
    public static void closeInputStream(InputStream is){//傳入的是具體的子類
        if (is != null){
            try {
                is.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            is = null;
        }
    }
    public static void closeOutputStream(OutputStream os){
        if (os != null){
            try {
                os.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            os = null;
        }
    }
    public static void closeReader(Reader reader){
        if (reader != null){
            try {
                reader.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            reader = null;
        }
    }
    public static void closeWriter(Writer writer){
        if (writer != null){
            try {
                writer.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            writer = null;
        }
    }
    public static void closeRandomAccessFile(RandomAccessFile raf){
        if (raf != null){
            try {
                raf.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            raf = null;
        }
    }
}複製程式碼

相關文章