-1

我想创建一个十六进制编辑器来打开大型二进制文件。这是我的代码。它适用于小文件。但是当我打开大文件时,十六进制编辑器面临问题。

data[] ... array of byte

string str = "";
byte[] temp = null;
int i;
for (i = 0; i < (data.Length - 16); i += 16)
{
    temp = _sub_array(data, i, 16);
    str += BitConverter.ToString(temp).Replace("-", "\t");
    str += "\n";
}

temp = _sub_array(data, i, (data.Length - i));
str += BitConverter.ToString(temp).Replace("-", "\t");

richTextBox.Text = str;
4

2 回答 2

1

正如评论中所说,您应该尽量避免一次读取整个文件。但是,如果您一次需要整个文件在内存中,我认为您的主要问题可能是程序在读取和转换数据时会遇到的“粘性”。您更明智地使用单独的线程进行十六进制工作,并让主线程专注于保持您的 UI 运行顺畅。无论哪种方式,您也可以使用任务而不是线程。所以使用你的代码片段,让它看起来更像这样:

data[] ... array of byte

private void button1_Click(object sender, EventArgs e)
{
    Thread t = new Thread(readHexFile);
    t.Start();
}

private void readHexFile()
{
    string str = "";
    byte[] temp = null;
    int i;
    for (i = 0; i < (data.Length - 16); i += 16)
    {
        temp = _sub_array(data, i, 16);
        str += BitConverter.ToString(temp).Replace("-", "\t");
        str += "\n";
    }

    temp = _sub_array(data, i, (data.Length - i));
    str += BitConverter.ToString(temp).Replace("-", "\t");

    BeginInvoke(new Action(()=> richTextBox.Text = str));
}

您需要添加“使用 System.Threading”才能访问线程。还要注意 BeginInvoke 与 richTextBox.Text 在 lambda 表达式中的工作。当您在单独的线程上运行数据处理时,这是必要的,因为如果您尝试使用该线程直接访问文本框,Windows 将抱怨跨线程调用。只有创建控件的线程才被允许直接访问它。BeginInvoke 不直接访问控件,因此您可以从数据处理线程中使用它来获取写入控件的文本。这将阻止数据处理“破坏” UI 响应能力。

如果你从来没有做过,这可能看起来很吓人,但相信我。如果你掌握了线程和任务的窍门(它们在机器内部是不同的,但可以由类似的开发人员工具操作),你将永远不想再次从主线程渲染到 UI。

编辑:我保留了您代码中的字符串,但我同意建议使用 StringBuilder 的评论。字符串是不可变的,所以每次你连接到字符串时,在内部发生的事情是整个字符串被废弃,并且正在使用附加文本创建一个新字符串。所以,是的,也要切换到 StringBuilder 对象。

于 2015-08-03T21:55:04.393 回答
1

所以你有小文件的工作代码,但你面临大文件的问题。你没有提到这些问题是什么所以这里有一些猜测:

  • 如果您将整个文件加载到 abyte[]中,那么您可能会遇到内存问题并可能抛出一个OutOfMemoryException
  • 您正在string反复连接 a 。这不仅是内存问题,也是性能问题(参考 Jon Skeet 的文章http://www.yoda.arachsys.com/csharp/stringbuilder.html
  • _sub_array()被重复调用并返回 16 length byte[],这是另一个内存和性能问题。
  • String.Replace()反复调用(参见项目符号 2)。

我认为这些是内存问题,因为我们不知道垃圾收集器何时会清理内存。

所以让我们解决这些潜在的问题:

  • 一次读取 16 个字节的文件(@EZI 评论),这也消除了对_sub_array(). 查看FileStream类以一次读取 16 个字节。
  • BitConverter.ToString()将这 16 个字节放入一个StringBuilderwith StringBuilder.AppendLine()(我的评论)中,但在String.Replace()你读完文件之前不要这样做。
  • 读完文件后,您可以将 分配StringBuilder给您的RichTextBox喜欢(sb 是用于 的变量名StringBuilder):richTextBox.Text = sb.ToString();

希望这可以帮助...

于 2015-08-04T00:23:38.503 回答