基于C#实现一个文件编码转换工具
作者:kaikaile1995
本文介绍了一个文件编码转换工具,支持多种编码格式转换,如UTF-8、GB2231222312、BIG5等,并具备智能编码检测、批量转换、自动添加后缀等功能,主窗体代码、程序入口及配置文件详细说明功能特点,需要的朋友可以参考下
文件编码转换工具,支持多种编码格式之间的转换,包括 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#文件编码转换工具的资料请关注脚本之家其它相关文章!
