Ок, что я сделал - (правда, это было не намного быстрее, чем перезапись 360 контактов).
Я использовал бесплатное ПО Контакты который позволяет экспортировать в текстовый файл. Экспорт в VCards отключен в бесплатной версии, поэтому на данный момент для меня это не вариант.
Затем я создал в Visual Studio консольное приложение C# для преобразования текстового файла в VCard.
Вот:
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using Thought.vCards; //https://www.nuget.org/packages/Thought.vCards/
namespace VCardGen
{
class Program
{
const string INPUT_FILE = @"C:\VSProjects\VCardGen\in.txt";
const string OUTPUT_FILE = @"C:\\VSProjects\\VCardGen\\Files5\\{0}.vcf";
//What encoding comes here? This worked but national characters displayed as ?
static Encoding ENCODING = Encoding.GetEncoding("Windows-1250");
/// <summary>
/// Removes special characters
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
static String RemoveDiacritics(String s)
{
String normalizedString = s.Normalize(NormalizationForm.FormD);
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < normalizedString.Length; i++)
{
Char c = normalizedString[i];
if (CharUnicodeInfo.GetUnicodeCategory(c) != UnicodeCategory.NonSpacingMark && CharUnicodeInfo.GetUnicodeCategory(c)!=UnicodeCategory.OtherSymbol)
stringBuilder.Append(c);
}
return stringBuilder.ToString();
}
/// <summary>
/// Saves one vCard
/// </summary>
/// <param name="c"></param>
static void SaveVCard(vCard c, Encoding e)
{
if (c == null) return;
string fn = RemoveDiacritics(c.FamilyName + c.GivenName).Trim().Replace(" ", ""); ;
vCardStandardWriter writer = new vCardStandardWriter();
{
writer.EmbedInternetImages = false;
writer.EmbedLocalImages = false;
writer.Options = vCardStandardWriterOptions.IgnoreCommas;
using (var file = File.OpenWrite(String.Format(OUTPUT_FILE, fn)))
using (var fwriter = new StreamWriter(file, e))
{
writer.Write(c, fwriter);
}
writer = null;
}
}
static void Main(string[] args)
{
//Load file outputed by Qontact
string text = System.IO.File.ReadAllText(INPUT_FILE, ENCODING);
List<string> l = text.Split('\n').ToList();
vCard c= null;
//Process Qontact file line by line
foreach (string s in l)
{
string x = s.Trim();
if (x.Length == 0) continue;
if (x.StartsWith("-"))
{
SaveVCard(c,ENCODING);
string[] np = x.Substring(1).Split(',');
c = new vCard();
c.FamilyName = np[0].Trim();
if (np.Length>1) c.GivenName = np[1].Trim();
}
else if (x.StartsWith("NAME: "))
c.DisplayName = x.Replace("NAME: ", "").Trim() ;
else if (x.StartsWith("MOB: "))
c.Phones.Add(new vCardPhone(x.Replace("MOB: ", "").Trim(), vCardPhoneTypes.Cellular));
else if (x.StartsWith("ORG:"))
c.Organization = x.Replace("ORG:", "").Trim();
else if (x.StartsWith("ADDR:"))
{
string n = x.Replace("ADDR:", "");
vCardDeliveryAddress a = new vCardDeliveryAddress();
a.Street = n.Trim();
c.DeliveryAddresses.Add(a);
}
else if (x.StartsWith("EMAIL:"))
c.EmailAddresses.Add(new vCardEmailAddress(x.Replace("EMAIL:", "").Trim()));
else if (x.StartsWith("HOME :"))
c.Phones.Add(new vCardPhone(x.Replace("HOME :", "").Trim(), vCardPhoneTypes.Home));
else if (x.StartsWith("TEL:"))
c.Phones.Add(new vCardPhone(x.Replace("TEL:", "").Trim(), vCardPhoneTypes.Work));
}
SaveVCard(c, ENCODING);
}
}
}
с использованием http://www.thoughtproject.com/Libraries/vCard/ - ничего лучше не нашел. https://www.nuget.org/packages/Thought.vCards/
Это было довольно неприятно, потому что Samsung Galaxy S6 не принимал карты vCard, которые были правильно открыты в Outlook, поэтому это было не очень просто, особенно используемую кодировку текста я не совсем понял. Мне пришлось перезапустить Samsung Galaxy A6 после импорта — он зависал, показывая множество параллельных импортов vCard. Но контакты импортировались успешно.