【Java】通过移除空行和注释来压缩 JavaScript 代码

1. [代码]JavaScriptCompressor.java
/**
 * This file is part of the Echo Web Application Framework (hereinafter "Echo").
 * Copyright (C) 2002-2009 NextApp, Inc.
 *
 * Compresses a String containing JavaScript by removing comments and whitespace.
 */
public class JavaScriptCompressor {
 
    private static final char LINE_FEED = ‘\n‘;
    private static final char CARRIAGE_RETURN = ‘\r‘;
    private static final char SPACE = ‘ ‘;
    private static final char TAB = ‘\t‘;
 
    /**
     * Compresses a String containing JavaScript by removing comments and 
     * whitespace.
     * 
     * @param script the String to compress
     * @return a compressed version
     */
    public static String compress(String script) {
        JavaScriptCompressor jsc = new JavaScriptCompressor(script);
        return jsc.outputBuffer.toString();
    }
 
    /** Original JavaScript text. */
    private String script;
     
    /** 
     * Compressed output buffer.
     * This buffer may only be modified by invoking the <code>append()</code>
     * method.
     */
    private StringBuffer outputBuffer;
     
    /** Current parser cursor position in original text. */
    private int pos;
     
    /** Character at parser cursor position. */
    private char ch;
     
    /** Last character appended to buffer. */
    private char lastAppend;
 
    /** Flag indicating if end-of-buffer has been reached. */
    private boolean endReached;
 
    /** Flag indicating whether content has been appended after last identifier. */
    private boolean contentAppendedAfterLastIdentifier = true;
 
    /**
     * Creates a new <code>JavaScriptCompressor</code> instance.
     * 
     * @param script
     */
    private JavaScriptCompressor(String script) {
        this.script = script;
        outputBuffer = new StringBuffer(script.length());
        nextChar();
 
        while (!endReached) {
            if (Character.isJavaIdentifierStart(ch)) {
                renderIdentifier();
            } else if (ch == ‘ ‘) {
                skipWhiteSpace();
            } else if (isWhitespace()) {
                // Compress whitespace
                skipWhiteSpace();
            } else if ((ch == ‘"‘) || (ch == ‘\‘‘)) {
                // Handle strings
                renderString();
            } else if (ch == ‘/‘) {
                // Handle comments
                nextChar();
                if (ch == ‘/‘) {
                    nextChar();
                    skipLineComment();
                } else if (ch == ‘*‘) {
                    nextChar();
                    skipBlockComment();
                } else {
                    append(‘/‘);
                }
            } else {
                append(ch);
                nextChar();
            }
        }
    }
 
    /**
     * Append character to output.
     * flash动画
     * @param ch the character to append
     */http://www.huiyi8.com/donghua/?
    private void append(char ch) {
        lastAppend = ch;
        outputBuffer.append(ch);
        contentAppendedAfterLastIdentifier = true;
    }
     
    /**
     * Determines if current character is whitespace.
     * 
     * @return true if the character is whitespace
     */
    private boolean isWhitespace() {
        return ch == CARRIAGE_RETURN || ch == SPACE || ch == TAB || ch == LINE_FEED;        
    }
 
    /**
     * Load next character.
     */
    private void nextChar() {
        if (!endReached) {
            if (pos < script.length()) {
                ch = script.charAt(pos++);
            } else {
                endReached = true;
                ch = 0;
            }
        }
    }
 
    /**
     * Adds an identifier to output.
     */
    private void renderIdentifier() {
        if (!contentAppendedAfterLastIdentifier)
            append(SPACE);
        append(ch);
        nextChar();
        while (Character.isJavaIdentifierPart(ch)) {
            append(ch);
            nextChar();
        }
        contentAppendedAfterLastIdentifier = false;
    }
 
    /**
     * Adds quoted String starting at current character to output.
     */
    private void renderString() {
        char startCh = ch; // Save quote char
        append(ch);
        nextChar();
        while (true) {
            if ((ch == LINE_FEED) || (ch == CARRIAGE_RETURN) || (endReached)) {
                // JavaScript error: string not terminated
                return;
            } else {
                if (ch == ‘\\‘) {
                    append(ch);
                    nextChar();
                    if ((ch == LINE_FEED) || (ch == CARRIAGE_RETURN) || (endReached)) {
                        // JavaScript error: string not terminated
                        return;
                    }
                    append(ch);
                    nextChar();
                } else {
                    append(ch);
                    if (ch == startCh) {
                        nextChar();
                        return;
                    }
                    nextChar();
                }
            }
        }
    }
 
    /**
     * Moves cursor past a line comment.
     */
    private void skipLineComment() {
        while ((ch != CARRIAGE_RETURN) && (ch != LINE_FEED)) {
            if (endReached) {
                return;
            }
            nextChar();
        }
    }
 
    /**
     * Moves cursor past a block comment.
     */
    private void skipBlockComment() {
        while (true) {
            if (endReached) {
                return;
            }
            if (ch == ‘*‘) {
                nextChar();
                if (ch == ‘/‘) {
                    nextChar();
                    return;
                }
            } else
                nextChar();
        }
    }
     
    /**
     * Renders a new line character, provided previously rendered character 
     * is not a newline.
     */
    private void renderNewLine() {
        if (lastAppend != ‘\n‘ && lastAppend != ‘\r‘) {
            append(‘\n‘);
        }
    }
     
    /**
     * Moves cursor past white space (including newlines).
     */
    private void skipWhiteSpace() {
        if (ch == LINE_FEED || ch == CARRIAGE_RETURN) {
            renderNewLine();
        } else {
            append(ch);
        }
        nextChar();
        while (ch == LINE_FEED || ch == CARRIAGE_RETURN || ch == SPACE || ch == TAB) {
            if (ch == LINE_FEED || ch == CARRIAGE_RETURN) {
                renderNewLine();
            }
            nextChar();
        }
    }
}

【Java】通过移除空行和注释来压缩 JavaScript 代码

时间: 2024-10-10 11:18:00

【Java】通过移除空行和注释来压缩 JavaScript 代码的相关文章

给定一个源代码文件(.cs, .java),输出该文件的总行数、空行数、注释行数、代码行数

public class ComputeSourceLine { public static void main(String[] args) throws FileNotFoundException { // TODO Auto-generated method stub // 定义相关变量 int totalLine = 0; int emptyLine = 0; int commentLine = 0; int codeLine = 0; // 大家重点了解 Scanner类(网络搜索)

java简单统计.java文件中的有效代码行,空行,注释行

package regxdemo; import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; public class CountFile { /** * @param args */ static int cntCode=0, cntNode=0, cntSpace

java 内存移到堆外!!! Jvm gcih 淘宝优化JVM实践

官方地址 Jvm gcih 出自Jvm  GC-Invisible Heap 什么是GCIH GC-Invisible Heap,简称GCIH,是一种将Java对象从Java堆内移动到堆外,并且可以在JVM间共享这些对象的技术. 为什么要用GCIH GCIH顾名思义就是GC访问不到的堆,它是对JVM内存管理机制的一个有益的补充. 在某些特殊的应用中有大量生命周期很长的对象,在应用运行的整个过程中它们都存在,不需要被GC回收.如果这类对象很多,总体占用内存比例高,那么他们的存在将给GC带来很多不必

linux过滤旧文件中的空行和注释行剩余内容组成新文件

一.说明 在某些场景下我们想要将旧文件中空行和注释行过滤掉,将产生实际效果的行保留. 比如redis提供的配置示例文件中有很多用于说明的空行和注释行,我们想把产生实际效果的配置行筛选出来组成新的简洁的配置文件. 二.命令 grep -Ev "^$|#" old_file_name > new_file_name grep--过滤命令 -E--使用正则表达示进行匹配 -v--剔除匹配的项(默认是筛选匹配的项) ^--开头匹配 $--代表空行 |--正则中的或运算 #--#开头行 o

阿里巴巴Java 开发手册编程规约之注释规约

1. [强制]类.类属性.类方法的注释必须使用 Javadoc 规范,使用/**内容*/格式,不得使用//xxx 方式.说明: 在 IDE 编辑窗口中, Javadoc 方式会提示相关注释,生成 Javadoc 可以正确输出相应注释: 在 IDE 中,工程调用方法时,不进入方法即可悬浮提示方法.参数.返回值的意义,提高阅读效率. 2. [强制]所有的抽象方法(包括接口中的方法) 必须要用 Javadoc 注释.除了返回值.参数.异常说明外,还必须指出该方法做什么事情,实现什么功能.说明: 对子类

java 线程返回值,优先级,后台线程 示例代码

ava 线程返回值,休眠,优先级,后台线程  示例代码 package org.rui.thread.basic; import java.util.ArrayList; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Execu

C++统计代码注释行数 &amp; 有效代码行数 &amp; 代码注释公共行 &amp; 函数个数

问题来源,在14年的暑假的一次小项目当中遇到了一个这样的问题,要求统计C++代码的注释行数,有效代码行数,代码注释公共行数,以及函数个数. 下面稍微解释一下问题, 1)注释行数:指有注释的行,包括有代码和注释的公共行(如:3,4,15,22...) 2)有效代码行:指有代码的行,包括有代码和注释的公共行(如:1,4,11,15,25....) 3)代码注释公共行:指又有代码又有注释的行(如:4,15...) 4)函数个数:这个不用说明了吧. 以下为注释情况展示代码: 1 #include <st

java 队列、优先级队列、双向队列示例演示代码

package org.rui.collection2.queues; import java.util.LinkedList; import java.util.PriorityQueue; import java.util.Queue; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.Li

java学习中,匿名函数、构造方法、构造代码块、构造方法中调用构造方法(java 学习中的小记录)

java学习中,匿名函数.构造方法.构造代码块.构造方法中调用构造方法(java 学习中的小记录) 作者:王可利(Star·星星) 匿名函数 匿名对象:没有名字的对象 匿名对象使用的注意点: 1.一般不会用匿名对象给属性赋值,无法获取属性值,每次new 都是一个新的对象. 2.匿名对象永远都不可能是一个对象. 如:person new().name = "星星":是不行的 匿名对象的好处:书写简单. 匿名对象使用的场景: 1.如果一个对象调用一个方法一次的时候,就可以用匿名对象来调用.