`
javaboy2006
  • 浏览: 183020 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

多路归并排序

阅读更多
package merge;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;

/**
 * 
 * 外部排序指的是大文件的排序,即待排序的记录存储在外存储器上,待排序的文件无法一次装入内存,
 * 需要在内存和外部存储器之间进行多次数据交换,以达到排序整个文件的目的。
 * 外部排序最常用的算法是多路归并排序,即将原文件分解成多个能够一次性装人内存的部分,
 * 分别把每一部分调入内存完成排序。然后,对已经排序的子文件进行归并排序。
 * 一般来说外排序分为两个步骤:预处理和合并排序。即首先根据内存的大小,将有n个记录的磁盘文件分批读入内存,采用有效的内存排序方法进行排序,将其预处理为若干个有序的子文件,这些有序子文件就是初始顺串,然后采用合并的方法将这些初始顺串逐趟合并成一个有序文件。
 * 
 * @author jia.hej
 *
 * @version $Id: MergeSort.java, v 0.1 2009-8-7 下午03:53:51 jia.hej Exp $
 */
public class MergeSort {

    /** 十 */
    private static long   TEN              = 10;
    /** 百 */
    private static long   HUNDRED          = 100;
    /** 千 */
    private static long   THOUSAND         = 1000;
    /** 万 */
    private static long   MILLION          = 10000;                 //1078  00:00:01 078
    /** 十万 */
    private static long   TEN_MILLION      = 100000;                //9656  00:00:09 656
    /** 百万 */
    private static long   HUNDRED_MILLION  = 1000000;               //93733  00:01:33 733
    /** 千万 */
    private static long   THOUSAND_MILLION = 10000000;              //970144  00:16:10 144
    /** 亿 */
    private static long   BILLION          = 100000000;
    /** 十亿 */
    private static long   TEN_BILLION      = 1000000000;
    /** 百亿 */
    private static long   HUNDRED_BILLION  = 10000000000l;
    /** 千亿 */
    private static long   THOUSAND_BILLION = 100000000000l;

    private static String INPUT_FILE       = "c:\\test\\input.txt";

    private static String OUTPUT_FILE      = "c:\\test\\output.txt";

    /** 拆分大小 */
    private static int    SPLIT_SIZE       = 10 * 10000;

    private static int    numSize;

    public static void main(String[] args) throws Exception {
        createDir("c:\\test");
        createFile(INPUT_FILE);
        numSize = createRandomNum(THOUSAND_MILLION);

        sortFile(INPUT_FILE);

        long beginTime = System.currentTimeMillis();
        System.out.println("begin=" + beginTime);

        //拆分文件
        splitFile(INPUT_FILE, numSize);

        List<String> splitFilePathList = new ArrayList<String>();
        File dir = new File("c:\\test\\temp");
        File[] files = dir.listFiles();
        for (int i = 0; i < files.length; i++) {
            File file = files[i];
            splitFilePathList.add(file.getAbsolutePath());
        }
        //合并文件
        createFile(OUTPUT_FILE);
        mergeFile(splitFilePathList, OUTPUT_FILE);

        long endTime = System.currentTimeMillis();
        System.out.println("end=" + endTime);
        System.out.println("end-begin=" + (endTime - beginTime));
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
        System.out.println(simpleDateFormat.format(endTime - beginTime));

        //删除拆分文件
        System.gc();
        Runtime.getRuntime().exec(new String[] { "cmd", "/c", "del", "c:\\test\\temp\\*.txt" });
    }

    private static void sortFile(String path) throws Exception {
        SortedSet<Integer> set = new TreeSet<Integer>();
        File file = new File(path);
        FileReader fileReader = new FileReader(file);
        BufferedReader bufferedReader = new BufferedReader(fileReader);
        String value;
        while ((value = bufferedReader.readLine()) != null) {
            set.add(Integer.parseInt(value));
        }
        bufferedReader.close();
        fileReader.close();
        createFile("c:\\test\\input排序.txt");
        writeFile("c:\\test\\input排序.txt", set, false);
    }

    /**
     * 拆分文件
     * 
     * @param inputPath
     * @param numSize
     * @throws Exception
     */
    private static void splitFile(String inputPath, int numSize) throws Exception {
        File file = new File(inputPath);
        FileReader fileReader = new FileReader(file);
        BufferedReader bufferedReader = new BufferedReader(fileReader);
        SortedSet<Integer> set = new TreeSet<Integer>();
        String str;
        createDir("c:\\test\\temp");
        if (numSize > SPLIT_SIZE) {
            int count = 1;
            int fileNum = 1;
            while ((str = bufferedReader.readLine()) != null) {
                set.add(Integer.parseInt(str));
                //超过拆分数,写入子文件
                if (count >= SPLIT_SIZE) {
                    createFile("c:\\test\\temp\\" + fileNum + ".txt");
                    writeFile("c:\\test\\temp\\" + fileNum + ".txt", set, false);
                    set.clear();
                    count = 0;
                    fileNum++;
                }
                count++;//读取文件当前行数
            }
        }
        //总量未达到拆分数,写入子文件
        else {
            while ((str = bufferedReader.readLine()) != null) {
                set.add(Integer.parseInt(str));
            }
            createFile("c:\\test\\temp\\1.txt");
            writeFile("c:\\test\\temp\\1.txt", set, false);
        }
        if (bufferedReader != null) {
            bufferedReader.close();
        }
        if (fileReader != null) {
            fileReader.close();
        }
    }

    /**
     * 合并文件
     * 
     * <p>
     *    1.txt(1、3、5、7、9)和2.txt(6、8、9)<br/>
     *    首先1和6进入treeset。 <br/>
     *    输出1,发现是来自于1.txt的,再读入3,此时set中的元素是6和3。<br/> 
     *    输出3,发现还是来自于1.txt的,再读入5,此时set中的元素是6和5。 <br/>
     *    输出5,发现还是来自于1.txt的,再读入7,此时set中的元素是6和7。 <br/>
     *    输出6,发现来自于2.txt的,读入8,此时set中的元素是8和7。 <br/>
     *    输出7,发现来自于1.txt的,读入9,此时set中的元素是8和9。 <br/>
     *    输出8,发现来自于2.txt的,无法再读入9,此时set中的元素是9。<br/>
     *    输出9。
     * </p>
     * 
     * @param splitFilePathList
     * @param outputPath
     * @throws Exception
     */
    private static void mergeFile(List<String> splitFilePathList, String outputPath)
                                                                                    throws Exception {
        //fileInfo添加到set
        SortedSet<FileInfo> fileInfoSet = new TreeSet<FileInfo>(new FileInfoComparator());
        if (fileInfoSet.isEmpty()) {
            for (int i = 0; i < splitFilePathList.size(); i++) {
                File file = new File(splitFilePathList.get(i));
                FileReader fileReader = new FileReader(file);
                BufferedReader bufferedReader = new BufferedReader(fileReader);

                FileInfo fileInfo = new FileInfo();
                String splitFilePath = splitFilePathList.get(i);
                fileInfo.setFileNum(Integer.parseInt(splitFilePath.substring(splitFilePath
                    .lastIndexOf("\\") + 1, splitFilePath.indexOf(".txt"))));//文件号
                fileInfo.setReader(bufferedReader);//reader引用
                String value = bufferedReader.readLine();
                if (value != null) {
                    fileInfo.setValue(value);//当前值
                    fileInfo.setLineNum(fileInfo.getLineNum() + 1);//当前行号
                    fileInfoSet.add(fileInfo);
                }
            }
        }

        Set<Integer> valueSet = new LinkedHashSet<Integer>();
        boolean isSplit = false;
        int count = 1;
        //输出set元素
        while (!fileInfoSet.isEmpty()) {
            FileInfo currentFileInfo = fileInfoSet.first();
            valueSet.add(Integer.parseInt(currentFileInfo.getValue()));
            //拆分批量写入文件
            if (valueSet.size() >= SPLIT_SIZE) {
                writeFile(outputPath, valueSet, true);
                valueSet.clear();
                isSplit = true;
            }

            //clone fileInfo
            FileInfo nextFileInfo = new FileInfo();
            nextFileInfo.setFileNum(currentFileInfo.getFileNum());
            nextFileInfo.setLineNum(currentFileInfo.getLineNum());
            nextFileInfo.setValue(currentFileInfo.getValue());
            nextFileInfo.setReader(currentFileInfo.getReader());

            boolean isSuccess = nextFileInfo.readNextValue();

            //未到文件末尾,set中fileInfo重新排序
            if (isSuccess) {
                if (fileInfoSet.remove(currentFileInfo)) {
                    fileInfoSet.add(nextFileInfo);
                }
            }
            //已到文件末尾,从set中移除该fileInfo
            else {
                fileInfoSet.remove(currentFileInfo);
            }

            System.out.println("----- MergeFile:" + count++ + " -----");
            System.out.println("fileNum=" + currentFileInfo.getFileNum());
            System.out.println("lineNum=" + currentFileInfo.getLineNum());
            System.out.println("value=" + currentFileInfo.getValue());
            System.out.println("----------------------------");
        }

        //从未拆分过则一次性写入文件
        if (valueSet.size() > 0 && valueSet.size() < SPLIT_SIZE && !isSplit) {
            writeFile(outputPath, valueSet, false);
        }
        //曾拆分过剩余部分写入文件
        else if (valueSet.size() > 0 && valueSet.size() < SPLIT_SIZE && isSplit) {
            writeFile(outputPath, valueSet, true);
        }
    }

    /**
     * 生成随机数
     * 
     * @param numSize
     * @return
     * @throws Exception
     */
    private static int createRandomNum(long numSize) throws Exception {
        Set<Integer> set = new LinkedHashSet<Integer>();
        int count = 0;
        boolean isSplit = false;
        while (count < numSize) {
            int num = (int) (Math.random() * numSize + 1);
            if (set.add(num)) {
                count++;
            }
            //拆分批量写入文件
            if (set.size() >= SPLIT_SIZE) {
                writeFile(INPUT_FILE, set, true);
                set.clear();
                isSplit = true;
            }
        }

        //从未拆分过则一次写入文件
        if (set.size() > 0 && set.size() < SPLIT_SIZE && !isSplit) {
            writeFile(INPUT_FILE, set, false);
        }
        //曾拆分过剩余部分写入文件
        else if (set.size() > 0 && set.size() < SPLIT_SIZE && isSplit) {
            writeFile(INPUT_FILE, set, true);
        }
        return count;
    }

    private static void createDir(String dirPath) {
        File dir = new File(dirPath);
        if (!dir.exists()) {
            if (dir.mkdir()) {
                System.out.println(dir.getName() + " is create.");
            }
        }
    }

    private static void createFile(String path) throws Exception {
        File file = new File(path);
        if (!file.exists()) {
            if (file.createNewFile()) {
                System.out.println(file.getName() + " is create.");
            }
        }
    }

    private static void writeFile(String path, Set<Integer> set, boolean isAppend) throws Exception {
        File file = new File(path);
        FileWriter fileWriter = new FileWriter(file, isAppend);// 第二个参数表示:是否为追加模
        BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
        Iterator<Integer> iterator = set.iterator();
        while (iterator.hasNext()) {
            bufferedWriter.write(iterator.next().toString());
            bufferedWriter.newLine();
        }
        bufferedWriter.flush();
        if (bufferedWriter != null) {
            bufferedWriter.close();
        }
        if (fileWriter != null) {
            fileWriter.close();
        }
    }
}

package merge;

import java.io.BufferedReader;

/**
 * 
 * 文件信息
 * 
 * @author jia.hej
 *
 * @version $Id: FileInfo.java, v 0.1 2009-8-1 上午02:11:30 jia.hej Exp $
 */
public class FileInfo {

    /**
     * 文件号
     */
    private int            fileNum;

    /**
     * 当前行号
     */
    private int            lineNum = 0;

    /**
     * 当前值
     */
    private String         value;

    /**
     * BufferedReader引用
     */
    private BufferedReader reader;

    public boolean readNextValue() throws Exception {
        String value;
        if ((value = this.reader.readLine()) != null) {
            this.value = value;
            this.lineNum++;
            return true;
        } else {
            this.reader.close();
            return false;
        }
    }

    public int getFileNum() {
        return fileNum;
    }

    public void setFileNum(int fileNum) {
        this.fileNum = fileNum;
    }

    public int getLineNum() {
        return lineNum;
    }

    public void setLineNum(int lineNum) {
        this.lineNum = lineNum;
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

    public BufferedReader getReader() {
        return reader;
    }

    public void setReader(BufferedReader reader) {
        this.reader = reader;
    }
}

package merge;

import java.util.Comparator;

/**
 * 
 * 文件比较器
 * 
 * @author jia.hej
 *
 * @version $Id: FileInfoComparator.java, v 0.1 2009-8-7 下午01:42:05 jia.hej Exp $
 */
public class FileInfoComparator implements Comparator<FileInfo> {

    public int compare(FileInfo o1, FileInfo o2) {
        if (Integer.parseInt(o1.getValue()) != Integer.parseInt(o2.getValue())) {
            return Integer.parseInt(o1.getValue()) - Integer.parseInt(o2.getValue());
        }
        //如果存在重复值则使用文件号比较
        else {
            return o1.getFileNum() - o2.getFileNum();
        }
    }

}



重写的第二版
package merge;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;

/**
 * 
 * @author jia.hej
 * @version $Id: MergeSort.java, v 0.1 2017-5-6 上午12:56:01 jia.hej Exp $
 */
public class MergeSort {

    /** 十 */
    private static long   TEN              = 10;
    /** 百 */
    private static long   HUNDRED          = 100;
    /** 千 */
    private static long   THOUSAND         = 1000;
    /** 万 */
    private static long   MILLION          = 10000;                 //1078  00:00:01 078
    /** 十万 */
    private static long   TEN_MILLION      = 100000;                //9656  00:00:09 656
    /** 百万 */
    private static long   HUNDRED_MILLION  = 1000000;               //93733  00:01:33 733
    /** 千万 */
    private static long   THOUSAND_MILLION = 10000000;              //970144  00:16:10 144
    /** 亿 */
    private static long   BILLION          = 100000000;
    /** 十亿 */
    private static long   TEN_BILLION      = 1000000000;
    /** 百亿 */
    private static long   HUNDRED_BILLION  = 10000000000l;
    /** 千亿 */
    private static long   THOUSAND_BILLION = 100000000000l;

    private static String INPUT_FILE       = "c:\\test\\input.txt";

    private static String OUTPUT_FILE      = "c:\\test\\output.txt";

    /** 拆分大小 */
    private static int    SPLIT_SIZE       = 1000;

    public static void main(String[] args) throws Exception {
        createDir("c:\\test");
        createFile(INPUT_FILE);
        int numberSize = createRandomNum(TEN_MILLION);

        long beginTime = System.currentTimeMillis();

        //文件拆分
        splitFile(INPUT_FILE, numberSize);

        createDir("c:\\test\\sort");
        List<String> splitFilePathList = new ArrayList<String>();
        File dir = new File("c:\\test\\temp");
        File[] files = dir.listFiles();
        for (int i = 0; i < files.length; i++) {
            File file = files[i];
            splitFilePathList.add(file.getAbsolutePath());

            //文件排序
            sortFile(file.getAbsolutePath());
        }

        //文件合并
        createFile(OUTPUT_FILE);
        mergeFile(splitFilePathList, OUTPUT_FILE);

        System.out.println("begin=" + beginTime);
        long endTime = System.currentTimeMillis();
        System.out.println("end=" + endTime);
        System.out.println("总耗时=" + ((endTime - beginTime) / 1000) + "s");
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
        System.out.println(simpleDateFormat.format(endTime - beginTime));

        //删除临时拆分文件
        System.gc();
        Runtime.getRuntime().exec(new String[] { "cmd", "/c", "del", "c:\\test\\temp\\*.txt" });
        Runtime.getRuntime().exec(new String[] { "cmd", "/c", "del", "c:\\test\\sort\\*.txt" });
    }

    private static void sortFile(String path) throws Exception {
        SortedSet<Integer> set = new TreeSet<Integer>();
        File file = new File(path);
        FileReader fileReader = new FileReader(file);
        BufferedReader bufferedReader = new BufferedReader(fileReader);
        String value;
        while ((value = bufferedReader.readLine()) != null) {
            set.add(Integer.parseInt(value));
        }
        bufferedReader.close();
        fileReader.close();
        createFile("c:\\test\\sort\\" + file.getName());
        writeFile("c:\\test\\sort\\" + file.getName(), set, false);
    }

    /**
     * 拆分文件
     * 
     * @param inputPath
     * @param numSize
     * @throws Exception
     */
    private static void splitFile(String inputPath, int numberSize) throws Exception {
        File file = new File(inputPath);
        FileReader fileReader = new FileReader(file);
        BufferedReader bufferedReader = new BufferedReader(fileReader);
        SortedSet<Integer> set = new TreeSet<Integer>();
        String str;
        createDir("c:\\test\\temp");

        if (numberSize > SPLIT_SIZE) {
            int count = 1;
            int fileNum = 1;
            while ((str = bufferedReader.readLine()) != null) {
                set.add(Integer.parseInt(str));
                //超过拆分数,写入子文件
                if (count >= SPLIT_SIZE) {
                    createFile("c:\\test\\temp\\" + fileNum + ".txt");
                    writeFile("c:\\test\\temp\\" + fileNum + ".txt", set, false);
                    set.clear();
                    count = 0;
                    fileNum++;
                }
                count++;//读取文件当前行数
            }
        }
        //总量未达到拆分数,写入子文件
        else {
            while ((str = bufferedReader.readLine()) != null) {
                set.add(Integer.parseInt(str));
            }
            createFile("c:\\test\\temp\\1.txt");
            writeFile("c:\\test\\temp\\1.txt", set, false);
        }
        if (bufferedReader != null) {
            bufferedReader.close();
        }
        if (fileReader != null) {
            fileReader.close();
        }
    }

    /**
     * 合并文件
     * 
     * <p>
     *    1.txt(1、3、5、7、9)和2.txt(6、8、9)<br/>
     *    首先1和6进入treeset。 <br/>
     *    输出1,发现是来自于1.txt的,再读入3,此时set中的元素是6和3。<br/> 
     *    输出3,发现还是来自于1.txt的,再读入5,此时set中的元素是6和5。 <br/>
     *    输出5,发现还是来自于1.txt的,再读入7,此时set中的元素是6和7。 <br/>
     *    输出6,发现来自于2.txt的,读入8,此时set中的元素是8和7。 <br/>
     *    输出7,发现来自于1.txt的,读入9,此时set中的元素是8和9。 <br/>
     *    输出8,发现来自于2.txt的,无法再读入9,此时set中的元素是9。<br/>
     *    输出9。
     * </p>
     * 
     * @param splitFilePathList
     * @param outputPath
     * @throws Exception
     */
    private static void mergeFile(List<String> splitFilePathList, String outputPath)
                                                                                    throws Exception {
        //按拆分文件数初始化map
        Map<Integer, FileInfo> valueFileMap = new HashMap<Integer, FileInfo>();
        for (int i = 0; i < splitFilePathList.size(); i++) {
            File file = new File(splitFilePathList.get(i));
            FileReader fileReader = new FileReader(file);
            BufferedReader bufferedReader = new BufferedReader(fileReader);

            FileInfo fileInfo = new FileInfo();
            String splitFilePath = splitFilePathList.get(i);
            fileInfo.setFileNo(Integer.parseInt(splitFilePath.substring(
                splitFilePath.lastIndexOf("\\") + 1, splitFilePath.indexOf(".txt"))));//文件号
            fileInfo.setReader(bufferedReader);//reader引用
            String value = bufferedReader.readLine();
            if (value != null) {
                fileInfo.setCurrentValue(value);//当前值
                fileInfo.setCurrentLineNo(fileInfo.getCurrentLineNo() + 1);//当前行号
                valueFileMap.put(Integer.parseInt(value), fileInfo);
            }
        }

        File outputFile = new File(outputPath);
        FileWriter outputFileWriter = new FileWriter(outputFile, true);// 第二个参数表示:是否为追加模式
        BufferedWriter outputBufferedWriter = new BufferedWriter(outputFileWriter);

        //按文件行号横向遍历
        for (int i = 0; i < splitFilePathList.size() * SPLIT_SIZE; i++) {
            //查找最小值
            Integer minValue = Integer.MAX_VALUE;
            for (Integer currentValue : valueFileMap.keySet()) {
                if (currentValue.intValue() < minValue) {
                    minValue = currentValue.intValue();
                }
            }

            //最小值追加到输出文件
            Set<Integer> tempValueSet = new LinkedHashSet<Integer>();
            tempValueSet.add(minValue);
            writeFile(outputBufferedWriter, tempValueSet);

            //命中FileInfo读指针后移
            FileInfo currentFileInfo = valueFileMap.get(minValue);

            System.out.println("----- MergeFile:" + (i + 1) + " -----");
            System.out.println("fileNo=" + currentFileInfo.getFileNo());
            System.out.println("currentLineNo=" + currentFileInfo.getCurrentLineNo());
            System.out.println("currentValue=" + currentFileInfo.getCurrentValue());
            System.out.println("----------------------------");

            FileInfo nextFileInfo = new FileInfo();
            nextFileInfo.setFileNo(currentFileInfo.getFileNo());
            nextFileInfo.setCurrentLineNo(currentFileInfo.getCurrentLineNo());
            nextFileInfo.setReader(currentFileInfo.getReader());

            valueFileMap.remove(minValue);

            //读指针未到文件尾
            if (nextFileInfo.readNextValue()) {
                valueFileMap.put(Integer.parseInt(nextFileInfo.getCurrentValue()), nextFileInfo);
            } else {
                nextFileInfo.closeReader();
            }
        }

        if (outputBufferedWriter != null) {
            outputBufferedWriter.close();
        }
        if (outputFileWriter != null) {
            outputFileWriter.close();
        }
    }

    /**
     * 生成随机数
     * 
     * @param numberSize
     * @return
     * @throws Exception
     */
    private static int createRandomNum(long numberSize) throws Exception {
        int count = 0;
        Set<Integer> set = new LinkedHashSet<Integer>();

        while (count < numberSize) {
            int num = (int) (Math.random() * numberSize);
            if (set.add(num)) {
                count++;
            }
        }

        writeFile(INPUT_FILE, set, true);
        return count;
    }

    private static void createDir(String dirPath) {
        File dir = new File(dirPath);
        if (dir.exists()) {
            dir.delete();
        }

        if (dir.mkdir()) {
            System.out.println("[" + dir.getName() + " dir is create]");
        }
    }

    private static void createFile(String path) throws Exception {
        File file = new File(path);
        if (file.exists()) {
            file.delete();
        }

        if (file.createNewFile()) {
            System.out.println("[" + file.getName() + " file is create]");
        }
    }

    private static void writeFile(String path, Set<Integer> set, boolean isAppend) throws Exception {
        File file = new File(path);
        FileWriter fileWriter = new FileWriter(file, isAppend);// 第二个参数表示:是否为追加模式
        BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
        Iterator<Integer> iterator = set.iterator();
        while (iterator.hasNext()) {
            bufferedWriter.write(iterator.next().toString());
            bufferedWriter.newLine();
        }
        bufferedWriter.flush();
        if (bufferedWriter != null) {
            bufferedWriter.close();
        }
        if (fileWriter != null) {
            fileWriter.close();
        }
    }

    private static void writeFile(BufferedWriter bufferedWriter, Set<Integer> set) throws Exception {
        Iterator<Integer> iterator = set.iterator();
        while (iterator.hasNext()) {
            bufferedWriter.write(iterator.next().toString());
            bufferedWriter.newLine();
        }
        bufferedWriter.flush();
    }

}

package merge;

import java.io.BufferedReader;
import java.io.IOException;

/**
 * 
 * 文件信息
 * 
 * @author jia.hej
 * @version $Id: FileInfo.java, v 0.1 2017-5-6 上午12:56:01 jia.hej Exp $
 */
public class FileInfo {

    /**
     * 文件号
     */
    private int            fileNo        = 0;

    /**
     * 当前行号
     */
    private int            currentLineNo = 0;

    /**
     * 当前值
     */
    private String         currentValue;

    /**
     * BufferedReader引用
     */
    private BufferedReader reader;

    public boolean readNextValue() throws Exception {
        if (reader == null) {
            return false;
        }

        String value;
        if ((value = this.reader.readLine()) != null) {
            this.currentValue = value;
            this.currentLineNo++;
            return true;
        } else {
            this.reader.close();
            this.reader = null;
            return false;
        }
    }

    public void closeReader() throws IOException {
        if (reader != null) {
            reader.close();
        }
    }

    public int getFileNo() {
        return fileNo;
    }

    public void setFileNo(int fileNo) {
        this.fileNo = fileNo;
    }

    public int getCurrentLineNo() {
        return currentLineNo;
    }

    public void setCurrentLineNo(int currentLineNo) {
        this.currentLineNo = currentLineNo;
    }

    public String getCurrentValue() {
        return currentValue;
    }

    public void setCurrentValue(String currentValue) {
        this.currentValue = currentValue;
    }

    public BufferedReader getReader() {
        return reader;
    }

    public void setReader(BufferedReader reader) {
        this.reader = reader;
    }

}
分享到:
评论

相关推荐

    node-v12.20.1-sunos-x64.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    基于Springboot+Vue的乡政府管理系统-毕业源码案例设计.zip

    网络技术和计算机技术发展至今,已经拥有了深厚的理论基础,并在现实中进行了充分运用,尤其是基于计算机运行的软件更是受到各界的关注。加上现在人们已经步入信息时代,所以对于信息的宣传和管理就很关键。系统化是必要的,设计网上系统不仅会节约人力和管理成本,还会安全保存庞大的数据量,对于信息的维护和检索也不需要花费很多时间,非常的便利。 网上系统是在MySQL中建立数据表保存信息,运用SpringBoot框架和Java语言编写。并按照软件设计开发流程进行设计实现。系统具备友好性且功能完善。 网上系统在让售信息规范化的同时,也能及时通过数据输入的有效性规则检测出错误数据,让数据的录入达到准确性的目的,进而提升数据的可靠性,让系统数据的错误率降至最低。 关键词:vue;MySQL;SpringBoot框架 【引流】 Java、Python、Node.js、Spring Boot、Django、Express、MySQL、PostgreSQL、MongoDB、React、Angular、Vue、Bootstrap、Material-UI、Redis、Docker、Kubernetes

    一名合格的程序猿修炼手册.md

    一名合格的程序猿修炼手册.

    5MHz 函数发生器使用说明书

    5MHz 函数发生器使用说明书

    99- 矿山工业互联网平台解决方案.pptx

    99- 矿山工业互联网平台解决方案.pptx

    基于Python大学生社会实践申报系统的设计与实现带vue前后端分离毕业源码案例设计.zip

    网络技术和计算机技术发展至今,已经拥有了深厚的理论基础,并在现实中进行了充分运用,尤其是基于计算机运行的软件更是受到各界的关注。加上现在人们已经步入信息时代,所以对于信息的宣传和管理就很关键。系统化是必要的,设计网上系统不仅会节约人力和管理成本,还会安全保存庞大的数据量,对于信息的维护和检索也不需要花费很多时间,非常的便利。 网上系统是在MySQL中建立数据表保存信息,运用SpringBoot框架和Java语言编写。并按照软件设计开发流程进行设计实现。系统具备友好性且功能完善。 网上系统在让售信息规范化的同时,也能及时通过数据输入的有效性规则检测出错误数据,让数据的录入达到准确性的目的,进而提升数据的可靠性,让系统数据的错误率降至最低。 关键词:vue;MySQL;SpringBoot框架 【引流】 Java、Python、Node.js、Spring Boot、Django、Express、MySQL、PostgreSQL、MongoDB、React、Angular、Vue、Bootstrap、Material-UI、Redis、Docker、Kubernetes

    工厂工资明细表Excel模版

    基于提供的字段介绍,我们可以设计一个基础的工厂工资明细表Excel模板结构如下: | 序号 | 姓名 | 工种 | 工作天数 | 工时费/天 | 小计(正常工资) | 加班时间 | 加班费率/小时 | 小计(加班工资) | 预借 | 合计(实发工资) | 签字 | 备注 | | ---- | ---- | ---- | -------- | ---------- | -------------- | -------- | -------------- | --------------- | ---- | -------------- | ---- | ---- | | 1 | | | | | | | | | | | | | | 2 | | | | | =D2*C2

    供应链管理 高成本、高库存、重资产的解决方案.rar

    随着市场竞争的不断加剧和客户需求的多样化,传统的供应链管理模式面临着高成本、高库存和重资产等一系列挑战。为了有效应对这些挑战,企业亟需通过数字化转型来重塑供应链管理,实现效率提升和成本降低。本资料《供应链管理:高成本、高库存、重资产的解决方案》提供了针对这些问题的综合性数字化解决方案。在这份精品资料中,读者将了解到如何利用先进的信息技术手段,如大数据、云计算、物联网(IoT)和人工智能(AI),对供应链进行优化。通过实时数据分析,企业能够精准预测市场需求,从而减少过剩库存,降低仓储成本。同时,智能化的供应链协同平台可以加强供应商与制造商之间的合作,提高响应速度和灵活性,缩短产品交付周期。此外,资料还深入探讨了如何通过数字技术实现供应链的可视化管理,使企业能够全面掌握供应链的每一个环节,及时发现并解决问题,避免成本浪费。通过采用轻资产运营模式,企业能够减轻固定资产负担,提高资本使用效率。最终,这份资料不仅为企业提供了一套完整的供应链数字化转型路径,还结合具体案例分析,展示了数字化转型如何在实际操作中带来显著成效,帮助企业在激烈的市场竞争中保持领先地位。重新回答||

    五相感应电机矢量控制模型MATLAB

    适合相关科研人员,新手借鉴啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊

    node-v10.14.0-x64.msi

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    基于STM32F103C8单片机-FLASH读写程序KEIL工程源码.zip

    STM32学习软件编程资料,STM32F103C8单片机经典外设应用设计实例软件源代码,KEIL工程文件,可供学习参考。

    node-v12.22.8-sunos-x64.tar_3.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    node-v12.16.2-sunos-x64.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    菜鸟自制流密码.docx

    菜鸟自制流密码.docx

    基于大数据的房产估价.doc

    基于大数据的房产估价 基于大数据的房产估价是一种利用海量数据和分析技术来评估房地产价值的方法。它通过收集、整合和分析各种与房地产相关的数据,以提供更加准确、全面的房产估价服务。 首先,大数据在房产估价中的应用主要体现在数据收集和处理上。这些数据可能包括不同时间点的房产属性、成交量、成交额、成交时长等,以及消费者线上行为数据和市场交易数据等。这些数据可以来自于多个渠道,如政府部门、房地产机构、互联网平台等。通过对这些数据的收集、清洗、整合和分析,可以更加准确地判断房地产市场的现状和趋势,为房产估价提供有力的数据支持。 其次,基于大数据的房产估价方法还可以结合地理信息系统(GIS)和其他技术工具,对房地产价格进行精细化分析。例如,可以利用GIS系统判断各类城市生活配套设施对房地产价格影响的权重,或者结合消费者行为数据和交易数据,分析目标消费者的核心需求和迫切程度,从而更准确地判断房地产项目的可行性和市场潜力。 此外,基于大数据的房产估价还可以利用机器学习、人工智能等先进技术,构建预测模型,对房地产市场的未来发展进行预测和研判。这些模型可以根据历史数据和趋势,分析各种因素对房地产价格的

    node-v11.6.0-linux-armv7l.tar.gz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    5G网优认证练习题题库.xlsx

    5G通信、网络优化与通信建设

    绘画学习平台微信小程序设计+ssm后端毕业源码案例设计.zip

    网络技术和计算机技术发展至今,已经拥有了深厚的理论基础,并在现实中进行了充分运用,尤其是基于计算机运行的软件更是受到各界的关注。加上现在人们已经步入信息时代,所以对于信息的宣传和管理就很关键。系统化是必要的,设计网上系统不仅会节约人力和管理成本,还会安全保存庞大的数据量,对于信息的维护和检索也不需要花费很多时间,非常的便利。 网上系统是在MySQL中建立数据表保存信息,运用SpringBoot框架和Java语言编写。并按照软件设计开发流程进行设计实现。系统具备友好性且功能完善。 网上系统在让售信息规范化的同时,也能及时通过数据输入的有效性规则检测出错误数据,让数据的录入达到准确性的目的,进而提升数据的可靠性,让系统数据的错误率降至最低。 关键词:vue;MySQL;SpringBoot框架 【引流】 Java、Python、Node.js、Spring Boot、Django、Express、MySQL、PostgreSQL、MongoDB、React、Angular、Vue、Bootstrap、Material-UI、Redis、Docker、Kubernetes

    抛光机-零件图-机械工程图-机械三维3D建模图打包下载.zip

    抛光机_零件图_机械工程图_机械三维3D建模图打包下载.zip

    Cambro 2020 21 产品目录

    Cambro 2020 21 产品目录

Global site tag (gtag.js) - Google Analytics