Java去除源代码注释

总体思路是对待分析的带注释段的字符串进行遍历,声明一个缓冲字符串变量来记录非注释的部分,最后返回这个缓冲字符串变量作为结果

1.首先考虑/*comment*/形式的注释
当遇到/*部分便停止记录,继续往后遍历到*/部分,实现跳过/**/段

2.考虑/*comment/*inside*/out*/形式的嵌套注释
声明一个数字变量来记录/*的开始的次数,遇到一个/*就+1,遇到一个*/就-1,实现嵌套匹配

3.考虑双斜杠注释
发现//形式的字符串的时候表明遇到了双斜杠注释,这时候使用while循环继续向后遍历,直到发现一个换行符,从而跳过整个这一行

4.考虑双引号
双引号中的注释部分是不能去掉的,比如print("//Hello\"World\"/*comment*/");
所以上面几条所考虑的情况都应该是在双引号范围之外,所以应该最先匹配双引号。如果没有出现双引号,则按照上面的规则处理
如果发现了开始双引号,在匹配结束双引号的时候要注意可能会遇到转义双引号,需要跳过以\开始的双引号,从而匹配到正确的结束双引号




import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

public class main
{

/**
* @param args
*/
public static void main(String[] args)
{
// TODO Auto-generated method stub
String test1 = "printf(\"Hello /* a comment /* a comment inside comment */ inside /* another comment inside comment */ string */ world\")";
String test2 = "//*no recursion*/* file header */";
String test3 = "//*no recursion*/* file header***********/************* Sample input program **********/**************/int spawn_workers(int worker_count) {/* The block below is supposed to spawn 100 workers. But it creates many more. Commented until I figure out why for (int i = 0; i < worker_count; ++i) { if(!fork()) { /* This is the worker. Start working. */ do_work(); } } */ return 0; /* successfully spawned 100 workers */}int main() {printf(\"Hello /*a comment inside string*/ world\"); int worker_count = 0/*octal number*/144; if (spawn_workers(worker_count) != 0) { exit(-1); } return 0;}";

String test = ReadFileToString("E:/main.java");
// System.out.println(removeComments(test));
// System.out.println(removeCommentsWithQuote(test));
System.out.println(removeCommentsWithQuoteAndDoubleEscape(test));
}
/**/

/**
* 简单的直接去掉星号斜杠注释段
* @param code
* @return
*/
public static String removeComments(String code)
{
StringBuilder sb = new StringBuilder();
int cnt = 0;
for (int i = 0; i < code.length(); i++)
{
if(cnt == 0)
{
if(i+1 < code.length() && code.charAt(i) == '/' && code.charAt(i+1) == '*')
{
cnt++;
i++;
continue;
}
}
else
{
if(i+1 < code.length() && code.charAt(i) == '*' && code.charAt(i+1) == '/')
{
cnt--;
i++;
continue;
}
if(i+1 < code.length() && code.charAt(i) == '/' && code.charAt(i+1) == '*')
{
cnt++;
i++;
continue;
}
}
if(cnt == 0)
{
sb.append(code.charAt(i));
}
}
return sb.toString();
}

/**
* 处理带双引号的注释
* @param code
* @return
*/
public static String removeCommentsWithQuote(String code)
{
StringBuilder sb = new StringBuilder();
int cnt = 0;
boolean quoteFlag = false;
for (int i = 0; i < code.length(); i++)
{
//如果没有开始双引号范围
if(!quoteFlag)
{
//如果发现双引号开始
if(code.charAt(i) == '\"')
{
sb.append(code.charAt(i));
quoteFlag = true;
continue;
}
//不在双引号范围内
else
{
//处理/**/注释段
if(cnt == 0)
{
if(i+1 < code.length() && code.charAt(i) == '/' && code.charAt(i+1) == '*')
{
cnt++;
i++;
continue;
}
}
else
{
if(i+1 < code.length() && code.charAt(i) == '*' && code.charAt(i+1) == '/')
{
cnt--;
i++;
continue;
}
if(i+1 < code.length() && code.charAt(i) == '/' && code.charAt(i+1) == '*')
{
cnt++;
i++;
continue;
}
}
//如果没有发现/**/段或者已经处理完了嵌套的/**/
if(cnt == 0)
{
sb.append(code.charAt(i));
continue;
}
}
}
//处理双引号段
else
{
//如果发现双引号结束(非转移形式的双引号)
if(code.charAt(i) == '\"' && code.charAt(i-1) != '\\')
{
sb.append(code.charAt(i));
quoteFlag = false;
}
//双引号开始了但是还没有结束
else
{
sb.append(code.charAt(i));
}
}

}
return sb.toString();
}

/**
* 处理双引号和双斜杠注释
* @param code
* @return
*/
public static String removeCommentsWithQuoteAndDoubleEscape(String code)
{
StringBuilder sb = new StringBuilder();
int cnt = 0;
boolean quoteFlag = false;
for (int i = 0; i < code.length(); i++)
{
//如果没有开始双引号范围
if(!quoteFlag)
{
//如果发现双引号开始
if(code.charAt(i) == '\"')
{
sb.append(code.charAt(i));
quoteFlag = true;
continue;
}
//处理双斜杠注释
else if(i+1 < code.length() && code.charAt(i) == '/' && code.charAt(i+1) == '/')
{
while(code.charAt(i) != '\n')
{
i++;
}
continue;
}
//不在双引号范围内
else
{
//处理/**/注释段
if(cnt == 0)
{
if(i+1 < code.length() && code.charAt(i) == '/' && code.charAt(i+1) == '*')
{
cnt++;
i++;
continue;
}
}
else
{
//发现"*/"结尾
if(i+1 < code.length() && code.charAt(i) == '*' && code.charAt(i+1) == '/')
{
cnt--;
i++;
continue;
}
//发现"/*"嵌套
if(i+1 < code.length() && code.charAt(i) == '/' && code.charAt(i+1) == '*')
{
cnt++;
i++;
continue;
}
}
//如果没有发现/**/注释段或者已经处理完了嵌套的/**/注释段
if(cnt == 0)
{
sb.append(code.charAt(i));
continue;
}
}
}
//处理双引号注释段
else
{
//如果发现双引号结束(非转义形式的双引号)
if(code.charAt(i) == '\"' && code.charAt(i-1) != '\\')
{
sb.append(code.charAt(i));
quoteFlag = false;
}
//双引号开始了但是还没有结束
else
{
sb.append(code.charAt(i));
}
}
}
return sb.toString();
}

/**
* 从一个文件读入到String
* @param FilePath
* @return
*/
public static String ReadFileToString(String FilePath)
{
FileInputStream fis = null;
BufferedReader br = null;
try
{
fis = new FileInputStream(FilePath);
br = new BufferedReader(new InputStreamReader(fis, "utf-8"));
}
catch (IOException e)
{
e.printStackTrace();
}
//构建成String
StringBuffer sb = new StringBuffer();
String temp = null;
try
{
while((temp = br.readLine()) != null)
{
sb.append(temp+'\n');
}
} catch (IOException e)
{
e.printStackTrace();
}
return sb.toString();
}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值