:: Не фоксом единым
UTF-8 to 1251
Simple777
Автор

Сообщений: 33855
Дата регистрации: 05.11.2006
Нашел на просторах инета вот такую шнягу:

function cp1251toutf8($text) {
$text = str_replace(chr(192),chr(208).chr(144),$text); # А
$text = str_replace(chr(193),chr(208).chr(145),$text); # Б
$text = str_replace(chr(194),chr(208).chr(146),$text); # В
$text = str_replace(chr(195),chr(208).chr(147),$text); # Г
$text = str_replace(chr(196),chr(208).chr(148),$text); # Д
$text = str_replace(chr(197),chr(208).chr(149),$text); # Е
$text = str_replace(chr(168),chr(208).chr(129),$text); # Ё
$text = str_replace(chr(198),chr(208).chr(150),$text); # Ж
$text = str_replace(chr(199),chr(208).chr(151),$text); # З
$text = str_replace(chr(200),chr(208).chr(152),$text); # И
$text = str_replace(chr(201),chr(208).chr(153),$text); # Й
$text = str_replace(chr(202),chr(208).chr(154),$text); # К
$text = str_replace(chr(203),chr(208).chr(155),$text); # Л
$text = str_replace(chr(204),chr(208).chr(156),$text); # М
$text = str_replace(chr(205),chr(208).chr(157),$text); # Н
$text = str_replace(chr(206),chr(208).chr(158),$text); # О
$text = str_replace(chr(207),chr(208).chr(159),$text); # П
$text = str_replace(chr(208),chr(208).chr(160),$text); # Р
$text = str_replace(chr(209),chr(208).chr(161),$text); # С
$text = str_replace(chr(210),chr(208).chr(162),$text); # Т
$text = str_replace(chr(211),chr(208).chr(163),$text); # У
$text = str_replace(chr(212),chr(208).chr(164),$text); # Ф
$text = str_replace(chr(213),chr(208).chr(165),$text); # Х
$text = str_replace(chr(214),chr(208).chr(166),$text); # Ц
$text = str_replace(chr(215),chr(208).chr(167),$text); # Ч
$text = str_replace(chr(216),chr(208).chr(168),$text); # Ш
$text = str_replace(chr(217),chr(208).chr(169),$text); # Щ
$text = str_replace(chr(218),chr(208).chr(170),$text); # Ъ
$text = str_replace(chr(219),chr(208).chr(171),$text); # Ы
$text = str_replace(chr(220),chr(208).chr(172),$text); # Ь
$text = str_replace(chr(221),chr(208).chr(173),$text); # Э
$text = str_replace(chr(222),chr(208).chr(174),$text); # Ю
$text = str_replace(chr(223),chr(208).chr(175),$text); # Я
$text = str_replace(chr(224),chr(208).chr(176),$text); # а
$text = str_replace(chr(225),chr(208).chr(177),$text); # б
$text = str_replace(chr(226),chr(208).chr(178),$text); # в
$text = str_replace(chr(227),chr(208).chr(179),$text); # г
$text = str_replace(chr(228),chr(208).chr(180),$text); # д
$text = str_replace(chr(229),chr(208).chr(181),$text); # е
$text = str_replace(chr(184),chr(209).chr(145),$text); # ё
$text = str_replace(chr(230),chr(208).chr(182),$text); # ж
$text = str_replace(chr(231),chr(208).chr(183),$text); # з
$text = str_replace(chr(232),chr(208).chr(184),$text); # и
$text = str_replace(chr(233),chr(208).chr(185),$text); # й
$text = str_replace(chr(234),chr(208).chr(186),$text); # к
$text = str_replace(chr(235),chr(208).chr(187),$text); # л
$text = str_replace(chr(236),chr(208).chr(188),$text); # м
$text = str_replace(chr(237),chr(208).chr(189),$text); # н
$text = str_replace(chr(238),chr(208).chr(190),$text); # о
$text = str_replace(chr(239),chr(208).chr(191),$text); # п
$text = str_replace(chr(240),chr(209).chr(128),$text); # р
$text = str_replace(chr(241),chr(209).chr(129),$text); # с
$text = str_replace(chr(242),chr(209).chr(130),$text); # т
$text = str_replace(chr(243),chr(209).chr(131),$text); # у
$text = str_replace(chr(244),chr(209).chr(132),$text); # ф
$text = str_replace(chr(245),chr(209).chr(133),$text); # х
$text = str_replace(chr(246),chr(209).chr(134),$text); # ц
$text = str_replace(chr(247),chr(209).chr(135),$text); # ч
$text = str_replace(chr(248),chr(209).chr(136),$text); # ш
$text = str_replace(chr(249),chr(209).chr(137),$text); # щ
$text = str_replace(chr(250),chr(209).chr(138),$text); # ъ
$text = str_replace(chr(251),chr(209).chr(139),$text); # ы
$text = str_replace(chr(252),chr(209).chr(140),$text); # ь
$text = str_replace(chr(253),chr(209).chr(141),$text); # э
$text = str_replace(chr(254),chr(209).chr(142),$text); # ю
$text = str_replace(chr(255),chr(209).chr(143),$text); # я
return $text;
}


Положим, я открываю текстовый файл в кодировке UTF-8, содержащий "обычные" символы до ASCII 127, а также и кириллицу. Символов из каких-либо других языков во входном файле не будет.

Как наиболее эффективно переделать приведенную таблицу под UDF для FPD?

Видимо, надо считывать сначала один байт во входном файле, и если это будет chr(208) или chr(209), то потом проверить значение следующего байта? И если эта пара встретится в перекодировочной таблице, то заменить 2 байта во входном файле на один байт в выходном файле?
Ratings: 0 negative/0 positive
Re: UTF-8 to 1251
sphinx

Сообщений: 31180
Откуда: Каменск-Уральски
Дата регистрации: 22.11.2006
Может поможет такой код на Visual Basic:

www.vbnet.ru

Я так понял, что кодировку без парсинга всего текста можно поменять сразу через ADODB.Stream

excelvba.ru



Что-то вроде..

FUNCTION ConvertUTF8to1251(sIn)
oRecode = CreateObject("ADODB.Stream")
oRecode.Open()
oRecode.CharSet = "windows-1251"
oRecode.WriteText(sIn)
oRecode.Position = 0
oRecode.CharSet = "UTF-8"
Convert1251toUtf = oRecode.ReadText()
oRecode.Close()


------------------
"Veni, vidi, vici!"(с)




Исправлено 3 раз(а). Последнее : sphinx, 22.03.16 20:35
Ratings: 0 negative/0 positive
Re: UTF-8 to 1251
Simple777
Автор

Сообщений: 33855
Дата регистрации: 05.11.2006
Нет. Никаких внешних средств использовать не надо в данном случае. У юзеров может быть установлено что угодно, а мне надо будет конвертировать в моей программе файлы, которые они будут получать из другого внешнего приложения. Тут вполне сгодится UDF-функция на FPD. Как ее написать "в лоб" я вижу. Но как показали обсуждения моих UDF-функций здесь, даже "обнять и заплакать" будет мало.

Вот поэтому и спрашиваю совета - как сделать UDF так, чтобы функция работала быстро и без глюков?
Ratings: 0 negative/0 positive
Re: UTF-8 to 1251
sphinx

Сообщений: 31180
Откуда: Каменск-Уральски
Дата регистрации: 22.11.2006
Подправил функцию...

FUNCTION ConvertUTF2WIN
LPARAMETERS tcFile
oStream = CreateObject("ADODB.Stream")
WITH oStream
.Type = 2
*-- Считываем текст из файла в кодировке UTF-8
.Open()
.LoadFromFile(tcFile)
cStr = .ReadText()
.Close()
*-- Назначаем новую кодировку
.CharSet = 'windows-1251'
.Open()
.WriteText(cStr)
ENDWITH
RETURN cStr


------------------
"Veni, vidi, vici!"(с)
Ratings: 0 negative/0 positive
Re: UTF-8 to 1251
Simple777
Автор

Сообщений: 33855
Дата регистрации: 05.11.2006
Извиняюсь, канешна... :-[

Но в FPD 2.6 нет CreateObject() :al:
Ratings: 0 negative/0 positive
Re: UTF-8 to 1251
sphinx

Сообщений: 31180
Откуда: Каменск-Уральски
Дата регистрации: 22.11.2006
Вот реализация через API-функции:

FUNCTION UTF8ToWin
LPARAMETERS inString As String
******************************
DECLARE INTEGER LocalAlloc IN kernel32 LONG uFlags, LONG uBytes
DECLARE INTEGER LocalFree IN kernel32 LONG hMem
Declare Integer MultiByteToWideChar in WIN32API ;
integer CodePage,;
integer Flags,;
string MultyByteStr,;
integer MultiByteStrLen,;
string @ WideCharStr,;
integer WideCharStrLen
Declare Integer WideCharToMultiByte in WIN32API ;
integer CodePage,;
integer Flags,;
string MultyByteStr,;
integer MultiByteStrLen,;
string @ WideCharStr,;
integer WideCharStrLen,;
integer ,;
integer
DECLARE RtlMoveMemory IN kernel32 AS CopyMemory;
STRING @ Destination,;
INTEGER SOURCE,;
INTEGER nLength
********************************
IF inString = '' OR ISNULL(inString)
MESSAGEBOX('String is null')
RETURN
ENDIF
Local WideCharBuf, MultiByteBuf
WideCharBuf=Replicate(Chr(0),Len(inString)*2)
MultiByteBuf=Replicate(Chr(0),Len(inString))
MultiByteToWideChar;
(nCurrentCodePage;
,0;
,cString;
,Len(cString);
,@WideCharBuf;
,Len(WideCharBuf))
WideCharToMultiByte;
(nNewCodePage;
,0;
,WideCharBuf;
,Len(WideCharBuf);
,@MultiByteBuf;
,Len(MultiByteBuf);
,0,0)
RETURN MultiByteBuf


------------------
"Veni, vidi, vici!"(с)
Ratings: 0 negative/0 positive
Re: UTF-8 to 1251
sphinx

Сообщений: 31180
Откуда: Каменск-Уральски
Дата регистрации: 22.11.2006
Есть еще API-функция CPCONVERT:


DECLARE INTEGER CPConvert IN CPConvert.dll AS ConvCP INTEGER nCPFrom, INTEGER nCPTo, STRING strFrom, STRING @strTo,INTEGER nLenOut
LOCAL cInString && Строка в кодировке UTF-8
LOCAL cOutString && Строка в кодировке Win-1251
cOutString = ConvertCP(65001, 1251, cInString)


------------------
"Veni, vidi, vici!"(с)
Ratings: 0 negative/0 positive
Re: UTF-8 to 1251
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
Simple777
как сделать UDF так, чтобы функция работала быстро
Написать её на Си. Скомпилировать в plb или чего там для FPD было...
Simple777
и без глюков?
1) Начальная отладка.
2) Набор тестов (вход, ожидаемый выход, сравнение - под все "тонкие" случаи).
Алгоритм описан в RFC, да даже в википедии - ничего супер-сложного в нём нету, хотя и нужны битовые операции. И про BOM не следует забывать.
Делать ориентируясь под "Символов из каких-либо других языков во входном файле не будет." - это значит делать сразу с глюками. Хочешь - делай, конечно, но не упоминай потом про "без глюков"


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: UTF-8 to 1251
Simple777
Автор

Сообщений: 33855
Дата регистрации: 05.11.2006
Обсуждение как на форуме, так и в личке таки сподвигло на написание нижеприводимого опуса. По крайней мере, при тестировании выходной файл формируется корректно. Для проверки использовалась строка из всех букв алфавита кириллицы (большие и маленькие буквы) вперемежку с цифрами, латиницей и специальными символами. Также проверялся и реальный файл.

Собственно, преобразованию подвергаются только те символы, которые с большой вероятностью являются 2-байтным представлением кириллицы в UTF-8. Все же остальные символы остаются в неизменном виде. Иными словами, если вдруг попадется некая кракозябра, то она так и перейдет в выходной файл. В данном же конкретном случае вероятность встречи кракозябры во входном файле примерно такая же, как и встреча с динозавром на улице, т.е 1/2

BOM такой. Сначала идет первый байт для 2-байтной кодировки, а потом второй.

clos all
set talk off
nfile1='ispisok.txt'
nfile2='rspisok.txt'
Vnomf1=FOPEN(nfile1)
Vnomf2=FCREA(nfile2)
DO WHIL !FEOF(vnomf1)
m.A=FREAD(vnomf1,1)
if betw(asc(m.a),208,209)
m.a=m.a+FGETS(vnomf1,1)
m.a=utf_866(m.a)
endi
=fwrite(vnomf2,m.a)
ENDD
clos all
quit

Далее utf_866.prg

PARAMETERS p
NOTE lenth p - 2 bytes
priv n
m.n=subs(p,2,1)
do case
case subs(p,1,1)=chr(208)
do case
case asc(m.n)=129
p=chr(168)
case betw(asc(m.n),144,191)
p=chr(asc(m.n)+48)
endc
case subs(p,1,1)=chr(209)
do case
case asc(m.n)=145
p=chr(184)
case betw(asc(m.n),128,143)
p=chr(asc(m.n)+112)
endc
endc
p=cpconv(1251,866,p)
RETURN p

[sm128]

P.S. Название топика теперь кагбы и не совсем соответствует - конечной целью было таки перегнать данные из UTF-8 в кодовую страницу 866. [sm128]



Исправлено 4 раз(а). Последнее : Simple777, 23.03.16 09:10
Ratings: 0 negative/0 positive
Re: UTF-8 to 1251
alex;

Сообщений: 2855
Откуда: Москва
Дата регистрации: 23.11.2004
Фигасе,
вы знаете сколько символов в юникоде?

или 1251 тож юникод - чот подзабыл



Исправлено 1 раз(а). Последнее : alex;, 23.03.16 09:56
Ratings: 0 negative/0 positive
Re: UTF-8 to 1251
Simple777
Автор

Сообщений: 33855
Дата регистрации: 05.11.2006
Это конвертер только для кириллицы. Остальные языки не обрабатываются. Да и задачи такой не было у меня. Входные файлы будут содержать только символы ASC 0-127 и кириллицу.



Исправлено 2 раз(а). Последнее : Simple777, 23.03.16 10:16
Ratings: 0 negative/0 positive
Re: UTF-8 to 1251
alex;

Сообщений: 2855
Откуда: Москва
Дата регистрации: 23.11.2004
мне нравиться больше применение chr в BITTO?

Забыл

млин

ЗЫ Как-то chr использовалсяв api.
Кароч, тов. модеры этот меседж нужна удалить

PSS Не всю тему прочитал, сорри



Исправлено 2 раз(а). Последнее : alex;, 23.03.16 10:54
Ratings: 0 negative/0 positive
Re: UTF-8 to 1251
alex;

Сообщений: 2855
Откуда: Москва
Дата регистрации: 23.11.2004
Я для перевода использовал чужую функцию
Private Declare Function MultiByteToWideChar Lib "kernel32.dll" (ByVal CodePage As Long, ByVal dwFlags As Long, ByVal lpMultiByteStr As String, ByVal cchMultiByte As Long, ByVal lpWideCharStr As Long, ByVal cchWideChar As Long) As Long
Private Declare Function WideCharToMultiByte Lib "kernel32.dll" (ByVal CodePage As Long, ByVal dwFlags As Long, ByVal lpWideCharStr As Long, ByVal cchWideChar As Long, ByVal lpMultiByteStr As Long, ByVal cchMultiByte As Long, ByVal lpDefaultChar As Long, ByVal lpUsedDefaultChar As Long) As Long
Public Function ToUTF8(ByVal sText As String) As String
Dim nRet As Long, strRet As String
strRet = String(Len(sText) * 2, vbNullChar)
nRet = WideCharToMultiByte(65001, &H0, StrPtr(sText), Len(sText), StrPtr(strRet), Len(sText) * 2, 0&, 0&)
ToUTF8 = Left(StrConv(strRet, vbUnicode), nRet)
End Function
Public Function FromUTF8(ByVal sText As String) As String
Dim nRet As Long, strRet As String
strRet = String(Len(sText), vbNullChar)
nRet = MultiByteToWideChar(65001, &H0, sText, Len(sText), StrPtr(strRet), Len(strRet))
FromUTF8 = Left(strRet, nRet)
End Function

ЗЫ Млин, наверно,и этотмеседжнуно удалить, тк используется api
Ratings: 0 negative/0 positive
Re: UTF-8 to 1251
Simple777
Автор

Сообщений: 33855
Дата регистрации: 05.11.2006
Вот все горазды лысому предлагать расческу.

Речь идет только о FPD, и никаких VBA, VBS, WIn-api и прочих "ништяков" в наличии не предполагается. [sm128]
Ratings: 0 negative/0 positive
Re: UTF-8 to 1251
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
alex;
вы знаете сколько символов в юникоде?
или 1251 тож юникод - чот подзабыл
По принятым в винапи соглашениям при переводе между разными кодовыми страницами если нет возможности найти нечто похожее (например псевдографика из 866 или те же "греческие" буквы в кириллицу 1251) то идёт замена "кракозябры" на "символ замены" - обычно это вопросительный знак.


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: UTF-8 to 1251
Crispy

Сообщений: 18571
Дата регистрации: 16.05.2005
Simple777
P.S. Название топика теперь кагбы и не совсем соответствует - конечной целью было таки перегнать данные из UTF-8 в кодовую страницу 866. [sm128]

Так получилось же вроде все, почему не соответствует-то?

Кстати в принципе не так уж сложно, как и в том моем примере (в решениях) об обратной конвертации, сделать не побайтовое, как у тебя, а тоже построчное преобразование.
Вот таким образом:

clos all
set talk off
nfile1 = 'ispisok.txt'
nfile2 = 'rspisok.txt'
Vnomf1 = FOPEN(nfile1)
Vnomf2 = FCREATE(nfile2)
DO WHILE !FEOF(vnomf1)
a = FGETS(vnomf1)
* для А-я:
FOR i=1 to 64
a = STRTRAN(a,CHR(IIF(i<49,208,209))+CHR(IIF(i<49,143,79)+i),CHR(IIF(i<49,127,175)+i))
ENDFOR
* также для Ё и ё можно добавить, если нужно:
a = STRTRAN(STRTRAN(a,CHR(208)+CHR(129),CHR(240)),CHR(209)+CHR(145),CHR(241))
=FPUTS(vnomf2,a)
ENDDO
=FCLOSE(vnomf1)
=FCLOSE(vnomf2)
clos all
quit

Получая на выходе аналогичное UTF-8 -> 866.
[sm128]

Разумеется, лучше оформить все это как процедуру, просто передавая в нее параметрами имена файлов. При этом, если нет какого-нибудь особого смысла хранить файл в обеих кодировках, можно и вообще после закрытия обоих файлов просто перекопировать новый 866-файл вместо исходного, чтобы не путаться далее в именах и кодировках. Т.е. тогда достаточно передавать параметром только лишь одно имя исходного файла, а временный называть как-то типа tmp.txt и удалять в конце процедуры. В FPD в подобных случаях я обычно так всегда и делал.


------------------
В действительности все иначе, чем на самом деле.
                                      (Антуан де Сент-Экзюпери)




Исправлено 1 раз(а). Последнее : Crispy, 24.03.16 11:29
Ratings: 0 negative/0 positive
Re: UTF-8 to 1251
Simple777
Автор

Сообщений: 33855
Дата регистрации: 05.11.2006
Да ежели в нашем селе я надену такие штаны включу такой модуль в проект, то буду считаться первым гармонистом!.. :danc: [sm128]
Ratings: 0 negative/0 positive
Re: UTF-8 to 1251
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
Crispy
просто перекопировать новый 866-файл вместо исходного, чтобы не путаться далее в именах и кодировках.
Ога, чтобы на всякий случай ещё пару раз его переконвертировать, превратив в невосстановимое и нечитаемое нечто Особливо памятуя про любовь к отсутствию BOM в файлах - чтобы уж никто и не заподозрил даже, в UTF8 сей файл или уже нет


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: UTF-8 to 1251
Simple777
Автор

Сообщений: 33855
Дата регистрации: 05.11.2006
Не, исходный файл я в таких случаях всегда сохраняю. У меня такой контингент юзеров, что они и "косяки" - две неразлучные вещи. Бывает, что происходит и довольно крутой разбор полетов. Покамест счет в мою пользу - в своих воротах "отстоял всухую". [sm128]. Кстати, несколько раз оракловцам "задницу надрал" при разборках. \m/
Ratings: 0 negative/0 positive
Re: UTF-8 to 1251
h.i.a.

Сообщений: 4002
Откуда: Мурманск/Спб/Мск
Дата регистрации: 18.11.2005
Добавлю свои пять копеек. Понадобилось по-быстрому разобрать с помощью VFP один лог, кириллица как оказалась в UTF-8.
В итоге получилось такое решение:
text_1251=STRCONV(STRCONV(text_utf8,11),2)


------------------
Ratings: 0 negative/0 positive


Извините, только зарегистрированные пользователи могут оставлять сообщения в этом форуме.

On-line: 5 (Гостей: 5)

© 2000-2024 Fox Club 
Яндекс.Метрика