24.02.2011, 11:17 | #1 |
Участник
|
Открыть текстовый файл ansi (win1251) на нерусифицированной Windows.
Задача: прочитать в axapta текстовый файл, сохраненный в кодировке Windows-1251 (ansi) на нелокализованной Windows. Смена региональных настроек ОС недопустима. Версия axapta DAX40SP2.
В-общем, поискал, порылся, сделал следующим образом, может, что получше предложите. За реализацию WinApi функции преобразования текста ansi->utf8 спасибо AndyD. Пробовал через Binary и получение массива символов через COMVariant и SafeArray. Потом в цикле сдвиг зоны кодов символов 192-255 ("А".."я") на 848 вперед. Работает, но медленно. Может, как-то упростить и сделать через .NET (на форуме можно найти функции преобразования ansi->utf8, но, как я понял, там могу быть проблемы с подключением references у пользователей. Не сообразил, как можно преобразовать строку и сразу с ней работать, без сохранения файла с конвертированным текстом и открытия оного как utf-8 через TextBuffer. Тут тоже какие-то оптимизации возможны, я думаю. P.S. Кстати, вся эта канитель возникла при импорте банковской выписки, сохраненной в формате 1С. Не нашли возможности формировать эту выписку сразу в Unicode, что исключило бы проблемы с чтением файла. X++: client static void kird_fileAnsi2utf8_forum(Args _args) { TextBuffer tb = new TextBuffer(); FileName filenameANSI = "c:\\TEMP\\ansi.txt"; FileName filenameUTF8 = "c:\\TEMP\\utf8.txt"; str text; #define.CP_WinCyrillic(1251) // windows cyrillic #define.CP_UTF8(65001) // UTF-8 str Ansi2Utf8(str Ansi) // THANKS AndyD { DLL _kernelDLL = new DLL("KERNEL32"); DLLFunction MultiByteToWideChar = new DLLFunction(_kernelDLL, "MultiByteToWideChar"); DLLFunction WideCharToMultiByte = new DLLFunction(_kernelDLL, "WideCharToMultiByte"); Binary buf, buf1; int len; str res; ; res = ""; if (Ansi) { buf = new Binary(strlen(Ansi)+1); // тут нужно +1, иначе код сваливается с ошибкой. buf.string(0, Ansi); buf1 = new Binary((strlen(Ansi) + 1) * 2); MultiByteToWideChar.returns(ExtTypes::DWord); MultiByteToWideChar.arg(ExtTypes::DWord, ExtTypes::DWord, ExtTypes::Pointer, ExtTypes::DWord, ExtTypes::Pointer, ExtTypes::DWord); if (MultiByteToWideChar.call(#CP_WinCyrillic, 0, buf, strlen(Ansi) + 1, buf1, strlen(Ansi) + 1)) { WideCharToMultiByte.returns(ExtTypes::DWord); WideCharToMultiByte.arg(ExtTypes::DWord, ExtTypes::DWord, ExtTypes::Pointer, ExtTypes::DWord, ExtTypes::Pointer, ExtTypes::DWord, ExtTypes::DWord, ExtTypes::DWord); len = WideCharToMultiByte.call(#CP_UTF8, 0, buf1, strlen(Ansi) + 1, buf, 0, 0, 0); if (len) { buf = new Binary(len); if (WideCharToMultiByte.call(#CP_UTF8, 0, buf1, strlen(Ansi) + 1, buf, len, 0, 0)) res = buf.string(0); } } } return res; } void saveIO() // сохраняем через AsciiIo, т.к. работает быстрее в 5-10 раз, чем сохранение через TextBuffer.toFile() { AsciiIo aSCIIFile; ; aSCIIFile = new AsciiIo(filenameUTF8, "w"); aSCIIFile.write(text); return; } ; // OPEN FILE tb = new TextBuffer(); if (! tb.fromFile(filenameANSI)) throw error('bad open ansi'); text = tb.getText(); info(strfmt("ansi: %1", text)); // CONVERT TEXT text = num2char(0xEF)+num2char(0xBB)+num2char(0xBF)+ // utf-8 file header. it is needed. Ansi2Utf8(text); // SAVE FILE IN UTF-8 saveIO(); // OPEN FILE AS UTF-8 tb = new TextBuffer(); tb.fromFile(filenameUTF8, FileEncoding::UTF8); text = tb.getText(); info(strfmt("utf8: %1", text)); } |
|
|
За это сообщение автора поблагодарили: Vasil (1). |
Теги |
ansi, text, textbuffer, textio, unicode, кодовая страница, текстовый файл, asciio |
|
Похожие темы | ||||
Тема | Ответов | |||
Как открыть файл | 4 | |||
Web-портал: открыть файл | 4 | |||
Client Axapta 3.0 SP4 и Linux. Как запустить? | 10 | |||
Экспорт в текстовый файл с разделителями | 7 | |||
Экспорт накладных в текстовый файл | 20 |
|