WinForm程序追加写入多个Decimal到二进制文件,文件大小仅16字节异常
WinForm二进制文件写入异常问题分析与解决
问题场景
这段代码用于WinForm程序,功能是将界面上的TextBox和NumericUpDown控件值写入二进制文件,但出现异常:
- 界面包含10个以上TextBox或NumericUpDown控件(空文本框会写入
0.0m) - 执行代码后,二进制文件大小仅为16字节(单个decimal类型的字节数),而非预期的
16×n字节 - 已尝试显式调用
fs.Close(),问题仍未解决
原始代码
string regexSearch = new string(Path.GetInvalidFileNameChars()) + new string(Path.GetInvalidPathChars()); string filename = data_dir + DateTime.Now.ToString("yyyy-MM-dd HH.mm.ss") + ".bin"; Regex regex = new($"[{Regex.Escape(regexSearch)}]"); using (FileStream fs = new(filename, FileMode.Append, FileAccess.Write)) using (BinaryWriter writer = new(fs)) { foreach(Control item in Controls) { if (item is TextBox box) { decimal current = 0; try { current = Convert.ToDecimal(box.Text); } catch (Exception) { /* do nothing */ }; writer.Write(current); } else if (item is NumericUpDown numberbox) writer.Write(numberbox.Value); } MessageBox.Show("File saved to " + filename + ".", Text, MessageBoxButtons.OK, MessageBoxIcon.Information); }
问题原因
核心问题在于foreach(Control item in Controls):
这里的Controls仅包含当前窗体的直接子控件,如果目标TextBox/NumericUpDown是放在Panel、GroupBox、TabPage等容器控件内部的,遍历顶层Controls时只会拿到容器本身,无法访问容器内的子控件。最终只有顶层的目标控件会被写入(如果有的话),导致文件大小远小于预期。
解决方案
需要递归遍历所有控件,包括容器内的子控件。
步骤1:添加递归遍历控件的辅助方法
// 递归获取所有子控件(包括容器内的) private IEnumerable<Control> GetAllControls(Control parentControl) { foreach (Control control in parentControl.Controls) { yield return control; // 递归遍历当前控件的子控件 foreach (Control childControl in GetAllControls(control)) { yield return childControl; } } }
步骤2:修改遍历逻辑
将原代码中的foreach(Control item in Controls)替换为:
foreach(Control item in GetAllControls(this))
修改后的完整写入代码:
string regexSearch = new string(Path.GetInvalidFileNameChars()) + new string(Path.GetInvalidPathChars()); string filename = data_dir + DateTime.Now.ToString("yyyy-MM-dd HH.mm.ss") + ".bin"; Regex regex = new($"[{Regex.Escape(regexSearch)}]"); using (FileStream fs = new(filename, FileMode.Append, FileAccess.Write)) using (BinaryWriter writer = new(fs)) { // 递归遍历所有控件 foreach(Control item in GetAllControls(this)) { if (item is TextBox box) { decimal current = 0; try { current = Convert.ToDecimal(box.Text); } catch (Exception) { /* do nothing */ }; writer.Write(current); } else if (item is NumericUpDown numberbox) writer.Write(numberbox.Value); } MessageBox.Show("File saved to " + filename + ".", Text, MessageBoxButtons.OK, MessageBoxIcon.Information); }
额外检查点
- 确认
data_dir变量是否正确,确保文件保存路径没有问题 - 可以在遍历前添加调试输出,统计找到的TextBox/NumericUpDown数量,验证遍历逻辑是否生效:
var targetControls = GetAllControls(this).Where(c => c is TextBox || c is NumericUpDown).ToList(); MessageBox.Show($"找到 {targetControls.Count} 个目标控件");
内容的提问来源于stack exchange,提问作者0x00ac3375
相关产品推荐
相关产品推荐

