C# 将十六进制字符串转换为bytearray并写入文件

C# 将十六进制字符串转换为bytearray并写入文件,c#,.net,winforms,io,C#,.net,Winforms,Io,我编写了一个应用程序,使用C#从串行端口读取数据,并以十六进制字符串格式在文本框中显示数据。最后,我将所有数据保存到一个二进制文件中。如果数据很大(可能大于20mb),则会抛出内存不足错误。我怎样才能解决这个问题?这是我的密码: private void btn_Save_Click(object sender, EventArgs e) { SaveFileDialog save_log = new SaveFileDialog(); save_log.DefaultExt =

我编写了一个应用程序,使用C#从串行端口读取数据,并以十六进制字符串格式在文本框中显示数据。最后,我将所有数据保存到一个二进制文件中。如果数据很大(可能大于20mb),则会抛出内存不足错误。我怎样才能解决这个问题?这是我的密码:

private void btn_Save_Click(object sender, EventArgs e)
{
    SaveFileDialog save_log = new SaveFileDialog();
    save_log.DefaultExt = ".bin";
    save_log.Filter = "Binary File (*.bin)|*.bin";
    // Determine if the user selected a file name from the saveFileDialog.
    if (save_log.ShowDialog() == System.Windows.Forms.DialogResult.OK &&
        save_log.FileName.Length > 0)
    {
        try
        {
            string hexString = Content.Text.ToString();
            FileStream stream = new FileStream(save_log.FileName, FileMode.Create, FileAccess.ReadWrite);
            stream.Write(Hex_to_ByteArray(hexString), 0, Hex_to_ByteArray(hexString).Length);
            stream.Close();
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }
}

private byte[] Hex_to_ByteArray(string s)
{
    s = s.Replace(" ", "");
    byte[] buffer = new byte[s.Length / 2];
    for (int i = 0; i < s.Length; i += 2)
    {
        buffer[i / 2] = (byte)Convert.ToByte(s.Substring(i, 2), 16);
    }
    return buffer;
}
private void btn\u保存\u单击(对象发送方,事件参数e)
{
SaveFileDialog save_log=新建SaveFileDialog();
保存_log.DefaultExt=“.bin”;
保存_log.Filter=“二进制文件(*.bin)|*.bin”;
//确定用户是否从“保存文件”对话框中选择了文件名。
如果(save_log.ShowDialog()==System.Windows.Forms.DialogResult.OK&&
保存(log.FileName.Length>0)
{
尝试
{
字符串hexString=Content.Text.ToString();
FileStream stream=新FileStream(save_log.FileName,FileMode.Create,FileAccess.ReadWrite);
stream.Write(十六进制到字节数组(hexString),0,十六进制到字节数组(hexString).Length);
stream.Close();
}
捕获(例外情况除外)
{
MessageBox.Show(例如Message);
}
}
}
专用字节[]十六进制到字节数组(字符串s)
{
s=s。替换(“,”);
字节[]缓冲区=新字节[s.Length/2];
对于(int i=0;i
使用IEnumerable。这将避免使用大字节数组

我不知道Content.Text里有什么。如果它是一个字节数组,也许您可以更改

static internal IEnumerable<byte>Hex_to_Byte(string s)
静态内部IEnumerableHex_到_字节(字符串s)
进入

静态内部IEnumerableHex_到_字节(字节[]字节)
然后稍微修改一下代码

FileStream stream = new FileStream(save_log.FileName, FileMode.Create, FileAccess.ReadWrite);
foreach( byte b in Hex_to_Byte(hexString) )
    stream.WriteByte(b);
stream.Close();



    static internal IEnumerable<byte>Hex_to_Byte(string s)
    {
        bool haveFirstByte = false;
        int firstByteValue = 0;

        foreach( char c in s)
        {
            if( char.IsWhiteSpace(c))
                continue;

            if( !haveFirstByte)
            {
                haveFirstByte = true;
                firstByteValue = GetHexValue(c) << 4;
            }
            else
            {
                haveFirstByte = false;
                yield return unchecked((byte)(firstByteValue + GetHexValue(c)));
            }

        }

    }
    static string hexChars = "0123456789ABCDEF";
    static int GetHexValue(char c)
    {
        int v = hexChars.IndexOf(char.ToUpper(c));
        if (v < 0)
            throw new ArgumentOutOfRangeException("c", string.Format("not a hex char: {0}"));
        return v;
    }
FileStream-stream=newfilestream(保存log.FileName、FileMode.Create、FileAccess.ReadWrite);
foreach(十六进制字节b到字节(十六进制字符串))
stream.WriteByte(b);
stream.Close();
静态内部IEnumerableHex_到_字节(字符串s)
{
bool haveFirstByte=false;
int firstByteValue=0;
foreach(字符c在s中)
{
if(char.IsWhiteSpace(c))
继续;
如果(!haveFirstByte)
{
haveFirstByte=true;

firstByteValue=GetHexValue(c)使用IEnumerable。这将避免使用大字节数组

我不知道Content.Text中有什么。如果是字节数组,也许你可以更改

static internal IEnumerable<byte>Hex_to_Byte(string s)
静态内部IEnumerableHex_到_字节(字符串s)
进入

静态内部IEnumerableHex_到_字节(字节[]字节)
然后稍微修改一下代码

FileStream stream = new FileStream(save_log.FileName, FileMode.Create, FileAccess.ReadWrite);
foreach( byte b in Hex_to_Byte(hexString) )
    stream.WriteByte(b);
stream.Close();



    static internal IEnumerable<byte>Hex_to_Byte(string s)
    {
        bool haveFirstByte = false;
        int firstByteValue = 0;

        foreach( char c in s)
        {
            if( char.IsWhiteSpace(c))
                continue;

            if( !haveFirstByte)
            {
                haveFirstByte = true;
                firstByteValue = GetHexValue(c) << 4;
            }
            else
            {
                haveFirstByte = false;
                yield return unchecked((byte)(firstByteValue + GetHexValue(c)));
            }

        }

    }
    static string hexChars = "0123456789ABCDEF";
    static int GetHexValue(char c)
    {
        int v = hexChars.IndexOf(char.ToUpper(c));
        if (v < 0)
            throw new ArgumentOutOfRangeException("c", string.Format("not a hex char: {0}"));
        return v;
    }
FileStream-stream=newfilestream(保存log.FileName、FileMode.Create、FileAccess.ReadWrite);
foreach(十六进制字节b到字节(十六进制字符串))
stream.WriteByte(b);
stream.Close();
静态内部IEnumerableHex_到_字节(字符串s)
{
bool haveFirstByte=false;
int firstByteValue=0;
foreach(字符c在s中)
{
if(char.IsWhiteSpace(c))
继续;
如果(!haveFirstByte)
{
haveFirstByte=true;

firstByteValue=GetHexValue(c)您将创建两次字节数组。此外,对如此长的字符串使用
.Replace
也没有帮助。您可以避免所有这些:

try
{
    var stream = new FileStream(
        save_log.FileName,
        FileMode.Create,
        FileAccess.ReadWrite);

    WriteHexStringToFile(Content.Text, stream);

    stream.Close();
}
catch (Exception ex)
{
    MessageBox.Show(ex.Message);
}

private void WriteHexStringToFile(string hexString, FileStream stream)
{
    var twoCharacterBuffer = new StringBuilder();
    var oneByte = new byte[1];
    foreach (var character in hexString.Where(c => c != ' '))
    {
        twoCharacterBuffer.Append(character);

        if (twoCharacterBuffer.Length == 2)
        {
            oneByte[0] = (byte)Convert.ToByte(twoCharacterBuffer.ToString(), 16);
            stream.Write(oneByte, 0, 1);
            twoCharacterBuffer.Clear();
        }
    }
}
另外,看看和/或哪一个可以为您完成所有这些

更新:

首先,请注意,您将兆字节数据存储在字符串中的想法完全是胡说八道,您不应该这样做。您应该将数据分成更小的部分进行处理。由于这种胡说八道,我无法为您提供一个可用的演示(例如在IDEONE上),因为在线编译器的资源限制。我已经在我的机器上测试了代码,正如你所看到的,我甚至可以处理50 MB的字符串-但这一切都取决于你可用的内存量。如果你这样做,那么在每台机器上都很容易达到可用内存的限制。以及你在本文中询问的方法具体问题与此无关-问题是因为您的
内容.Text
字符串中充满了大量数据。当内存几乎满时,
OutOfMemoryException
几乎可以发生在代码中的任何位置

您可以在浏览器中查看整个图片以查看所有详细信息


您要创建两次字节数组。而且,对如此长的字符串使用
.Replace
也没有帮助。您可以避免所有这些:

try
{
    var stream = new FileStream(
        save_log.FileName,
        FileMode.Create,
        FileAccess.ReadWrite);

    WriteHexStringToFile(Content.Text, stream);

    stream.Close();
}
catch (Exception ex)
{
    MessageBox.Show(ex.Message);
}

private void WriteHexStringToFile(string hexString, FileStream stream)
{
    var twoCharacterBuffer = new StringBuilder();
    var oneByte = new byte[1];
    foreach (var character in hexString.Where(c => c != ' '))
    {
        twoCharacterBuffer.Append(character);

        if (twoCharacterBuffer.Length == 2)
        {
            oneByte[0] = (byte)Convert.ToByte(twoCharacterBuffer.ToString(), 16);
            stream.Write(oneByte, 0, 1);
            twoCharacterBuffer.Clear();
        }
    }
}
另外,看看和/或哪一个可以为您完成所有这些

更新:

首先,请注意,您将兆字节数据存储在字符串中的想法完全是胡说八道,您不应该这样做。您应该将数据分成更小的部分进行处理。由于这种胡说八道,我无法为您提供一个可用的演示(例如在IDEONE上),因为在线编译器的资源限制。我已经在我的机器上测试了代码,正如你所看到的,我甚至可以处理50 MB的字符串-但这一切都取决于你可用的内存量。如果你这样做,那么在每台机器上都很容易达到可用内存的限制。以及你在本文中询问的方法具体问题与此无关-问题是因为您的
内容.Text
字符串中充满了大量数据。当内存几乎满时,
OutOfMemoryException
几乎可以发生在代码中的任何位置

您可以在浏览器中查看整个图片以查看所有详细信息


如果您拥有从串行端口读取的数据(可能采用
字节[]
格式),为什么不保留它,并在需要时将其写入文件?这样,您就不必将十六进制字符串转换回二进制。这是个好主意,但并不能解决我的问题。不要自己做任何事情。使用
编码
。如果您有从串行端口读取的数据(在
字节[]中),此源代码可能会对您有所帮助