출처 : http://truelogic.org/wordpress/2015/09/18/minify-javascript-with-c/
MVC부터는 번들이 있어, 전혀 쓸모가 없지만 구닥다리 웹폼에서는 이것이 필요했다..
결론부터 말하면 한글 깨짐 문제로 사용하지 않는 자료, 영문 압축은 잘 됨
1. 윈폼이든 ASP.NET의 IIS 든.. 새로 쓰기 할 경로폴더에 읽기/쓰기 권한이 있어야 함
2. 원 제작자의 의도는, 외쿡인이라 한글을 쓰지 않으니
압축로직을 char[] 가 아닌 바이너리 스트림으로 처리하면서 이 부분에서 한글 깨짐이 발생함
3. 해결방법은 byte 비교가 아닌 char 를 비교하며 한글 문자열일때 유니코드 변환을 해야함..
4. 즉 출처의 소스 코드는 인코딩 옵션을 줘바야 그닥 의미가 없음
결론은 js 압축 방식의 형태를 구경해보고자 한다면...
적어도 한번은 삽질해봤고.. 학습용으로 보기엔 괜찮은 코드라 올려둠
하지만 실사용은 mvc이상에선 닷넷프레임워크면 기본제공 번들러를
core면 nuget에서 받아 사용하지 않을까 추정..
그리고 구닥다리 웹폼엔 https://www.nuget.org/packages/AjaxMin/ 이걸 써도 되지 않을까 추측
js를 압축해주는 사이트라면 https://closure-compiler.appspot.com/home 와 같은 사이트도 있고
다른 대안의 방법은 많음...
주의 : 로컬 IIS 디버깅중 코드 오류 발생하면 iisworker가 물고 있는 경우가 발생하니
iisworker 프로세스를 강제 종료해야 할 수 있음
using System;
using System.IO;
namespace JSMinify
{
public class Minify
{
private string mFileName = ""; // file to process
private string mOriginalData = ""; // data from original file
private string mModifiedData = ""; // processed data
private bool mIsError = false; // becomes true if any error happens
private string mErr = ""; // error message
private BinaryReader mReader = null; // stream to process the file byte by byte
private const int EOF = -1; // for end of file
/// <summary>
/// Constructor - does all the processing
/// </summary>
/// <param name="f">file path</param>
public Minify(string f) {
try
{
if (File.Exists(f))
{
mFileName = f;
//read contents completely. This is only for test purposes. The actual processing is done by another stream
StreamReader rdr = new StreamReader(mFileName);
mOriginalData = rdr.ReadToEnd();
rdr.Close();
mReader = new BinaryReader(new FileStream(mFileName, FileMode.Open));
doProcess();
mReader.Close();
//write modified data
string outFile = mFileName + ".min";
StreamWriter wrt = new StreamWriter(outFile);
wrt.Write(mModifiedData);
wrt.Close();
}
else {
mIsError = true;
mErr = "File does not exist";
}
}
catch (Exception ex) {
mIsError = true;
mErr = ex.Message;
}
}
/// <summary>
/// Main process
/// </summary>
private void doProcess() {
int lastChar = 1; // current byte read
int thisChar = -1; // previous byte read
int nextChar = -1; // byte read in peek()
bool endProcess = false; // loop control
bool ignore = false; // if false then add byte to final output
bool inComment = false; // true when current bytes are part of a comment
bool isDoubleSlashComment = false; // '//' comment
// main processing loop
while (!endProcess) {
endProcess = (mReader.PeekChar() == -1); // check for EOF before reading
if (endProcess)
break;
ignore = false;
thisChar = mReader.ReadByte();
if (thisChar == '\t')
thisChar = ' ';
else if (thisChar == '\t')
thisChar = '\n';
else if (thisChar == '\r')
thisChar = '\n';
if (thisChar == '\n')
ignore = true;
if (thisChar == ' ')
{
if ((lastChar == ' ') || isDelimiter(lastChar) == 1)
ignore = true;
else {
endProcess = (mReader.PeekChar() == -1); // check for EOF
if (!endProcess)
{
nextChar = mReader.PeekChar();
if (isDelimiter(nextChar) == 1)
ignore = true;
}
}
}
if (thisChar == '/')
{
nextChar = mReader.PeekChar();
if (nextChar == '/' || nextChar == '*')
{
ignore = true;
inComment = true;
if (nextChar == '/')
isDoubleSlashComment = true;
else
isDoubleSlashComment = false;
}
}
// ignore all characters till we reach end of comment
if (inComment) {
while (true) {
thisChar = mReader.ReadByte();
if (thisChar == '*') {
nextChar = mReader.PeekChar();
if (nextChar == '/')
{
thisChar = mReader.ReadByte();
inComment = false;
break;
}
}
if (isDoubleSlashComment && thisChar == '\n') {
inComment = false;
break;
}
} // while (true)
ignore = true;
} // if (inComment)
if (!ignore)
addToOutput(thisChar);
lastChar = thisChar;
} // while (!endProcess)
}
/// <summary>
/// Add character to modified data string
/// </summary>
/// <param name="c">char to add</param>
private void addToOutput(int c)
{
mModifiedData += (char) c;
}
/// <summary>
/// Original data from file
/// </summary>
/// <returns></returns>
public string getOriginalData()
{
return mOriginalData;
}
/// <summary>
/// Modified data after processing
/// </summary>
/// <returns></returns>
public string getModifiedData()
{
return mModifiedData;
}
/// <summary>
/// Check if a byte is alphanumeric
/// </summary>
/// <param name="c">byte to check</param>
/// <returns>retval - 1 if yes. else 0</returns>
private int isAlphanumeric(int c)
{
int retval = 0;
if ((c >= 'a' && c <= 'z') ||
(c >= '0' && c <= '9') ||
(c >= 'A' && c <= 'Z') ||
c == '_' || c == '$' || c == '\\' || c > 126)
retval = 1;
return retval;
}
/// <summary>
/// Check if a byte is a delimiter
/// </summary>
/// <param name="c">byte to check</param>
/// <returns>retval - 1 if yes. else 0</returns>
private int isDelimiter(int c)
{
int retval = 0;
if (c == '(' || c == ',' || c == '=' || c == ':' ||
c == '[' || c == '!' || c == '&' || c == '|' ||
c == '?' || c == '+' || c == '-' || c == '~' ||
c == '*' || c == '/' || c == '{' || c == '\n' ||
c == ','
)
{
retval = 1;
}
return retval;
}
}
}
'C#.NET > C#' 카테고리의 다른 글
Dapper ORM 사용 예제 (0) | 2024.10.22 |
---|---|
Spring의 Class ToString 을 비슷하게 구현해보자 (0) | 2024.09.20 |
간단 텍스트 파일 로그 생성 (0) | 2024.09.06 |
c# 권장 코딩 규칙 가이드 (0) | 2020.06.09 |