对文件中的每一行进行更改 - Java

时间:2016-03-04 00:28:59

标签: java file indentation lines

我正在开发一个程序,它读取包含不正确缩进代码的5个不同文件。我必须编写一个方法来正确缩进代码并将其打印到控制台和新文件,给定选项卡大小以及输入和输出文件的名称作为参数。到目前为止,我的代码贯穿并缩进每一行,然后尝试确定何时缩进另一个制表符或取消缩进。

public static void justifyJava( String inputFileName, String outputFileName, 
                                int tabSize ) throws FileNotFoundException {

    String one_tab = "";
    for (int i = 0; i < tabSize; i++) {
        one_tab += " ";
        }

    Scanner input = new Scanner( new File (inputFileName));
    PrintStream out = new PrintStream ( new File (outputFileName));
    int lineCount = 0;
    while ( input.hasNextLine() ) {
        String line = input.nextLine();
        line = one_tab + line.trim();
        lineCount++;
        if (lineCount == 1){
            line = line.substring(tabSize);
        }
        else if (lineCount == 2){
            Scanner lineScan = new Scanner(line);
            while (lineScan.hasNext()) {
                String token = lineScan.next();
                if (token.length() <= 2) {
                    line = line.substring(tabSize);
                }
            }
        }
        else if (line.contains("{") && lineCount > 2){
            System.out.println(line);
            out.println(line);
            line = one_tab + input.nextLine();
            while(!(line.contains("}"))){
                line = one_tab + line;
                System.out.println(line);
                out.println(line);
                line = input.nextLine();
            }
            line = one_tab + line;
        }
        else if (line.contains("}") && input.hasNextLine()){
            line = one_tab + line;
        }
        else if (!(input.hasNextLine())) {
            line = line.substring(tabSize);
        } 
        System.out.println(line);
        out.println(line);                                    
    }            
}

这种方式变得非常乏味,因为我必须考虑多少情况,特别是因为这些文件中的代码使用不同的大括号样式。基本上我试图做的就是在一个标签后面的一个开口大括号后面的每一行缩进,并且一个标签后面的每个行都是一个闭合的大括号。有更简单的方法吗?

1 个答案:

答案 0 :(得分:0)

确定&#34;多少次&#34;你必须缩进一行就像知道在这行之前打开了多少代码块一样。为此,在以下情况下检测到新的代码块:

  1. 该字符串包含一个左括号{。
  2. 该字符串包含一个控制语句,例如if
  3. 第二种方法更难,因为你必须确定字符串是否实际上是一个控制语句而不是变量名的一部分。

    因此,一个简单的程序,并没有涵盖所有可能的编码标准,但会起到相当不错的作用:

    1. 搜索不属于评论的左括号。
    2. 找到它时,递归调用传递新缩进大小的方法。
    3. 找到代码块结束后返回。
    4. 这是一个适用于大多数简单案例的MWE。它能够检测字符串外的开始和结束括号,而不会在注释行内搜索。

      import java.io.File;
      import java.io.FileNotFoundException;
      import java.io.PrintStream;
      import java.util.ArrayList;
      import java.util.Scanner;
      
      
      public class JavaIndent {
      
          public static void main(String[] args) {
              try {
                  JavaIndent.justify("path/to/input.java", "path/to/output.java", 4);
              } catch (FileNotFoundException ex) {
                  System.out.println("File not found...");
              }
          }
      
          public static void justify(String inputFileName, String outputFileName,
                  int tabSize) throws FileNotFoundException {
      
              String one_tab = "";
              for (int i = 0; i < tabSize; i++) {
                  one_tab += " ";
              }
      
              Scanner input = new Scanner(new File(inputFileName));
              PrintStream out = new PrintStream(new File(outputFileName));
      
              JavaIndent.justifyRecursion(one_tab, "", input, out);
          }
      
          private static String justifyRecursion(String base_tab, String tab, Scanner input, PrintStream out) {
              String line;
              boolean flag_open, flag_close, flag_comment, flag_empty;
              while (input.hasNextLine()) {
                  line = input.nextLine().trim();
                  flag_open  = JavaIndent.contains(line, "{");
                  flag_close = JavaIndent.contains(line, "}");
                  flag_empty = line.length() == 0;
                  flag_comment = (flag_empty) ? false : line.charAt(0) == '/';
                  if (flag_comment || flag_empty) {
                      out.println(tab + line);
                  } else if (flag_close) {
                      return line;
                  } else if (flag_open) {
                      out.println(tab + line + "ENTERED OPEN");
                      line = JavaIndent.justifyRecursion(base_tab, tab + base_tab, input, out);
                      out.println(tab + line);
      
                      // Handles statements like } else { and sequences of these.
                      flag_open = JavaIndent.contains(line, "{");
                      while (flag_open) {
                          line = JavaIndent.justifyRecursion(base_tab, tab + base_tab, input, out);
                          out.println(tab + line);
                          flag_open = JavaIndent.contains(line, "{");
                      }
                  } else {
                      // Just a regular line, nothing special
                      out.println(tab + line);
                  }
              }
              return "";
          }
      
          private static boolean contains(String line, String sequence) {
              String current = "";
              char ch, last_ch = ' ';
              int count_quotation = 0;
              ArrayList<String> code_without_strings = new ArrayList<>();
              for (int k = 0; k < line.length(); ++k) {
                  ch = line.charAt(k);
                  if (ch == '"' && count_quotation == 0 && last_ch != '\'') {
                      code_without_strings.add(current);
                      current = "";
                      ++count_quotation;
                  } else if (ch == '"' && count_quotation == 1) {
                      if (last_ch != '\\') {
                          count_quotation = 0;
                      }
                  }
                  if (count_quotation == 0) {
                      current += ch;
                  }
                  last_ch = ch;
              }
              code_without_strings.add(current);
      
              for (String code : code_without_strings) {
                  if (code.contains(sequence))
                      return true;
              }
              return false;
          }
      }
      

      但是,仍然需要考虑这样的陈述:

      if (condition)
          System.out.println("This should be indented, but it won't be...");
      

      和此:

      /**
       * This is just a comment, but the program will indent from here on {.
       */
      

      尝试使用JavaIndent缩进JavaIndent.java并验证最终会得到

      if (code.contains(sequence))
      return true;
      

      而不是

      if (code.contains(sequence))
          return true;