전 세계 문자를 포함하는 파일을 찾고 선택적으로 이름을 바꾸기 위해 작은 콘솔 응용 프로그램 (아래 소스)을 작성했습니다. 대부분의 소스 제어 시스템 이것에 대한 약간의 배경). 내가 사용하고있는 코드는 문자를 가진 간단한 사전을 찾아서 바꾸고 (그리고 1 바이트 이상의 저장소를 사용하는 다른 모든 문자를 핵으로 만들지 만) 매우 익숙한 느낌이 들게됩니다. (a) 캐릭터가 국제적인지 여부를 알아내는 올바른 방법은 무엇입니까? (b) 최고의 ASCII 대체 문자는 무엇입니까?C#을 사용하여 파일 이름 문자가 국제적인 것으로 간주되는지 확인합니다.
왜 이것이 필요한지에 대한 배경 정보를 제공해 드리겠습니다. 덴마크의 A 문자에는 UTF-8로 된 두 개의 다른 인코딩이 있는데, 둘 다 동일한 기호를 나타냅니다. NFC 및 NFD 인코딩으로 알려져 있습니다. Windows와 Linux는 기본적으로 NFC 인코딩을 만들지 만 지정된 인코딩을 존중합니다. Mac은 모든 이름 (HFS + 파티션에 저장할 때)을 NFD로 변환하므로 Windows에서 작성된 파일의 이름에 대해 다른 바이트 스트림을 반환합니다. 이것은 Subversion, Git 및이 시나리오를 적절하게 다루지 않는 다른 많은 유틸리티를 효과적으로 파기합니다.
현재 Mercurial을 평가 중입니다. 국제 문자를 처리 할 때 더 나빠질 수 있습니다. 이러한 문제에 상당히 지쳐서 소스 제어 또는 국제 문자가 있어야하고 여기에 우리가 있습니다.
내 현재의 구현 :
public class Checker
{
private Dictionary<char, string> internationals = new Dictionary<char, string>();
private List<char> keep = new List<char>();
private List<char> seen = new List<char>();
public Checker()
{
internationals.Add('æ', "ae");
internationals.Add('ø', "oe");
internationals.Add('å', "aa");
internationals.Add('Æ', "Ae");
internationals.Add('Ø', "Oe");
internationals.Add('Å', "Aa");
internationals.Add('ö', "o");
internationals.Add('ü', "u");
internationals.Add('ä', "a");
internationals.Add('é', "e");
internationals.Add('è', "e");
internationals.Add('ê', "e");
internationals.Add('¦', "");
internationals.Add('Ã', "");
internationals.Add('©', "");
internationals.Add(' ', "");
internationals.Add('§', "");
internationals.Add('¡', "");
internationals.Add('³', "");
internationals.Add('', "");
internationals.Add('º', "");
internationals.Add('«', "-");
internationals.Add('»', "-");
internationals.Add('´', "'");
internationals.Add('`', "'");
internationals.Add('"', "'");
internationals.Add(Encoding.UTF8.GetString(new byte[] { 226, 128, 147 })[ 0 ], "-");
internationals.Add(Encoding.UTF8.GetString(new byte[] { 226, 128, 148 })[ 0 ], "-");
internationals.Add(Encoding.UTF8.GetString(new byte[] { 226, 128, 153 })[ 0 ], "'");
internationals.Add(Encoding.UTF8.GetString(new byte[] { 226, 128, 166 })[ 0 ], ".");
keep.Add('-');
keep.Add('=');
keep.Add('\'');
keep.Add('.');
}
public bool IsInternationalCharacter(char c)
{
var s = c.ToString();
byte[] bytes = Encoding.UTF8.GetBytes(s);
if(bytes.Length > 1 && ! internationals.ContainsKey(c) && ! seen.Contains(c))
{
Console.WriteLine("X '{0}' ({1})", c, string.Join(",", bytes));
seen.Add(c);
if(! keep.Contains(c))
{
internationals[ c ] = "";
}
}
return internationals.ContainsKey(c);
}
public bool HasInternationalCharactersInName(string name, out string safeName)
{
StringBuilder sb = new StringBuilder();
Array.ForEach(name.ToCharArray(), c => sb.Append(IsInternationalCharacter(c) ? internationals[ c ] : c.ToString()));
int length = sb.Length;
sb.Replace(" ", " ");
while(sb.Length != length)
{
sb.Replace(" ", " ");
}
safeName = sb.ToString().Trim();
string namePart = Path.GetFileNameWithoutExtension(safeName);
if(namePart.EndsWith("."))
safeName = namePart.Substring(0, namePart.Length - 1) + Path.GetExtension(safeName);
return name != safeName;
}
}
그리고 이것은 다음과 같이 호출 할 것이다 :
FileInfo file = new File("Århus.txt");
string safeName;
if(checker.HasInternationalCharactersInName(file.Name, out safeName))
{
// rename file
}
주 작은 따옴표 콘솔 창에서 Visual Studio로 복사하여 Chrome을 통해 StackOverflow에 복사 할 수 있다는 사실에 놀라움을 금치 못했습니다. 그러나 우리가 내용보다는 파일 이름을 말하자마자 우리는 1980 년대에 다시 돌아 왔습니다. –