C# 无例外地将字符串转换为ASCII(如TryParse)

C# 无例外地将字符串转换为ASCII(如TryParse),c#,string,ascii,asciiencoding,C#,String,Ascii,Asciiencoding,我正在为ASCII字符串类实现一个TryParse()方法。该方法获取字符串并将其转换为C样式的字符串(即以null结尾的ASCII字符串) 我只使用了一个Parse(),使用以下命令将其转换为ASCII: public static bool Parse(string s, out byte[] result) { result = null; if (s == null || s.Length < 1) return false; byte[]

我正在为ASCII字符串类实现一个
TryParse()
方法。该方法获取字符串并将其转换为C样式的字符串(即以null结尾的ASCII字符串)

我只使用了一个
Parse()
,使用以下命令将其转换为ASCII:

public static bool Parse(string s, out byte[] result)
{
    result = null;
    if (s == null || s.Length < 1)
        return false;

    byte[]d = new byte[s.Length + 1]; // Add space for null-terminator
    System.Text.Encoding.ASCII.GetBytes(s).CopyTo(d, 0); 
    // GetBytes can throw exceptions 
    // (so can CopyTo() but I can replace that with a loop)
    result = d;
    return true;
}
公共静态bool解析(字符串s,输出字节[]结果)
{
结果=空;
如果(s==null | | s.长度<1)
返回false;
byte[]d=新字节[s.Length+1];//为空终止符添加空间
System.Text.Encoding.ASCII.GetBytes(s).CopyTo(d,0);
//GetBytes可以引发异常
//(CopyTo()也可以,但我可以用循环替换)
结果=d;
返回true;
}
然而,TryParse的一部分思想是消除异常的开销,并且
GetBytes()
抛出异常,因此我正在寻找一种不这样做的不同方法

也许有一种类似于
TryGetbytes()
的方法

或者我们可以对标准.Net
字符串的预期格式进行推理,并以数学方式执行更改(我对UTF编码不太熟悉)

编辑:我想对于字符串中的非ASCII字符,
TryParse()
方法应该返回
false


编辑:我希望当我开始为这个类实现
ToString()
方法时,我可能需要在那里执行相反的操作。

GetBytes
方法正在引发异常,因为您指定它应该引发异常

使用
EncoderReplacementFallback
创建编码对象,以避免不可编码字符出现异常

Encoding encodingWithFallback = new ASCIIEncoding() { DecoderFallback = DecoderFallback.ReplacementFallback };
encodingWithFallback.GetBytes("Hɘ££o wor£d!");
这种方式模仿了原始.NET值类型的
TryParse
方法:

bool TryEncodingToASCII(string s, out byte[] result)
{
    if (s == null || Regex.IsMatch(s, "[^\x00-\x7F]")) // If a single ASCII character is found, return false.
    {
        result = null;
        return false;
    }
    result = Encoding.ASCII.GetBytes(s); // Convert the string to ASCII bytes.
    return true;
}

GetBytes
方法正在引发异常,因为您指定它应该引发异常

使用
EncoderReplacementFallback
创建编码对象,以避免不可编码字符出现异常

Encoding encodingWithFallback = new ASCIIEncoding() { DecoderFallback = DecoderFallback.ReplacementFallback };
encodingWithFallback.GetBytes("Hɘ££o wor£d!");
这种方式模仿了原始.NET值类型的
TryParse
方法:

bool TryEncodingToASCII(string s, out byte[] result)
{
    if (s == null || Regex.IsMatch(s, "[^\x00-\x7F]")) // If a single ASCII character is found, return false.
    {
        result = null;
        return false;
    }
    result = Encoding.ASCII.GetBytes(s); // Convert the string to ASCII bytes.
    return true;
}

Encoding.GetBytes
可能会引发两个异常

ArgumentNullException
很容易避免。对您的输入执行空检查,您可以确保不会抛出此错误

encoderCallbackException
需要进一步调查

回退策略确定编码器如何处理无效字符或解码器如何处理无效字节

如果我们在地图上看到:

它使用替换回退将无法编码的每个字符串和无法解码的每个字节替换为问号(“?”)字符

这意味着它不使用异常回退,因此永远不会抛出
EncoderFallbackException


总之,如果您使用ASCII编码并确保不传入空字符串,那么调用
GetBytes

将永远不会引发异常
编码有两种可能的异常

ArgumentNullException
很容易避免。对您的输入执行空检查,您可以确保不会抛出此错误

encoderCallbackException
需要进一步调查

回退策略确定编码器如何处理无效字符或解码器如何处理无效字节

如果我们在地图上看到:

它使用替换回退将无法编码的每个字符串和无法解码的每个字节替换为问号(“?”)字符

这意味着它不使用异常回退,因此永远不会抛出
EncoderFallbackException

总之,如果您使用ASCII编码并确保不传入空字符串,那么调用
GetBytes

将永远不会引发异常两个选项:

您可以完全忽略
编码
,自己编写循环:

public static bool TryParse(string s, out byte[] result)
{
    result = null;
    // TODO: It's not clear why you don't want to be able to convert an empty string
    if (s == null || s.Length < 1)
    {
        return false;
    }

    byte buffer = new byte[s.Length + 1]; // Add space for null-terminator
    for (int i = 0; i < s.Length; i++)
    {
        char c = s[i];
        if (c > 127)
        {
            return false;
        }
        buffer[i] = (byte) c;
    }
    result = buffer;
    return true;
}
不过,这需要编写
CustomFallback
——它基本上需要跟踪是否曾被要求处理无效输入

如果您不介意对数据进行两次编码处理,可以使用基于UTF-8的编码和替换回退(使用非ASCII替换字符)调用
encoding.GetByteCount
,并检查其返回的字节数是否与字符串中的字符数相同。如果是,则调用
Encoding.ASCII.GetBytes

就我个人而言,我会选择第一个选项,除非你有理由相信它太慢。

两个选项:

您可以完全忽略
编码
,自己编写循环:

public static bool TryParse(string s, out byte[] result)
{
    result = null;
    // TODO: It's not clear why you don't want to be able to convert an empty string
    if (s == null || s.Length < 1)
    {
        return false;
    }

    byte buffer = new byte[s.Length + 1]; // Add space for null-terminator
    for (int i = 0; i < s.Length; i++)
    {
        char c = s[i];
        if (c > 127)
        {
            return false;
        }
        buffer[i] = (byte) c;
    }
    result = buffer;
    return true;
}
不过,这需要编写
CustomFallback
——它基本上需要跟踪是否曾被要求处理无效输入

如果您不介意对数据进行两次编码处理,可以使用基于UTF-8的编码和替换回退(使用非ASCII替换字符)调用
encoding.GetByteCount
,并检查其返回的字节数是否与字符串中的字符数相同。如果是,则调用
Encoding.ASCII.GetBytes


就个人而言,我会选择第一个选项,除非你有理由相信它太慢。

GetBytes
主要抛出一个异常
ArgumentNullException
,你可以很容易地进行检查……我认为ASCII转换不会抛出一个回退异常(除了NRE)是GetBytes将抛出的唯一一件事,因为所有单字节都可以在单字节编码中转换。@Pikoh-确实可以,但正如我所说的,这个想法是为了消除异常的开销(大部分想法是这样的),现在还不清楚您实际上在“解析”什么。(这听起来不像是