001/*
002 * JPPF.
003 * Copyright (C) 2005-2019 JPPF Team.
004 * http://www.jppf.org
005 *
006 * Licensed under the Apache License, Version 2.0 (the "License");
007 * you may not use this file except in compliance with the License.
008 * You may obtain a copy of the License at
009 *
010 *   http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018
019package org.jppf.utils;
020
021import java.io.*;
022
023/**
024 * Utility class that splits a text file into smaller ones with the same number of lines.
025 * @author Laurent Cohen
026 */
027public class TexFileSplitter {
028  /**
029   * A map of the specified options and their values.
030   */
031  private static final TypedProperties props = new TypedProperties();
032
033  /**
034   * Split the input text files into output text files according to the specified options.
035   * @param args specifies the options in the format -<option1> <value1> ... -<optionN> <valueN>.
036   */
037  public static void main(final String[] args) {
038    try {
039      processArguments(args);
040      final File file = new File(props.getString("inputFile"));
041      int lines = 0;
042      String s = "";
043      try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
044        while (s != null) {
045          s = reader.readLine();
046          if (s != null) lines++;
047        }
048      }
049      System.out.println("counted " + lines  + " lines");
050      try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
051        final int nbFiles = props.getInt("nbFiles");
052        final int n = lines/nbFiles;
053        for (int i=0; i<nbFiles; i++) {
054          final int nb = (i < nbFiles - 1) ? n : lines - (nbFiles - 1)*n;
055          s = "";
056          final File out = new File(props.getString("outputDir") + '/' + props.getString("prefix") + '-' + i + props.getString("extension"));
057          FileUtils.mkdirs(out);
058          try (final BufferedWriter writer = new BufferedWriter(new FileWriter(out))) {
059            for (int j=0; j<nb && s != null; j++) {
060              s = reader.readLine();
061              if (s != null) writer.write(s + '\n');
062            }
063            writer.flush();
064          }
065          System.out.println("created file '" + out.getName() + '\'');
066        }
067      }
068      System.out.println("wrote all files");
069    } catch (final Exception e) {
070      System.out.println(e.getMessage());
071      displayOptions();
072    }
073  }
074
075  /**
076   * Process the command-line options
077   * @param args contains the specified options and their value.
078   * @throws Exception if any error occurs while parsing the options.
079   */
080  private static void processArguments(final String...args) throws Exception {
081    if ((args == null) || (args.length < 1)) throw new Exception("you must specify at least the input file (-i option)");
082    int i = 0;
083    while (i <args.length) {
084      final String s = args[i++];
085      if (StringUtils.isOneOf(s, false, "-?", "-h", "-help")) throw new Exception("\nFile splitter help");
086      else if ("-i".equals(s)) props.setProperty("inputFile", args[i++]);
087      else if ("-o".equals(s)) props.setProperty("outputDir", args[i++]);
088      else if ("-n".equals(s)) props.setProperty("nbFiles", args[i++]);
089      else if ("-p".equals(s)) props.setProperty("prefix", args[i++]);
090      else if ("-e".equals(s)) props.setProperty("extension", args[i++]);
091    }
092    if (props.getString("inputFile", null) == null) throw new Exception("missing mandatory '-i' option");
093    if (props.getString("outputDir", null) == null) props.setProperty("outputDir", new File(props.getString("inputFile")).getParentFile().getName());
094    if (props.getString("nbFiles", null) == null) props.setProperty("nbFiles", "10");
095    if (props.getString("prefix", null) == null) props.setProperty("prefix", "part");
096    if (props.getString("extension", null) == null) props.setProperty("extension", ".txt");
097  }
098
099  /**
100   * Display the list of options and their meaning.
101   */
102  public static void displayOptions() {
103    //System.out.println("\nFile splitter help");
104    System.out.println("command-line format: java -cp <classpath> org.jppf.utils.FileSplitter -option_1 value_1 ... -option_n value_n");
105    System.out.println("Available options:");
106    System.out.println("  -i input_file             : the path to the text file to split");
107    System.out.println("  -o output_dir             : the output directory where to create the resulting files");
108    System.out.println("                              no value means same directory as input file");
109    System.out.println("  -n nb_files               : number of files to split the input into");
110    System.out.println("                              if not specified, 10 is used");
111    System.out.println("  -p output_files_prefix    : prefix for the resulting files names");
112    System.out.println("  -e output_files_extension : extension for the resulting files names");
113    System.out.println("  -?, -h, -help             : display this help screen (all other options are ignored)");
114    System.out.println("Examples:");
115    System.out.println("java -cp <classpath> org.jppf.utils.FileSplitter -i logfile.txt -o ./split -n 5 -p split-log -e .log");
116    System.out.println("splits the file logfile.txt into 5, resulting files will be split-log-0.log ... split-log-5.log in folder ./split");
117    System.out.println("java -cp <classpath> org.jppf.utils.FileSplitter -i logfile.txt");
118    System.out.println("splits the file logfile.log into 10, resulting files will be part-0.txt ... part-9.txt in the same folder");
119  }
120}