완전성을 위해 일부 구현을 제공하고 싶습니다. 일반적으로 Regex는 비용이 많이 드는 접근 방식입니다. 특히 문자열이 큰 경우 (큰 파일을 전송할 때 발생). 다음 접근 방식은 가장 빠른 검색 방법을 먼저 시도합니다.
public static class HelperExtensions {
// Characters that are used in base64 strings.
private static Char[] Base64Chars = new[] { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' };
/// <summary>
/// Extension method to test whether the value is a base64 string
/// </summary>
/// <param name="value">Value to test</param>
/// <returns>Boolean value, true if the string is base64, otherwise false</returns>
public static Boolean IsBase64String(this String value) {
// The quickest test. If the value is null or is equal to 0 it is not base64
// Base64 string's length is always divisible by four, i.e. 8, 16, 20 etc.
// If it is not you can return false. Quite effective
// Further, if it meets the above criterias, then test for spaces.
// If it contains spaces, it is not base64
if (value == null || value.Length == 0 || value.Length % 4 != 0
|| value.Contains(' ') || value.Contains('\t') || value.Contains('\r') || value.Contains('\n'))
return false;
// 98% of all non base64 values are invalidated by this time.
var index = value.Length - 1;
// if there is padding step back
if (value[index] == '=')
index--;
// if there are two padding chars step back a second time
if (value[index] == '=')
index--;
// Now traverse over characters
// You should note that I'm not creating any copy of the existing strings,
// assuming that they may be quite large
for (var i = 0; i <= index; i++)
// If any of the character is not from the allowed list
if (!Base64Chars.Contains(value[i]))
// return false
return false;
// If we got here, then the value is a valid base64 string
return true;
}
}
편집하다
Sam이 제안한대로 소스 코드를 약간 변경할 수도 있습니다. 그는 테스트의 마지막 단계에 대해 더 나은 성능을 제공합니다. 루틴
private static Boolean IsInvalid(char value) {
var intValue = (Int32)value;
// 1 - 9
if (intValue >= 48 && intValue <= 57)
return false;
// A - Z
if (intValue >= 65 && intValue <= 90)
return false;
// a - z
if (intValue >= 97 && intValue <= 122)
return false;
// + or /
return intValue != 43 && intValue != 47;
}
if (!Base64Chars.Contains(value[i]))
줄을 다음 으로 대체하는 데 사용할 수 있습니다.if (IsInvalid(value[i]))
Sam의 향상된 기능이 포함 된 전체 소스 코드 는 다음과 같습니다 (명확성을 위해 주석 제거).
public static class HelperExtensions {
public static Boolean IsBase64String(this String value) {
if (value == null || value.Length == 0 || value.Length % 4 != 0
|| value.Contains(' ') || value.Contains('\t') || value.Contains('\r') || value.Contains('\n'))
return false;
var index = value.Length - 1;
if (value[index] == '=')
index--;
if (value[index] == '=')
index--;
for (var i = 0; i <= index; i++)
if (IsInvalid(value[i]))
return false;
return true;
}
// Make it private as there is the name makes no sense for an outside caller
private static Boolean IsInvalid(char value) {
var intValue = (Int32)value;
if (intValue >= 48 && intValue <= 57)
return false;
if (intValue >= 65 && intValue <= 90)
return false;
if (intValue >= 97 && intValue <= 122)
return false;
return intValue != 43 && intValue != 47;
}
}
=
기호를 사용하는 경우에 패딩이 필요합니다 . 패딩이 잘못되면 입력이 표현식과 일치하더라도 오류가 발생합니다.