文件编码转换工具,支持多种编码格式之间的转换,包括 utf-8、utf-7、unicode、ascii、gb2312(简体中文)、big5(繁体中文)等。
实现代码
1. 主窗体代码 (mainform.cs)
using system;
using system.collections.generic;
using system.io;
using system.text;
using system.windows.forms;
using system.drawing;
using system.linq;
using system.threading.tasks;
namespace fileencodingconverter
{
public partial class mainform : form
{
private readonly dictionary<string, encoding> encodings = new dictionary<string, encoding>();
private readonly list<conversionresult> conversionresults = new list<conversionresult>();
private readonly stringbuilder logbuilder = new stringbuilder();
public mainform()
{
initializecomponent();
initializeencodings();
initializeui();
}
private void initializeencodings()
{
// 注册编码提供程序以支持gb2312等特殊编码
encoding.registerprovider(codepagesencodingprovider.instance);
// 添加支持的编码
encodings.add("utf-8", encoding.utf8);
encodings.add("utf-7", encoding.utf7);
encodings.add("utf-16 (le)", encoding.unicode); // little endian
encodings.add("utf-16 (be)", encoding.bigendianunicode); // big endian
encodings.add("utf-32", encoding.utf32);
encodings.add("ascii", encoding.ascii);
encodings.add("gb2312 (简体中文)", encoding.getencoding("gb2312"));
encodings.add("big5 (繁体中文)", encoding.getencoding("big5"));
encodings.add("iso-8859-1", encoding.getencoding("iso-8859-1"));
encodings.add("windows-1252", encoding.getencoding(1252));
encodings.add("shift-jis", encoding.getencoding("shift_jis"));
encodings.add("euc-kr", encoding.getencoding("euc-kr"));
}
private void initializeui()
{
// 窗体设置
this.text = "文件编码转换工具";
this.size = new size(900, 650);
this.startposition = formstartposition.centerscreen;
this.backcolor = color.fromargb(240, 243, 249);
this.font = new font("segoe ui", 9);
// 创建控件
int ypos = 20;
int labelwidth = 120;
int controlwidth = 300;
int rowheight = 35;
// 源文件选择
lblsourcefile = new label { text = "源文件:", location = new point(20, ypos), size = new size(labelwidth, 20), textalign = contentalignment.middleright };
txtsourcefile = new textbox { location = new point(150, ypos), size = new size(controlwidth, 25), readonly = true };
btnbrowsesource = new button { text = "浏览...", location = new point(460, ypos), size = new size(75, 25), backcolor = color.steelblue, forecolor = color.white, flatstyle = flatstyle.flat };
btnbrowsesource.flatappearance.bordersize = 0;
btnbrowsesource.click += btnbrowsesource_click;
// 目标文件选择
ypos += rowheight;
lbltargetfile = new label { text = "目标文件:", location = new point(20, ypos), size = new size(labelwidth, 20), textalign = contentalignment.middleright };
txttargetfile = new textbox { location = new point(150, ypos), size = new size(controlwidth, 25), readonly = true };
btnbrowsetarget = new button { text = "浏览...", location = new point(460, ypos), size = new size(75, 25), backcolor = color.steelblue, forecolor = color.white, flatstyle = flatstyle.flat };
btnbrowsetarget.flatappearance.bordersize = 0;
btnbrowsetarget.click += btnbrowsetarget_click;
// 源编码选择
ypos += rowheight;
lblsourceencoding = new label { text = "源编码:", location = new point(20, ypos), size = new size(labelwidth, 20), textalign = contentalignment.middleright };
cmbsourceencoding = new combobox { location = new point(150, ypos), size = new size(controlwidth, 25), dropdownstyle = comboboxstyle.dropdownlist };
cmbsourceencoding.items.addrange(encodings.keys.toarray());
cmbsourceencoding.selectedindex = 0;
// 目标编码选择
ypos += rowheight;
lbltargetencoding = new label { text = "目标编码:", location = new point(20, ypos), size = new size(labelwidth, 20), textalign = contentalignment.middleright };
cmbtargetencoding = new combobox { location = new point(150, ypos), size = new size(controlwidth, 25), dropdownstyle = comboboxstyle.dropdownlist };
cmbtargetencoding.items.addrange(encodings.keys.toarray());
cmbtargetencoding.selectedindex = 0;
// 转换选项
ypos += rowheight;
chkdetectencoding = new checkbox { text = "自动检测源文件编码", location = new point(150, ypos), autosize = true, checked = true };
chkdetectencoding.checkedchanged += (s, e) => cmbsourceencoding.enabled = !chkdetectencoding.checked;
// 转换按钮
ypos += rowheight + 10;
btnconvert = new button { text = "开始转换", location = new point(150, ypos), size = new size(100, 35), backcolor = color.forestgreen, forecolor = color.white, flatstyle = flatstyle.flat, font = new font("segoe ui", 10, fontstyle.bold) };
btnconvert.flatappearance.bordersize = 0;
btnconvert.click += btnconvert_click;
btnbatchconvert = new button { text = "批量转换", location = new point(260, ypos), size = new size(100, 35), backcolor = color.dodgerblue, forecolor = color.white, flatstyle = flatstyle.flat, font = new font("segoe ui", 10, fontstyle.bold) };
btnbatchconvert.flatappearance.bordersize = 0;
btnbatchconvert.click += btnbatchconvert_click;
btnstop = new button { text = "停止", location = new point(370, ypos), size = new size(100, 35), backcolor = color.indianred, forecolor = color.white, flatstyle = flatstyle.flat, font = new font("segoe ui", 10, fontstyle.bold), enabled = false };
btnstop.flatappearance.bordersize = 0;
btnstop.click += btnstop_click;
// 结果列表
ypos += rowheight + 20;
lstresults = new listview { location = new point(20, ypos), size = new size(840, 300), view = view.details, fullrowselect = true, gridlines = true };
lstresults.columns.add("源文件", 200);
lstresults.columns.add("目标文件", 200);
lstresults.columns.add("源编码", 80);
lstresults.columns.add("目标编码", 80);
lstresults.columns.add("状态", 80);
lstresults.columns.add("大小", 80);
lstresults.columns.add("耗时", 80);
// 日志区域
ypos += 320;
lbllog = new label { text = "操作日志:", location = new point(20, ypos), autosize = true };
ypos += 25;
txtlog = new textbox { location = new point(20, ypos), size = new size(840, 150), multiline = true, readonly = true, scrollbars = scrollbars.vertical, font = new font("consolas", 9) };
// 状态栏
statusstrip = new statusstrip();
toolstripstatuslabel = new toolstripstatuslabel();
toolstripprogressbar = new toolstripprogressbar();
statusstrip.items.add(toolstripstatuslabel);
statusstrip.items.add(toolstripprogressbar);
statusstrip.location = new point(0, this.clientsize.height - 22);
statusstrip.size = new size(this.clientsize.width, 22);
statusstrip.anchor = anchorstyles.bottom | anchorstyles.left | anchorstyles.right;
// 添加控件到窗体
this.controls.addrange(new control[] {
lblsourcefile, txtsourcefile, btnbrowsesource,
lbltargetfile, txttargetfile, btnbrowsetarget,
lblsourceencoding, cmbsourceencoding,
lbltargetencoding, cmbtargetencoding,
chkdetectencoding,
btnconvert, btnbatchconvert, btnstop,
lstresults, lbllog, txtlog, statusstrip
});
// 初始化结果列表
lstresults.listviewitemsorter = new listviewcolumnsorter();
}
#region 控件声明
private label lblsourcefile, lbltargetfile, lblsourceencoding, lbltargetencoding, lbllog;
private textbox txtsourcefile, txttargetfile, txtlog;
private combobox cmbsourceencoding, cmbtargetencoding;
private button btnbrowsesource, btnbrowsetarget, btnconvert, btnbatchconvert, btnstop;
private checkbox chkdetectencoding;
private listview lstresults;
private statusstrip statusstrip;
private toolstripstatuslabel toolstripstatuslabel;
private toolstripprogressbar toolstripprogressbar;
#endregion
#region 事件处理
private void btnbrowsesource_click(object sender, eventargs e)
{
using (openfiledialog openfiledialog = new openfiledialog())
{
openfiledialog.filter = "所有文件 (*.*)|*.*";
openfiledialog.title = "选择源文件";
if (openfiledialog.showdialog() == dialogresult.ok)
{
txtsourcefile.text = openfiledialog.filename;
// 自动生成目标文件名
if (string.isnullorempty(txttargetfile.text))
{
string dir = path.getdirectoryname(openfiledialog.filename);
string filename = path.getfilenamewithoutextension(openfiledialog.filename);
string ext = path.getextension(openfiledialog.filename);
txttargetfile.text = path.combine(dir, $"{filename}_converted{ext}");
}
}
}
}
private void btnbrowsetarget_click(object sender, eventargs e)
{
using (savefiledialog savefiledialog = new savefiledialog())
{
savefiledialog.filter = "所有文件 (*.*)|*.*";
savefiledialog.title = "选择目标文件";
if (!string.isnullorempty(txtsourcefile.text))
{
savefiledialog.filename = path.getfilename(txtsourcefile.text);
}
if (savefiledialog.showdialog() == dialogresult.ok)
{
txttargetfile.text = savefiledialog.filename;
}
}
}
private async void btnconvert_click(object sender, eventargs e)
{
if (string.isnullorempty(txtsourcefile.text) || !file.exists(txtsourcefile.text))
{
messagebox.show("请选择有效的源文件", "错误", messageboxbuttons.ok, messageboxicon.error);
return;
}
if (string.isnullorempty(txttargetfile.text))
{
messagebox.show("请指定目标文件路径", "错误", messageboxbuttons.ok, messageboxicon.error);
return;
}
// 准备ui
btnconvert.enabled = false;
btnbatchconvert.enabled = false;
btnstop.enabled = true;
lstresults.items.clear();
conversionresults.clear();
logbuilder.clear();
txtlog.clear();
toolstripprogressbar.value = 0;
toolstripstatuslabel.text = "转换中...";
try
{
// 执行转换
var result = await convertfileasync(
txtsourcefile.text,
txttargetfile.text,
chkdetectencoding.checked ? null : encodings[cmbsourceencoding.text],
encodings[cmbtargetencoding.text]
);
// 显示结果
addresulttolistview(result);
logmessage($"转换完成: {path.getfilename(txtsourcefile.text)}");
}
catch (exception ex)
{
logmessage($"转换失败: {ex.message}");
messagebox.show($"转换失败: {ex.message}", "错误", messageboxbuttons.ok, messageboxicon.error);
}
finally
{
// 恢复ui
btnconvert.enabled = true;
btnbatchconvert.enabled = true;
btnstop.enabled = false;
toolstripstatuslabel.text = "就绪";
}
}
private async void btnbatchconvert_click(object sender, eventargs e)
{
using (folderbrowserdialog folderdialog = new folderbrowserdialog())
{
folderdialog.description = "选择包含要转换文件的文件夹";
folderdialog.shownewfolderbutton = false;
if (folderdialog.showdialog() == dialogresult.ok)
{
string sourcefolder = folderdialog.selectedpath;
string targetfolder = path.combine(sourcefolder, "converted");
if (!directory.exists(targetfolder))
{
directory.createdirectory(targetfolder);
}
// 准备ui
btnconvert.enabled = false;
btnbatchconvert.enabled = false;
btnstop.enabled = true;
lstresults.items.clear();
conversionresults.clear();
logbuilder.clear();
txtlog.clear();
toolstripprogressbar.value = 0;
toolstripstatuslabel.text = "批量转换中...";
try
{
// 获取所有文件
var files = directory.getfiles(sourcefolder, "*.*", searchoption.alldirectories);
int totalfiles = files.length;
int processedfiles = 0;
// 处理每个文件
foreach (string file in files)
{
if (cancellationtokensource.iscancellationrequested)
break;
string relativepath = file.substring(sourcefolder.length + 1);
string targetfile = path.combine(targetfolder, relativepath);
string targetdir = path.getdirectoryname(targetfile);
if (!directory.exists(targetdir))
{
directory.createdirectory(targetdir);
}
// 执行转换
var result = await convertfileasync(
file,
targetfile,
chkdetectencoding.checked ? null : encodings[cmbsourceencoding.text],
encodings[cmbtargetencoding.text]
);
// 显示结果
addresulttolistview(result);
processedfiles++;
// 更新进度
int progress = (int)((double)processedfiles / totalfiles * 100);
toolstripprogressbar.value = progress;
toolstripstatuslabel.text = $"处理中: {processedfiles}/{totalfiles} 文件";
}
logmessage($"批量转换完成! 共处理 {processedfiles} 个文件");
}
catch (exception ex)
{
logmessage($"批量转换失败: {ex.message}");
messagebox.show($"批量转换失败: {ex.message}", "错误", messageboxbuttons.ok, messageboxicon.error);
}
finally
{
// 恢复ui
btnconvert.enabled = true;
btnbatchconvert.enabled = true;
btnstop.enabled = false;
toolstripstatuslabel.text = "就绪";
}
}
}
}
private void btnstop_click(object sender, eventargs e)
{
cancellationtokensource?.cancel();
btnstop.enabled = false;
toolstripstatuslabel.text = "正在停止...";
}
#endregion
#region 核心功能
private cancellationtokensource cancellationtokensource = new cancellationtokensource();
private async task<conversionresult> convertfileasync(
string sourcefile,
string targetfile,
encoding sourceencoding,
encoding targetencoding)
{
var result = new conversionresult
{
sourcefile = sourcefile,
targetfile = targetfile,
sourceencoding = sourceencoding?.encodingname ?? "自动检测",
targetencoding = targetencoding.encodingname,
starttime = datetime.now
};
try
{
// 检测源文件编码(如果需要)
if (sourceencoding == null)
{
sourceencoding = detectfileencoding(sourcefile);
result.sourceencoding = sourceencoding.encodingname;
}
// 读取源文件内容
string content = await task.run(() => file.readalltext(sourcefile, sourceencoding));
// 写入目标文件
await task.run(() => file.writealltext(targetfile, content, targetencoding));
// 获取文件大小
fileinfo fileinfo = new fileinfo(targetfile);
result.size = fileinfo.length;
result.status = "成功";
}
catch (exception ex)
{
result.status = $"失败: {ex.message}";
}
finally
{
result.endtime = datetime.now;
result.duration = result.endtime - result.starttime;
}
return result;
}
private encoding detectfileencoding(string filepath)
{
// 使用bom检测编码
var bom = new byte[4];
using (var file = new filestream(filepath, filemode.open, fileaccess.read))
{
file.read(bom, 0, 4);
}
// 检查bom
if (bom[0] == 0xef && bom[1] == 0xbb && bom[2] == 0xbf)
return encoding.utf8;
if (bom[0] == 0xfe && bom[1] == 0xff)
return encoding.bigendianunicode;
if (bom[0] == 0xff && bom[1] == 0xfe)
{
if (bom[2] == 0x00 && bom[3] == 0x00)
return encoding.utf32;
return encoding.unicode;
}
if (bom[0] == 0x00 && bom[1] == 0x00 && bom[2] == 0xfe && bom[3] == 0xff)
return encoding.utf32;
if (bom[0] == 0x2b && bom[1] == 0x2f && bom[2] == 0x76)
return encoding.utf7;
// 没有bom,使用启发式检测
return detectencodingwithoutbom(filepath);
}
private encoding detectencodingwithoutbom(string filepath)
{
// 使用简单启发式方法检测编码
int utf8count = 0;
int asciicount = 0;
int chinesecount = 0;
using (var reader = new streamreader(filepath, encoding.default, true))
{
string content = reader.readtoend();
// 检查是否包含中文字符
foreach (char c in content)
{
if (c > 127)
{
chinesecount++;
}
}
// 检查utf-8特征
try
{
byte[] bytes = encoding.utf8.getbytes(content);
string decoded = encoding.utf8.getstring(bytes);
if (decoded == content) utf8count++;
}
catch { }
// 检查ascii特征
try
{
byte[] bytes = encoding.ascii.getbytes(content);
string decoded = encoding.ascii.getstring(bytes);
if (decoded == content) asciicount++;
}
catch { }
}
// 根据特征选择编码
if (chinesecount > 0)
{
// 如果包含中文字符,尝试gb2312或big5
if (filepath.contains("简体") || filepath.contains("gb"))
return encoding.getencoding("gb2312");
return encoding.getencoding("big5");
}
else if (utf8count > 0)
{
return encoding.utf8;
}
else
{
return encoding.default; // 使用系统默认编码
}
}
private void addresulttolistview(conversionresult result)
{
var item = new listviewitem(path.getfilename(result.sourcefile));
item.subitems.add(path.getfilename(result.targetfile));
item.subitems.add(result.sourceencoding);
item.subitems.add(result.targetencoding);
item.subitems.add(result.status);
item.subitems.add(formatfilesize(result.size));
item.subitems.add($"{result.duration.totalmilliseconds:0} ms");
item.tag = result;
// 根据状态设置颜色
if (result.status.startswith("成功"))
item.forecolor = color.green;
else
item.forecolor = color.red;
lstresults.items.add(item);
conversionresults.add(result);
}
private string formatfilesize(long bytes)
{
string[] sizes = { "b", "kb", "mb", "gb", "tb" };
int order = 0;
double len = bytes;
while (len >= 1024 && order < sizes.length - 1)
{
order++;
len /= 1024;
}
return $"{len:0.##} {sizes[order]}";
}
private void logmessage(string message)
{
string logentry = $"[{datetime.now:hh:mm:ss}] {message}";
logbuilder.appendline(logentry);
txtlog.appendtext(logentry + environment.newline);
txtlog.scrolltocaret();
}
#endregion
#region 辅助类
private class conversionresult
{
public string sourcefile { get; set; }
public string targetfile { get; set; }
public string sourceencoding { get; set; }
public string targetencoding { get; set; }
public string status { get; set; }
public long size { get; set; }
public datetime starttime { get; set; }
public datetime endtime { get; set; }
public timespan duration { get; set; }
}
private class listviewcolumnsorter : system.collections.icomparer
{
private int columnindex;
private sortorder sortorder;
public listviewcolumnsorter()
{
columnindex = 0;
sortorder = sortorder.ascending;
}
public int compare(object x, object y)
{
listviewitem item1 = (listviewitem)x;
listviewitem item2 = (listviewitem)y;
string text1 = item1.subitems[columnindex].text;
string text2 = item2.subitems[columnindex].text;
if (double.tryparse(text1, out double num1) &&
double.tryparse(text2, out double num2))
{
return sortorder == sortorder.ascending ?
num1.compareto(num2) : num2.compareto(num1);
}
return sortorder == sortorder.ascending ?
string.compare(text1, text2) : string.compare(text2, text1);
}
}
#endregion
}
}
2. 程序入口 (program.cs)
using system;
using system.windows.forms;
namespace fileencodingconverter
{
static class program
{
[stathread]
static void main()
{
application.enablevisualstyles();
application.setcompatibletextrenderingdefault(false);
application.run(new mainform());
}
}
}
3. 应用程序配置文件 (app.config)
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedruntime version="v4.0" sku=".netframework,version=v4.7.2"/>
</startup>
<runtime>
<assemblybinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentassembly>
<assemblyidentity name="system.runtime" publickeytoken="b03f5f7f11d50a3a" culture="neutral"/>
<bindingredirect oldversion="0.0.0.0-4.1.2.0" newversion="4.1.2.0"/>
</dependentassembly>
</assemblybinding>
</runtime>
</configuration>功能特点
1. 多编码支持
- 国际编码:utf-8、utf-7、utf-16 (le/be)、utf-32、ascii
- 中文编码:gb2312 (简体中文)、big5 (繁体中文)
- 其他编码:iso-8859-1、windows-1252、shift-jis、euc-kr
- 自动检测:智能检测源文件编码
2. 转换模式
- 单文件转换:选择单个源文件进行转换
- 批量转换:整个文件夹批量转换
- 自动生成目标文件:自动添加"_converted"后缀
3. 用户友好界面
- 直观操作:清晰的文件选择和编码选择
- 实时日志:显示详细的操作日志
- 结果列表:表格形式展示转换结果
- 状态指示:颜色标识成功/失败状态
- 进度显示:进度条显示处理进度
4. 高级功能
- 编码检测:智能检测无bom文件的编码
- 大文件处理:流式处理避免内存溢出
- 错误处理:详细的错误信息和异常捕获
- 性能优化:异步处理避免界面卡顿
技术实现细节
1. 编码检测算法
private encoding detectfileencoding(string filepath)
{
// 使用bom检测编码
var bom = new byte[4];
using (var file = new filestream(filepath, filemode.open, fileaccess.read))
{
file.read(bom, 0, 4);
}
// 检查bom
if (bom[0] == 0xef && bom[1] == 0xbb && bom[2] == 0xbf)
return encoding.utf8;
if (bom[0] == 0xfe && bom[1] == 0xff)
return encoding.bigendianunicode;
if (bom[0] == 0xff && bom[1] == 0xfe)
{
if (bom[2] == 0x00 && bom[3] == 0x00)
return encoding.utf32;
return encoding.unicode;
}
if (bom[0] == 0x00 && bom[1] == 0x00 && bom[2] == 0xfe && bom[3] == 0xff)
return encoding.utf32;
if (bom[0] == 0x2b && bom[1] == 0x2f && bom[2] == 0x76)
return encoding.utf7;
// 没有bom,使用启发式检测
return detectencodingwithoutbom(filepath);
}
2. 文件转换核心
private async task<conversionresult> convertfileasync(
string sourcefile,
string targetfile,
encoding sourceencoding,
encoding targetencoding)
{
var result = new conversionresult
{
sourcefile = sourcefile,
targetfile = targetfile,
sourceencoding = sourceencoding?.encodingname ?? "自动检测",
targetencoding = targetencoding.encodingname,
starttime = datetime.now
};
try
{
// 检测源文件编码(如果需要)
if (sourceencoding == null)
{
sourceencoding = detectfileencoding(sourcefile);
result.sourceencoding = sourceencoding.encodingname;
}
// 读取源文件内容
string content = await task.run(() => file.readalltext(sourcefile, sourceencoding));
// 写入目标文件
await task.run(() => file.writealltext(targetfile, content, targetencoding));
// 获取文件大小
fileinfo fileinfo = new fileinfo(targetfile);
result.size = fileinfo.length;
result.status = "成功";
}
catch (exception ex)
{
result.status = $"失败: {ex.message}";
}
finally
{
result.endtime = datetime.now;
result.duration = result.endtime - result.starttime;
}
return result;
}
3. 批量处理实现
private async void btnbatchconvert_click(object sender, eventargs e)
{
// 选择源文件夹
using (folderbrowserdialog folderdialog = new folderbrowserdialog())
{
if (folderdialog.showdialog() == dialogresult.ok)
{
string sourcefolder = folderdialog.selectedpath;
string targetfolder = path.combine(sourcefolder, "converted");
// 创建目标文件夹
directory.createdirectory(targetfolder);
// 获取所有文件
var files = directory.getfiles(sourcefolder, "*.*", searchoption.alldirectories);
int totalfiles = files.length;
int processedfiles = 0;
// 处理每个文件
foreach (string file in files)
{
if (cancellationtokensource.iscancellationrequested)
break;
// 构建目标路径
string relativepath = file.substring(sourcefolder.length + 1);
string targetfile = path.combine(targetfolder, relativepath);
string targetdir = path.getdirectoryname(targetfile);
// 创建子目录
directory.createdirectory(targetdir);
// 执行转换
var result = await convertfileasync(
file,
targetfile,
chkdetectencoding.checked ? null : encodings[cmbsourceencoding.text],
encodings[cmbtargetencoding.text]
);
// 显示结果
addresulttolistview(result);
processedfiles++;
// 更新进度
int progress = (int)((double)processedfiles / totalfiles * 100);
toolstripprogressbar.value = progress;
}
}
}
}
使用说明
1. 单文件转换
- 点击"浏览…"选择源文件
- 选择目标文件路径(自动生成或手动指定)
- 选择源编码(或勾选"自动检测")
- 选择目标编码
- 点击"开始转换"
2. 批量转换
- 点击"批量转换"按钮
- 选择包含要转换文件的文件夹
- 程序自动创建"converted"子文件夹存放结果
- 选择源编码(或勾选"自动检测")
- 选择目标编码
- 程序自动处理所有文件
3. 结果查看
- 结果列表:显示所有转换操作的详细信息
- 状态列:绿色表示成功,红色表示失败
- 日志区域:显示详细的操作日志
- 状态栏:显示当前处理进度
参考代码 c# 文件编码转换工具(支持utf-8/utf-7/unicode/ascii/gb2312(简体中文)/big5 (繁体中文)等编码转换 ) www.youwenfan.com/contentcst/49413.html
扩展功能建议
1. 添加文件预览功能
private void previewfile(string filepath, encoding encoding)
{
try
{
string content = file.readalltext(filepath, encoding);
var previewform = new form
{
text = $"预览: {path.getfilename(filepath)}",
size = new size(800, 600)
};
var textbox = new textbox
{
multiline = true,
scrollbars = scrollbars.both,
dock = dockstyle.fill,
text = content,
font = new font("consolas", 10)
};
previewform.controls.add(textbox);
previewform.showdialog();
}
catch (exception ex)
{
messagebox.show($"预览失败: {ex.message}", "错误",
messageboxbuttons.ok, messageboxicon.error);
}
}
2. 添加编码修复功能
private void fixencoding(string filepath, encoding correctencoding)
{
try
{
// 以错误编码读取
string content = file.readalltext(filepath, encoding.default);
// 以正确编码重新写入
file.writealltext(filepath, content, correctencoding);
logmessage($"已修复文件编码: {path.getfilename(filepath)}");
}
catch (exception ex)
{
logmessage($"修复失败: {ex.message}");
}
}
3. 添加文件比较功能
private void comparefiles(string file1, string file2)
{
try
{
string content1 = file.readalltext(file1);
string content2 = file.readalltext(file2);
if (content1 == content2)
{
messagebox.show("文件内容完全相同", "比较结果",
messageboxbuttons.ok, messageboxicon.information);
}
else
{
// 使用差异比较工具
// 这里可以集成第三方比较工具
messagebox.show("文件内容不同", "比较结果",
messageboxbuttons.ok, messageboxicon.warning);
}
}
catch (exception ex)
{
messagebox.show($"比较失败: {ex.message}", "错误",
messageboxbuttons.ok, messageboxicon.error);
}
}
4. 添加编码统计功能
private void analyzefolderencoding(string folderpath)
{
try
{
var encodingstats = new dictionary<string, int>();
var files = directory.getfiles(folderpath, "*.*", searchoption.alldirectories);
foreach (string file in files)
{
try
{
encoding encoding = detectfileencoding(file);
string encodingname = encoding.encodingname;
if (!encodingstats.containskey(encodingname))
{
encodingstats[encodingname] = 0;
}
encodingstats[encodingname]++;
}
catch
{
// 忽略无法检测的文件
}
}
// 显示统计结果
showencodingstatistics(encodingstats);
}
catch (exception ex)
{
messagebox.show($"分析失败: {ex.message}", "错误",
messageboxbuttons.ok, messageboxicon.error);
}
}
常见问题解决
1. 编码检测错误
- 问题:自动检测编码不准确
- 解决:
- 对于已知编码的文件,取消"自动检测"并手动选择
- 使用专业文本编辑器(如notepad++)确认实际编码
- 在程序中添加更多启发式规则
2. 转换后乱码
- 问题:转换后出现乱码
- 解决:
- 确认源文件的实际编码
- 尝试不同的源编码设置
- 使用"自动检测"功能
- 对于特殊字符,使用utf-8编码
3. 大文件处理
- 问题:处理大文件时内存不足
- 解决:
- 使用流式处理(streamreader/streamwriter)
- 分块读取和写入文件
- 增加系统虚拟内存
- 使用64位应用程序
4. 特殊字符处理
- 问题:某些特殊字符无法正确转换
- 解决:
- 使用utf-8编码处理多语言文本
- 对于特殊符号,使用unicode转义序列
- 在转换前进行字符替换
项目总结
这个文件编码转换工具提供了完整的解决方案,具有以下特点:
全面的编码支持:
- 支持12+种常见编码格式
- 智能检测无bom文件的编码
- 正确处理中文字符集
高效的转换引擎:
- 异步处理避免界面卡顿
- 批量转换支持
- 流式处理大文件
用户友好的界面:
- 直观的操作流程
- 详细的结果展示
- 实时的操作日志
- 进度和状态反馈
健壮的错误处理:
- 全面的异常捕获
- 详细的错误信息
- 可恢复的操作流程
扩展性设计:
- 模块化架构
- 易于添加新功能
- 支持插件式扩展
以上就是基于c#实现一个文件编码转换工具的详细内容,更多关于c#文件编码转换工具的资料请关注代码网其它相关文章!
发表评论