多线程,读取多个文件并写入新文件

时间:2012-12-21 02:26:08

标签: java multithreading file

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Test6 implements Runnable {

    private File file;
    private int totalNumberOfFiles = 0;
    private static int nextFile = -1;
    private static ArrayList<String> allFilesArrayList = new ArrayList<String>();
    private static ExecutorService executorService = null;

    public Test6(File file) {
        this.file = file;
    }

    private String readFileToString(String fileAddress) {
        FileInputStream stream = null;
        MappedByteBuffer bb = null;
        String stringFromFile = "";
        try {
            stream = new FileInputStream(new File(fileAddress));
            FileChannel fc = stream.getChannel();
            bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
            /* Instead of using default, pass in a decoder. */
            stringFromFile = Charset.defaultCharset().decode(bb).toString();
        } catch (IOException e) {
            System.out.println("readFileToString IOException");
            e.printStackTrace();
        } finally {
            try {
                stream.close();
            } catch (IOException e) {
                System.out.println("readFileToString IOException");
                e.printStackTrace();
            }
        }
        return stringFromFile;
    }

    private void toFile(String message, String fileName) {
        try {
            FileWriter fstream = new FileWriter("C:/Users/Nomi/Desktop/Workspace2/Test6/TestWritten/" + fileName);
            System.out.println("printing to file: ".concat(fileName));
            BufferedWriter out = new BufferedWriter(fstream);
            out.write(message);
            out.close();
        } catch (Exception e) {
            System.out.println("toFile() Exception");
            System.err.println("Error: " + e.getMessage());
        }
    }

//  private void listFilesForFolder(final File fileOrFolder) {
//      String temp = "";
//      if (fileOrFolder.isDirectory()) {
//          for (final File fileEntry : fileOrFolder.listFiles()) {
//              if (fileEntry.isFile()) {
//                  temp = fileEntry.getName();
//                  toFile(readFileToString(temp), "Copy".concat(temp));
//              }
//          }
//      }
//      if (fileOrFolder.isFile()) {
//          temp = fileOrFolder.getName();
//          toFile(readFileToString(temp), "Copy".concat(temp));
//      }
//  }

    public void getAllFilesInArrayList(final File fileOrFolder) {
        String temp = "";
        System.out.println("getAllFilesInArrayList fileOrFolder.getAbsolutePath()" + fileOrFolder.getAbsolutePath());
        if (fileOrFolder.isDirectory()) {
            for (final File fileEntry : fileOrFolder.listFiles()) {
                if (fileEntry.isFile()) {
                    temp = fileEntry.getAbsolutePath();
                    allFilesArrayList.add(temp);
                }
            }
        }
        if (fileOrFolder.isFile()) {
            temp = fileOrFolder.getAbsolutePath();
            allFilesArrayList.add(temp);
        }
        totalNumberOfFiles = allFilesArrayList.size();
        for (int i = 0; i < allFilesArrayList.size(); i++) {
            System.out.println("getAllFilesInArrayList path: " + allFilesArrayList.get(i));
        }
    }

    public synchronized String getNextFile() {
        nextFile++;
        if (nextFile < allFilesArrayList.size()) {
//          File tempFile = new File(allFilesArrayList.get(nextFile));
            return allFilesArrayList.get(nextFile);
        } else {
            return null;
        }
    }

    @Override
    public void run() {
        getAllFilesInArrayList(file);
        executorService = Executors.newFixedThreadPool(allFilesArrayList.size());
        while(nextFile < totalNumberOfFiles)
        {
            String tempGetFile = getNextFile();
            File tempFile = new File(allFilesArrayList.get(nextFile));
            toFile(readFileToString(tempFile.getAbsolutePath()), "Copy".concat(tempFile.getName()));
        }
    }

    public static void main(String[] args) {
        Test6 test6 = new Test6(new File("C:/Users/Nomi/Desktop/Workspace2/Test6/Test Files/"));
        Thread thread = new Thread(test6);
        thread.start();
//      executorService.execute(test6);
//      test6.listFilesForFolder(new File("C:/Users/Nomi/Desktop/Workspace2/Test6/"));
    }
}

这些节目正在做着预期的事情。它进入文件夹,抓取文件,将其读入字符串,然后将内容写入新文件。 我想做这个多线程。如果文件夹有N个文件,我需要N个线程。另外,如果可能的话,我想使用执行程序框架。我认为沿着这条线可以有一种方法:

public synchronized void getAllFilesInArrayList() {
        return nextFile;
    }

所以每个新线程都可以选择下一个文件。 谢谢你的帮助。

错误:

Exception in thread "Thread-0" java.lang.IllegalArgumentException
    at java.util.concurrent.ThreadPoolExecutor.<init>(ThreadPoolExecutor.java:589)
    at java.util.concurrent.ThreadPoolExecutor.<init>(ThreadPoolExecutor.java:480)
    at java.util.concurrent.Executors.newFixedThreadPool(Executors.java:59)
    at Test6.run(Test6.java:112)
    at java.lang.Thread.run(Thread.java:662)

1 个答案:

答案 0 :(得分:2)

首先,您解决问题的方法将导致更多同步和竞争条件的担忧,而不是必要的。保持线程不竞争的简单策略是:

1)让调度程序线程读取目录中的所有文件名。

2)对于每个文件,让调度程序线程产生一个工作线程并交出文件引用

3)让工作线程处理文件

4)确保你的输出文件名有一些合理的命名约定,这样就不会让线程互相覆盖。

至于使用执行程序,ThreadPoolExecutor可能会运行良好。去看看javadoc:http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/ThreadPoolExecutor.html