1. 程式人生 > >自己寫的文字轉網頁格式的DLL(附原始碼)

自己寫的文字轉網頁格式的DLL(附原始碼)

程式的總體說明:

這個程式源於自己喜歡諾機裡的ActiveNote程式,所以用C++寫了個程式,用於轉換電腦裡的文字檔案為HTML格式的檔案,然後導到手機裡閱讀。該版本是一個精簡版本,做成了DLL更通用。
DLL介面提供了兩個函式,第一個函式,Txt2Html,是轉換的主函式,第一個引數是完整路徑的檔名,第二個引數是設定引數;
第二個函式,GetInfoLog,用於返回處理資訊,如果成功轉換,返回一些轉換的資訊,如轉換了多少檔案之類的,如果失敗,則由此獲得錯誤程式碼。

關於轉換引數的設計:

(一)特殊引數設計:#@1 該引數為配色方案1 ,具體是網頁背景黃色,字型為褐色。

(二)預設引數:background-color:#1E4641; 設定背景色藍色
color:#F6F2E9;  設定字型色灰白色
font-size:12pt; 設定字型大小
line-height:135%; 設定行間距
margin-left:10px; 設定頁邊距

以上為預置的預設的五個引數。引數可以自己靈活設定,只要符合CSS語法即可,相同關鍵字的則覆蓋預設值。注意設定的引數之間以分號“;”隔開,最好在分號後添個空格。

注意,以上引數設定在body{}之中,因此作用於整個頁面。

特殊語法的設計:
文字轉換是逐行進行的,如果讀到一行起始兩個字元是{{,則將其後的內容原樣輸出至檔案中,不做轉換處理,這類似於C++中的解釋標記。不同的是{{必須是頂行,作用域直到遇到下一個換行符。防止潛在的誤判,加了一個條件,即該行中存在HTML標籤符“<”。


這樣設計的好處在於,可以自己手動對文字格式進行設定。如標題設定:
{{<h1>標題文字</h1>
再如字型設定
{{<font size="-1">文字</font>
還有最有趣之處在於,新增連結,插入圖片等
{{<img src="1.gif">

這樣,在手機上用HTML格式的文件閱讀,表現的會更豐富一些。

其他設計:
1.程式碼中處理的檔名用vector向量管理,好處在於以後升級可處理一批檔案,現在的版本只是處理一個檔案。
2.文字最終會轉成網頁通用的編碼UTF-8。


不足之處:
文字檔案只能是ANSI編碼,不支援Unicode,如果是UTF-8編碼的文字檔案,轉網頁處理沒有問題,轉UTF-8編碼的時候需要加判斷條件,跳過編碼處理。


以下附帶實現原始碼,僅供學習參考!


標頭檔案1:

#ifndef TXT2HTML_H
#define TXT2HTML_H

extern "C" int __declspec(dllexport)Txt2Html(char *file, char * para);
extern "C" unsigned long __declspec(dllexport)GetInfoLog();

#endif

標頭檔案2:
// stdafx.h : include file for standard system include files,
//  or project specific include files that are used frequently, but
//      are changed infrequently
//
#if !defined(AFX_STDAFX_H__B8EF9455_1C3B_4FBD_A3C8_D8D11154AD3E__INCLUDED_)
#define AFX_STDAFX_H__B8EF9455_1C3B_4FBD_A3C8_D8D11154AD3E__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

// Insert your headers here
#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers

#include <windows.h>
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>

// TODO: reference additional headers your program requires here
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_STDAFX_H__B8EF9455_1C3B_4FBD_A3C8_D8D11154AD3E__INCLUDED_)

實現檔案:

// txt2html.cpp : Defines the entry point for the DLL application.

#include "stdafx.h"
#include "txt2html.h"
#include <vector>

using namespace std;

string& replaceAll(string& context,const string& from,const string& to);

unsigned long infoLog;
//const var
const int numOfRsvdFormatStr=5;
string rsvdFormatKeyStrList[numOfRsvdFormatStr]  //系統預定的格式設定引數關鍵字
=	{
				string("background-color"),
					string("color"),	
					string("font-size"),
					string("line-height"),
					string("margin-left")
};
//string("word-spacing"),string("letter-spacing"), 去除兩個屬性

string rsvdFormatStrList[numOfRsvdFormatStr] // 預設定引數以及預設值
=	{
				string(" background-color:#1E4641; "),
					string(" color:#F6F2E9; "),
					string(" font-size:12pt; "),
					string(" line-height:135%; "),
					string(" margin-left:10px; ")
};
//				string(" word-spacing:2px; "),	string(" letter-spacing:1px; "),

BOOL APIENTRY DllMain( HANDLE hModule, 
					  DWORD  ul_reason_for_call, 
					  LPVOID lpReserved
					  )
{
    return TRUE;
}

unsigned long GetInfoLog()
{	
	return infoLog;	
}

int Txt2Html(char *file, char *para)
{
	// file Title List
	// 定義檔案變數
	vector<string> fileTitleList;
	
	string inFilePath,outFilePath,fileExtName,fileTitle;
	string filePathName;
	
	string formatString;
	
	// 解析檔案引數
	inFilePath=string(file);
	size_t lastPoint=inFilePath.rfind('.');
	size_t lastDivd=inFilePath.rfind('\\');
	
	fileExtName=inFilePath.substr(lastPoint+1,3);
	fileTitle=inFilePath.substr(lastDivd+1,lastPoint-lastDivd-1);
	filePathName=inFilePath.substr(0,lastDivd+1);
	
	if(fileExtName.compare("txt")&&fileExtName.compare("TXT"))
	{
		infoLog=ERROR_INVALID_PARAMETER;
		return 1;
	}
	
	// 解析處理命令引數
	string tempFormatString=string(para);
	
	size_t foundHere;
	foundHere=tempFormatString.find("#@1");
	if(foundHere!=string::npos)
	{
		rsvdFormatStrList[0]=string("background-color:#F0DCB4; ");
		rsvdFormatStrList[1]=string("color:#64190A; ");
		
		tempFormatString.erase(foundHere,3);
	}	
	
	size_t endHere;
	size_t startHere;
	for(int i=0;i<numOfRsvdFormatStr;i++)
	{
		if((startHere=tempFormatString.find(rsvdFormatKeyStrList[i]))!=string::npos)
		{
			endHere=tempFormatString.find(";",startHere);
			if(endHere==string::npos) endHere=tempFormatString.size();
			
			formatString+=tempFormatString.substr(startHere,endHere-startHere+1);
			
			formatString+=string(" ");
			tempFormatString.erase(startHere,endHere-startHere+1);
			
		}else
		{
			formatString+=rsvdFormatStrList[i];
		}
		
	}	
	formatString+=tempFormatString;
	
		
	// 測試檔案是否可開啟,將可開啟的新增至檔案列表
	ifstream inFile(inFilePath.c_str());
	if(!inFile)
	{
		infoLog=GetLastError();
		return 1;
	}
	
	inFile.close();
	
	fileTitleList.push_back(fileTitle);
	
	// 迴圈處理列表中的檔案
	string strLine;
	
	for(i=0;i<fileTitleList.size();i++)
	{
		inFilePath=filePathName+fileTitleList.at(i)+string(".txt");
		outFilePath=filePathName+fileTitleList.at(i); // 生成臨時檔案
		
		ifstream inFile(inFilePath.c_str());
		if(!inFile)
		{
			infoLog=GetLastError();
			return 1;
		}
		
		ofstream outFile(outFilePath.c_str());
		if(!outFile)
		{
			infoLog=GetLastError();
			return 1;
		} 
		// generate file head 
		outFile<<"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
			<<"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"
			<<"<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n"
			<<"<meta http-equiv=\"Content-Type\" content=\"text/html;charset=UTF-8\" />\n"
			<<"<title>"<<fileTitleList.at(i)<<"</title>\n"
			<<"<style type=\"text/css\">\nbody {"
			<<formatString
			<<" }\nimg {border: none;}\n</style>\n</head>\n<body><p>\n";
		
		for(;;)
		{
			if(inFile.eof())break;
			
			getline(inFile,strLine,'\n');
			
			// special characters parse
			if(strLine.size() > 2
				&& strLine.at(0)=='{'
				&& strLine.at(1)=='{'
				&& strLine.find("<")!=string::npos)
			{
				strLine=strLine.substr(2,strLine.size()-2);
			}
			else if(!strLine.empty())
			{			
				replaceAll(strLine,"&","&amp;"); // It should be the first
				
				replaceAll(strLine,"<","&lt;");
				replaceAll(strLine,">","&gt;");
				replaceAll(strLine,"  ","&nbsp;&nbsp;");
				replaceAll(strLine,"\"","&quot;");
				replaceAll(strLine,"\t","&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;");
			}
			
			outFile<<strLine<<"<br>";				
		}		
		outFile<<"</p></body></html>\n";
		
		inFile.close();
		outFile.close();		
	}	
	
	// 處理UTF-8轉碼
	for(i=0;i<fileTitleList.size();i++)
	{
		inFilePath=filePathName+fileTitleList.at(i);
		outFilePath=filePathName+fileTitleList.at(i)+string(".html");
		
		ifstream inFile(inFilePath.c_str(),ios::binary);
		if(!inFile)
		{
			infoLog=GetLastError();
			return 1;
		}
		
		ofstream outFile(outFilePath.c_str(),ios::binary);
		if(!outFile)
		{
			infoLog=GetLastError();
			return 1;
		} 
		
		// 轉碼核心部分		
		ostringstream ansiTextStringStream;
		
		ansiTextStringStream<<inFile.rdbuf();
		
		string ansiTextString=string(ansiTextStringStream.str());
		
		int uniTextLength=MultiByteToWideChar(CP_ACP,NULL,ansiTextString.c_str(),ansiTextString.length(),NULL,0); // 獲得轉換緩衝區大小
		
		if(!uniTextLength) 
		{
			infoLog=GetLastError();
			return 1;
		}
		
		LPWSTR uniTextBuf = new WCHAR[uniTextLength];
		
		if(!MultiByteToWideChar(CP_ACP, NULL, ansiTextString.c_str(),ansiTextString.length(), uniTextBuf, uniTextLength))
		{
			infoLog=GetLastError();
			return 1;
		}
		
		int utf8TextLength=WideCharToMultiByte(CP_UTF8, NULL, uniTextBuf, uniTextLength, NULL,0,NULL,NULL);
		
		if(!utf8TextLength) 
		{
			infoLog=GetLastError();
			return 1;
		}
		
		LPSTR utf8TextBuf=new CHAR[utf8TextLength];
		
		if(!WideCharToMultiByte(CP_UTF8, NULL, uniTextBuf, uniTextLength, utf8TextBuf, utf8TextLength,NULL,NULL))
		{
			infoLog=GetLastError();
			return 1;
		}
		
		outFile.write(utf8TextBuf,utf8TextLength);
		
		if(uniTextBuf)
		{
			delete []uniTextBuf;
		}
		if(utf8TextBuf)
		{
			delete []utf8TextBuf;
		}
			
		inFile.close();
		outFile.close();
		
		DeleteFile(inFilePath.c_str());
		
	}
	
	infoLog=fileTitleList.size();
	return 0;
	
}
string& replaceAll(string& context,const string& from,const string& to)
{
	size_t lookHere = 0;
	size_t foundHere;
	while((foundHere=context.find(from,lookHere))!=string::npos)
	{
		context.replace(foundHere,from.size(),to);
		lookHere=foundHere+to.size();
		
	}
	return context;
}

附,生成的dll下載地址: