Skip to content

Instantly share code, notes, and snippets.

@stdray
Created November 25, 2015 17:04
Show Gist options
  • Select an option

  • Save stdray/6f06da01235b7223ca27 to your computer and use it in GitHub Desktop.

Select an option

Save stdray/6f06da01235b7223ca27 to your computer and use it in GitHub Desktop.
public static class EncodingHelper
{
static readonly ConcurrentDictionary<Encoding, Encoding> CheckEncodingCache =
new ConcurrentDictionary<Encoding, Encoding>();
static readonly ConcurrentDictionary<Encoding, Encoding> ReplaceEncodingCache =
new ConcurrentDictionary<Encoding, Encoding>();
static readonly Encoding EncodingCP1251 = Encoding.GetEncoding(1251);
public static string ToCP1251(this string str, string replaceStr = "")
{
return Encode(EncodingCP1251, str, replaceStr);
}
public static string Encode(Encoding encoding, string str, string replaceStr = "")
{
if (CanEncode(encoding, str))
return str;
var replaceEncoding = GetReplaceEncoding(encoding, replaceStr);
var src = Encoding.Unicode.GetBytes(str);
var res = Encoding.Convert(Encoding.Unicode, replaceEncoding, src);
return encoding.GetString(res);
}
public static bool CanEncode(Encoding encoding, string str)
{
if (string.IsNullOrEmpty(str))
return true;
var enc = GetCheckEncoding(encoding);
var arr = new char[1];
for (var i = 0; i < str.Length; i++)
{
arr[0] = str[i];
if (enc.GetByteCount(arr, 0, 1) < 1)
return false;
}
return true;
}
static Encoding GetCheckEncoding(Encoding encoding)
{
return CheckEncodingCache.GetOrAdd(encoding, e =>
{
var enc = (Encoding)e.Clone();
enc.EncoderFallback = new EncoderFallbackCheckExists();
return enc;
});
}
static Encoding GetReplaceEncoding(Encoding encoding, string replaceStr)
{
return ReplaceEncodingCache.GetOrAdd(encoding, e =>
{
var enc = (Encoding)e.Clone();
enc.EncoderFallback = new EncoderReplacementFallback(replaceStr);
enc.DecoderFallback = new DecoderReplacementFallback(replaceStr);
return enc;
});
}
#region Classes
class EncoderFallbackCheckExists : EncoderFallback
{
public override int MaxCharCount { get { return 1; } }
public override EncoderFallbackBuffer CreateFallbackBuffer()
{
return new FallbackBufferCheckExists();
}
}
class FallbackBufferCheckExists : EncoderFallbackBuffer
{
public override int Remaining
{
get { return 0; }
}
public override bool Fallback(char charUnknown, int index)
{
return false;
}
public override bool Fallback(char charUnknownHigh, char charUnknownLow, int index)
{
return false;
}
public override char GetNextChar()
{
return '\0';
}
public override bool MovePrevious()
{
return false;
}
}
#endregion
}
[TestFixture]
public class EncodingHelperTests
{
[TestCase(true, 1251, null)]
[TestCase(true, 1251, "")]
[TestCase(true, 1251, "asdad")]
[TestCase(true, 1251, "абвгода")]
[TestCase(true, 1250, "\x015f")]
[TestCase(false, 1252, "\x015f")]
[TestCase(false, 1250, "\x00fe")]
[TestCase(true, 1252, "\x00fe")]
[TestCase(false, 1251, "2183273-1-2")]
public void CanEncode_ShouldBeExpexted(bool expected, int codePage, string str)
{
var enc = Encoding.GetEncoding(codePage);
var res = EncodingHelper.CanEncode(enc, str);
Assert.AreEqual(expected, res);
}
[TestCase(null, 1251, null)]
[TestCase("", 1251, "")]
[TestCase("asdad", 1251, "asdad")]
[TestCase("абвгода", 1251, "абвгода")]
[TestCase("\x015f", 1250, "\x015f")]
[TestCase("", 1252, "\x015f")]
[TestCase("", 1250, "\x00fe")]
[TestCase("\x00fe", 1252, "\x00fe")]
[TestCase("2183273-1-2", 1251, "2183273-1-2")]
public void Encode_ShouldBeExpexted(string expected, int codePage, string str)
{
var enc = Encoding.GetEncoding(codePage);
var res = EncodingHelper.Encode(enc, str);
Assert.AreEqual(expected, res);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment