Lop*_*per 26 c# string encoding class quoted-printable
C#中是否存在可以将Quoted-Printable编码转换为String?的现有类?单击上面的链接以获取有关编码的更多信息.
为方便起见,以上链接引用了以下内容.
任何8位字节的值可以与3个字符,被编码的"="随后两个十六进制数字(0-9或A-F)表示的字节的数值.例如,US-ASCII换页符(十进制值12)可以用"= 0C"表示,US-ASCII等号(十进制值61)用"= 3D"表示.除了可打印的ASCII字符或行尾字符之外的所有字符都必须以这种方式编码.
除"="(十进制61)外,所有可打印的ASCII字符(33到126之间的十进制值)可以由它们自己表示.
ASCII选项卡和空格字符,十进制值9和32,可以由它们自己表示,除非这些字符出现在一行的末尾.如果其中一个字符出现在一行的末尾,则必须将其编码为"= 09"(制表符)或"= 20"(空格).
如果正在编码的数据包含有意义的换行符,则必须将它们编码为ASCII CR LF序列,而不是其原始字节值.相反,如果字节值13和10具有除行尾之外的含义,则它们必须被编码为= 0D和= 0A.
引用可打印编码数据的行不得超过76个字符.为了在不改变编码文本的情况下满足该要求,可以根据需要添加软换行符.软换行符在编码行的末尾包含"=",并且不会在解码的文本中导致换行符.
Dav*_*ave 19
框架库中有一些功能可以做到这一点,但它看起来并没有干净利落.实现在内部类中System.Net.Mime.QuotedPrintableStream.这个类定义了一个叫做DecodeBytes你想要的方法.该方法似乎仅由一种用于解码MIME头的方法使用.此方法也是内部的,但在几个地方相当直接调用,例如Attachment.Namesetter.示范:
using System;
using System.Net.Mail;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Attachment attachment = Attachment.CreateAttachmentFromString("", "=?iso-8859-1?Q?=A1Hola,_se=F1or!?=");
Console.WriteLine(attachment.Name);
}
}
}
Run Code Online (Sandbox Code Playgroud)
产生输出:
¡HOLA,_señor!
您可能必须进行一些测试以确保正确处理回车等,尽管我们似乎做了一个快速测试.但是,依赖此功能可能不明智,除非您的用例足够接近解码MIME头字符串,您认为它不会被对库所做的任何更改破坏.你可能最好编写自己的引用可打印解码器.
小智 18
我扩展了Martin Murphy的解决方案,我希望它能适用于所有情况.
private static string DecodeQuotedPrintables(string input, string charSet)
{
if (string.IsNullOrEmpty(charSet))
{
var charSetOccurences = new Regex(@"=\?.*\?Q\?", RegexOptions.IgnoreCase);
var charSetMatches = charSetOccurences.Matches(input);
foreach (Match match in charSetMatches)
{
charSet = match.Groups[0].Value.Replace("=?", "").Replace("?Q?", "");
input = input.Replace(match.Groups[0].Value, "").Replace("?=", "");
}
}
Encoding enc = new ASCIIEncoding();
if (!string.IsNullOrEmpty(charSet))
{
try
{
enc = Encoding.GetEncoding(charSet);
}
catch
{
enc = new ASCIIEncoding();
}
}
//decode iso-8859-[0-9]
var occurences = new Regex(@"=[0-9A-Z]{2}", RegexOptions.Multiline);
var matches = occurences.Matches(input);
foreach (Match match in matches)
{
try
{
byte[] b = new byte[] { byte.Parse(match.Groups[0].Value.Substring(1), System.Globalization.NumberStyles.AllowHexSpecifier) };
char[] hexChar = enc.GetChars(b);
input = input.Replace(match.Groups[0].Value, hexChar[0].ToString());
}
catch { }
}
//decode base64String (utf-8?B?)
occurences = new Regex(@"\?utf-8\?B\?.*\?", RegexOptions.IgnoreCase);
matches = occurences.Matches(input);
foreach (Match match in matches)
{
byte[] b = Convert.FromBase64String(match.Groups[0].Value.Replace("?utf-8?B?", "").Replace("?UTF-8?B?", "").Replace("?", ""));
string temp = Encoding.UTF8.GetString(b);
input = input.Replace(match.Groups[0].Value, temp);
}
input = input.Replace("=\r\n", "");
return input;
}
Run Code Online (Sandbox Code Playgroud)
我写得很快.
public static string DecodeQuotedPrintables(string input)
{
var occurences = new Regex(@"=[0-9A-H]{2}", RegexOptions.Multiline);
var matches = occurences.Matches(input);
var uniqueMatches = new HashSet<string>(matches);
foreach (string match in uniqueMatches)
{
char hexChar= (char) Convert.ToInt32(match.Substring(1), 16);
input =input.Replace(match, hexChar.ToString());
}
return input.Replace("=\r\n", "");
}
Run Code Online (Sandbox Code Playgroud)
我一直在寻找动态解决方案,并花了 2 天尝试不同的解决方案。该解决方案将支持日语字符和其他标准字符集
private static string Decode(string input, string bodycharset) {
var i = 0;
var output = new List<byte>();
while (i < input.Length) {
if (input[i] == '=' && input[i + 1] == '\r' && input[i + 2] == '\n') {
//Skip
i += 3;
} else if (input[i] == '=') {
string sHex = input;
sHex = sHex.Substring(i + 1, 2);
int hex = Convert.ToInt32(sHex, 16);
byte b = Convert.ToByte(hex);
output.Add(b);
i += 3;
} else {
output.Add((byte)input[i]);
i++;
}
}
if (String.IsNullOrEmpty(bodycharset))
return Encoding.UTF8.GetString(output.ToArray());
else {
if (String.Compare(bodycharset, "ISO-2022-JP", true) == 0)
return Encoding.GetEncoding("Shift_JIS").GetString(output.ToArray());
else
return Encoding.GetEncoding(bodycharset).GetString(output.ToArray());
}
}
Run Code Online (Sandbox Code Playgroud)
然后你可以调用该函数
Decode("=E3=82=AB=E3=82=B9=E3", "utf-8")
Run Code Online (Sandbox Code Playgroud)
这最初是在这里找到的
小智 5
如果您要使用UTF-8编码解码带引号的可打印字符,则需要注意,不能同时解码每个带引号的可打印序列,因为如果同时存在多个带引号的可打印字符,则无法一次解码每个带引号的可打印序列。
例如-如果您具有以下序列= E2 = 80 = 99并一次使用UTF8对其进行解码,则会得到三个“怪异”字符-如果您改为构建一个由三个字节组成的数组,并用如果使用UTF8编码,您将得到一个单胶体。
显然,如果您使用的是ASCII编码,那么一次一次就没问题,但是解码运行意味着您的代码将可以使用,而与所使用的文本编码器无关。
哦,别忘了= 3D是一种特殊情况,这意味着您需要再解码一次,这真是一个疯狂的陷阱!
希望能有所帮助