为什么使用字符数组保存密码比使用String保存密码更好?

java中为什么不用string保存密码,而是使用的字符数组来存储?

1)由于String在Java中是不可变的,如果你将密码以明文的形式保存成字符串,那么它将一直留在内存中,直到垃圾收集器把它清除。而由于字符串被放在字符串缓冲池中以方便重复使用,所以它就可能在内存中被保留很长时间,而这将导致安全隐患,因为任何能够访问内存(memory dump内存转储)的人都能清晰的看到文本中的密码,这也是为什么你应该总是使用加密的形式而不是明文来保存密码。由于字符串是不可变的,所以没有任何方式可以修改字符串的值,因为每次修改都将产生新的字符串,然而如果你使用char[]来保存密码,你仍然可以将其中所有的元素都设置为空或者零。所以将密码保存到字符数组中很明显的降低了密码被窃取的风险。

2)Java本身也推荐使用JPasswordField组件的getPassword()方法,该方法将返回一个字符数组,而放弃了原来的getText()方法,这个方法把密码以明文的形式返回而可能会引起安全问题。所以,最好能听从来自Java团队的建议并且坚持标准,而不是去反对它。

3)使用字符串,在将文本输出到日志文件或者控制台的时候会存在风险。但是使用数组你不会把数组的内容打印出来,相反,打印出来的是数组在内存中的位置。尽管这算不上一个真正的原因,但这仍然很有意义。
String strPassword="Unknown";
char[] charPassword= new char[]{'U','n','k','w','o','n'};
System.out.println("String password: " + strPassword);
System.out.println("Character password: " + charPassword);

String password: Unknown
Character password: [C@110b053

这就是全部的关于为什么使用字符数组存储密码比字符串更好。只使用字符数组也是不够的,为了更安全你需要将数组内容进行转化。我也建议使用哈希的或者是加密过的密码而不是明文,然后一旦完成验证,就将它从内存中清除掉。

原文地址:http://javarevisited.blogspot.com/2012/03/why-character-array-is-better-than.html#ixzz2guhpuUJO

如果你觉得本篇对你有收获,请帮顶。
另外,我本人开通了微信公众号--分享技术之美,我会不定期的分享一些我学习的东西.
你可以搜索公众号:swalge 或者扫描下方二维码关注我


(转载文章请注明出处: http://blog.youkuaiyun.com/swagle/article/details/24453257 )
在 C# 中,我们可以使用数组来保存 `.txt` 文件的每一行数据,而是使用 `DataTable` 来结构化地存储所有行,并在后续处理中遍历这个表。虽然文本文件是纯行式数据(无固定列),但我们仍可以将每行拆分为多个字段并存入 `DataTable` 的列中。 以下是 **完整示例代码**: 用户选择一个 `.txt` 文件 → 程序逐行读取 → 按逗号分隔 → 存入 `DataTable` → 遍历 DataTable 查找包含 `"EXP INFO"` 的行 → 输出第4个字段(索引3)。 ```csharp using System; using System.Data; using System.IO; using System.Windows.Forms; namespace ReadTxtToDataTable { public class Program { [STAThread] public static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); using (OpenFileDialog openFileDialog = new OpenFileDialog()) { openFileDialog.Filter = "Text files (*.txt)|*.txt|All files (*.*)|*.*"; openFileDialog.Title = "请选择一个文本文件"; if (openFileDialog.ShowDialog() == DialogResult.OK) { string filePath = openFileDialog.FileName; try { // 创建 DataTable 来存储所有行的数据 DataTable dataTable = new DataTable("TextFileData"); // 添加一列用于存储原始行内容(可选) dataTable.Columns.Add("RawLine", typeof(string)); // 可选:添加动态列(如 Field0, Field1...),这里我们只保留原始行 + 分割后的处理 // 实际上我们会把每个分割字段都作为列存进去,而是在遍历时临时 split // 使用 StreamReader 逐行读取,节省内存(适合大文件) using (StreamReader reader = new StreamReader(filePath)) { string line; while ((line = reader.ReadLine()) != null) { dataTable.Rows.Add(line); // 只存原始行,分割留到后面处理 } } Console.WriteLine("开始处理 DataTable 中的数据:"); Console.WriteLine(new string('-', 50)); // 遍历 DataTable 的每一行 foreach (DataRow row in dataTable.Rows) { string rawLine = row["RawLine"].ToString(); if (rawLine.Contains("EXP INFO")) { string[] parts = rawLine.Split(','); if (parts.Length >= 4) { string fourthField = parts[3].Trim(); Console.WriteLine($"【匹配行】第4个字段: {fourthField}"); } else { Console.WriteLine($"【警告】字段足4个,跳过该行:{rawLine}"); } } } Console.WriteLine(new string('-', 50)); Console.WriteLine("处理完成。按任意键退出..."); } catch (Exception ex) { Console.WriteLine($"发生错误:{ex.Message}"); } } else { Console.WriteLine("未选择文件,程序退出。"); } } Console.ReadKey(); } } } ``` --- ### ✅ 解释: 1. **`DataTable` 的作用** - 我们创建了一个名为 `TextFileData` 的 `DataTable`。 - 它只有一个列 `RawLine`,用来保存从文件中读取的每一行原始字符串。 - 这样做的好处是:你可以后续对这个表做查询、绑定到 UI 控件(如 DataGridView)、导出等操作。 2. **为什么用多列存储 split 后的结果?** 因为 `.txt` 文件通常是定长字段(每行列数同),所以很难预先定义列。因此我们先只存原始行,在需要时再动态 `Split()` 处理。 3. **使用 `StreamReader` 替代 `File.ReadAllLines`** - 更节省内存,尤其适用于大文件。 - 一行一行读入并加入 `DataTable`,避免一次性加载全部内容到数组。 4. **仍然基于条件判断和 split 提取第四个字段** - 在遍历 `DataTable.Rows` 时,取出 `RawLine` 字段。 - 判断是否包含 `"EXP INFO"`。 - 按逗号分割后取 `parts[3]`。 5. **扩展性好** - 以后如果要将这些数据展示在 WinForms 的 `DataGridView` 上,只需设置: ```csharp dataGridView1.DataSource = dataTable; ``` --- ### 示例输出(基于之前的数据): ``` 开始处理 DataTable 中的数据: -------------------------------------------------- 【匹配行】第4个字段: VALUE:A1B2C3 【匹配行】第4个字段: RUN_ID:XYZ789 -------------------------------------------------- 处理完成。按任意键退出... ``` --- ### 💡 提示:如果你想把 split 字段也存进 DataTable(高级用法) 你也可以设计一个更复杂的 `DataTable`,比如有 `Field0`, `Field1`, ..., 或者命名列: ```csharp // 动态添加列(最多需要几列?) for (int i = 0; i < 10; i++) { dataTable.Columns.Add($"Field{i}", typeof(string)); } ``` 然后插入时: ```csharp string[] parts = line.Split(','); DataRow newRow = dataTable.NewRow(); newRow["RawLine"] = line; for (int i = 0; i < parts.Length && i < 10; i++) { newRow[$"Field{i}"] = parts[i].Trim(); } dataTable.Rows.Add(newRow); ``` 这样就可以直接通过列访问 `row["Field3"]` 来获取第四个字段。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值