DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
  • Refcardz
  • Trend Reports
  • Webinars
  • Zones
  • |
    • Agile
    • AI
    • Big Data
    • Cloud
    • Database
    • DevOps
    • Integration
    • IoT
    • Java
    • Microservices
    • Open Source
    • Performance
    • Security
    • Web Dev
DZone >

DiffPrint.java

Snippets Manager user avatar by
Snippets Manager
·
Mar. 18, 07 · · Code Snippet
Like (0)
Save
Tweet
684 Views

Join the DZone community and get the full member experience.

Join For Free
ソースレビュー用に色を付けてソースを表示させたHTMLファイルを出力して差分を分かりやすく印刷することを支援するツールです。

see:
ソースレビュー用の差分印刷機能
ソースレビュー用の差分印刷機能その2
ソースレビュー用の差分印刷機能その3

DiffPrint.java

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.util.StringTokenizer;

/**
 * @author fumokmm
 *
 */
public class DiffPrint {

	private static final String LS = System.getProperty("line.separator");	// 改行文字
	private static final String FS = System.getProperty("file.separator");	// ファイル区切り文字
	private static final String HTML_AMP = "&";
	private static final String HTML_GT = ">";
	private static final String HTML_LT = "<";
	private static final String HTML_DOUBLE_QUOT = """;
	private static final String HTML_SPACE = " ";
	private static final String HTML_TAB = HTML_SPACE + HTML_SPACE + HTML_SPACE + HTML_SPACE;

	/** ハイライト:行 */
	private static final String HILIGHT = "*";
	/** ハイライト:追加行 */
	private static final String HILIGHT_PLUS = "+";
	/** ハイライト:削除行 */
	private static final String HILIGHT_MINUS = "-";
	/** ハイライトセパレータ */
	private static final String HILIGHT_SEP = "|";
	
	private String src = null;
	private String fileName = null;

	/**
	 * 差分印刷用HTMLを出力します。
	 * 
	 * @param args 0:inDir 1:outDir
	 */
	public static void main(String[] args) throws IOException {
		System.out.println("処理開始");

		/* 入力ファイルのディレクトリ */
		File inDir = new File(".");
		if (args.length > 0 && args[0] != null && args[0].trim().length() > 0) {
			inDir = new File(args[0]);	
		}
		if (!inDir.exists()) {
			inDir.mkdir();
		}
		/* 出力ファイルのディレクトリ */
		File outDir = new File(".");
		if (args.length > 1 && args[1] != null && args[1].trim().length() > 0) {
			outDir = new File(args[1]);
		}
		if (!outDir.exists()) {
			outDir.mkdir();
		}
		/* スタイルシートファイルのディレクトリ */
		File cssDir = new File(outDir.getPath() + FS + "css");
		if (!cssDir.exists()) {
			cssDir.mkdir();
		}

		DiffPrint dp = new DiffPrint();
		File outFile = null;
		File cssFile = new File(cssDir.getPath() + FS + "diffprint.css");

		File[] inFiles = inDir.listFiles();
		for (File file : inFiles) {
			if (file.isFile()) {
				outFile = new File(outDir.getPath() + FS + file.getName() + "_dp.html");

				dp.readSource(file);
				dp.writeSource(outFile);
				System.out.println("IN  -> " + file);
				System.out.println("OUT -> " + outFile);
			}
		}

		dp.writeCss(cssFile);
		System.out.println("CSS -> " + cssFile);
		
		System.out.println("処理終了");
	}

	/**
	 * ファイルの拡張子を返す
	 * 
	 * @param file	ファイル
	 * @return ext 拡張子
	 */
	private static String getExtension(File file) {
		StringTokenizer st = new StringTokenizer(file.getName(), ".");
		String ext = null;
		while (st.hasMoreTokens()) {
			ext = st.nextToken();
		}
		return ext;
	}

	/**
	 * ソースファイルの読み込みます
	 * 
	 * @param inFile ソースファイル
	 */
	public void readSource(File inFile) throws IOException {
		StringBuilder sb = new StringBuilder();
		InputStreamReader inReader = new InputStreamReader(new FileInputStream(inFile));
		int ch;
		while ((ch = inReader.read()) != -1) {
			sb.append((char) ch);
		}
		this.src = sb.toString();
		this.fileName = inFile.getName();
	}

	/**
	 * 結果をHTML形式で書き出します
	 * 
	 * @param outFile 結果を出力するファイル
	 */
	public void writeSource(File outFile) throws IOException {
		BufferedReader reader = new BufferedReader(new StringReader(this.src));
		FileWriter fw = new FileWriter(outFile);

		/* 前半部分 */
		fw.write(makePreSourceArea());

		int rowNum = 0;
		String line;
		while ((line = reader.readLine()) != null) {
			/* ソース部分 */
			fw.write(makeSourceArea(++rowNum, line));
		}

		/* 後半部分 */
		fw.write(makePostSourceArea(++rowNum));

		fw.close();
	}
	
	/**
	 * スタイルシートファイルを作成します。
	 * 
	 * @param cssFile 出力するスタイルシートファイル
	 */
	public void writeCss(File cssFile) throws IOException {
		FileWriter fw = new FileWriter(cssFile);
		fw.write(makeCssArea());
		fw.close();
	}

	/**
	 * 出力ソースの前半部分を作成します。
	 * 
	 * @return 出力ソースの前半部分
	 */
	private String makePreSourceArea() {
		StringBuilder sb = new StringBuilder();
		sb.append("").append(LS);
		sb.append("").append(LS);
		sb.append("").append(LS);
		sb.append("").append(this.fileName).append("").append(LS);
		sb.append("").append(LS);
		sb.append("").append(LS);
		sb.append("").append(LS);
		sb.append("").append(LS);
		return sb.toString();
	}

	/**
	 * 出力ソースの後半部分を作成します。
	 * 
	 * @param rowNum 行番号
	 * @return 出力ソースの後半部分
	 */
	private String makePostSourceArea(int rowNum) {
		StringBuilder sb = new StringBuilder();
		sb.append("");
		sb.append("");
		sb.append("");
		sb.append("").append(LS);
		sb.append("
").append(this.fileName).append("
").append(rowNum).append("[EOF]
").append(LS); sb.append("").append(LS); sb.append("").append(LS); return sb.toString(); } /** * ソース部分を作成します。 * * @param rowNum 行番号 * @param line ソース一行分 * @return 出力ソース一行分 */ private String makeSourceArea(int rowNum, String line) { /* ハイライト行かどうかの判定 */ String hilightMark = isHilight(line); StringBuilder sb = new StringBuilder(); sb.append(""); sb.append(""); if (hilightMark != null) { sb.append(hilightMark); } sb.append(rowNum); sb.append(""); sb.append("").append(htmlEscape(line)).append(""); sb.append("").append(LS); return sb.toString(); } /** * スタイルシートの文字列を作成します。 * * @return CSS */ private String makeCssArea() { StringBuilder sb = new StringBuilder(); sb.append("body {").append(LS); sb.append("\tfont-family: \"MS ゴシック\";").append(LS); sb.append("}").append(LS); sb.append(".source-table {").append(LS); sb.append("\twidth: 650px;").append(LS); // 650だとぴったりくらい sb.append("\twidth: 645px;").append(LS); // 650だとぴったりくらい sb.append("\tfont-size: 12px;").append(LS); sb.append("}").append(LS); sb.append(".row-num {").append(LS); sb.append("\ttext-align: right;").append(LS); sb.append("\tvertical-align: top;").append(LS); sb.append("\tword-break: keep-all;").append(LS); sb.append("\tword-wrap: normal;").append(LS); sb.append("\tborder-right: 1px solid gray;").append(LS); sb.append("}").append(LS); sb.append(".source {").append(LS); sb.append("\tpadding-left: 0.3em;").append(LS); sb.append("\tword-break: break-all;").append(LS); sb.append("\tword-wrap: break-word;").append(LS); sb.append("}").append(LS); sb.append(".end-of-file {").append(LS); sb.append("\tcolor: gray;").append(LS); sb.append("\tpadding-left: 0.3em;").append(LS); sb.append("\tword-break: break-all;").append(LS); sb.append("\tword-wrap: break-word;").append(LS); sb.append("}").append(LS); sb.append("caption {").append(LS); sb.append("\ttext-align: left;").append(LS); sb.append("\tfont-weight: bold;").append(LS); sb.append("}").append(LS); sb.append(".hilight {").append(LS); sb.append("\tbackground-color: yellow;").append(LS); sb.append("}").append(LS); sb.append(".hilight-plus {").append(LS); sb.append("\tbackground-color: gold;").append(LS); sb.append("}").append(LS); sb.append(".hilight-minus {").append(LS); sb.append("\tbackground-color: silver;").append(LS); return sb.toString(); } /** * ハイライト行かどうか判定します * * @param line ソース一行分 * @return ハイライト行の場合、cssのハイライト用クラス名を返却。 * ハイライト行でなければnullを返却。 */ private String isHilight(String line) { if (line.startsWith(HILIGHT + HILIGHT_SEP)) { return HILIGHT; } else if (line.startsWith(HILIGHT_PLUS + HILIGHT_SEP)) { return HILIGHT_PLUS; } else if (line.startsWith(HILIGHT_MINUS + HILIGHT_SEP)) { return HILIGHT_MINUS; } return null; } private String makeHilight(String mark) { if (HILIGHT.equals(mark)) { return " class=\"hilight\""; } else if (HILIGHT_PLUS.equals(mark)) { return " class=\"hilight-plus\""; } else if (HILIGHT_MINUS.equals(mark)) { return " class=\"hilight-minus\""; } return ""; } /** * ハイライト部を除去します。 * * @param line ソース一行分 * @return ハイライト部を除去したソース一行分 */ private String deleteHilightMark(String line) { return line.replace(HILIGHT + HILIGHT_SEP, "") .replace(HILIGHT_MINUS + HILIGHT_SEP, "") .replace(HILIGHT_PLUS + HILIGHT_SEP, ""); } /** * HTMLエスケープを施して返却します。 * * @param line ソース一行分 * @return HTMLエスケープされたソース一行分 */ private String htmlEscape(String line) { return line.replaceAll("&", HTML_AMP) .replaceAll("<", HTML_LT) .replaceAll(">", HTML_GT) .replaceAll("\"", HTML_DOUBLE_QUOT) .replaceAll(" ", HTML_SPACE) .replaceAll("\t", HTML_TAB); } }

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • What SREs Can Learn From the Atlassian Nightmare Outage of 2022
  • How Does the Database Understand and Execute Your Query?
  • Upload Files to AWS S3 in JMeter Using Groovy
  • How to Handle Early Startup Technical Debt (Or Just Avoid it Entirely)

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • MVB Program
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends:

DZone.com is powered by 

AnswerHub logo