Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Общие вопросы > Проблема с кодировкой сохранённого файла


Автор: lollollollol 15.1.2014, 22:57
Здравствуйте, ситуация такая:

На сервер был скачен текстовый файл с русским текстом, на сервере нет русского языка, и файл сохранился с текстом типа "Õîòèòå ïîõóäåòü", когда я скачал файл на мой комп, все символы такими и остались.

Вопрос: Как из этого файла получить снова русский текст? Работа с файлам будет выполняться программно, спасибо

Добавлено через 10 минут и 16 секунд
Utf8ToAnsi не работает

Автор: lollollollol 16.1.2014, 00:08
ЧТо же это за кодировка, немогу ничего найти уже 4 часа!!!!!!!!!!!
Уже весь гугл и яндекс перелопатил!

Автор: ZBugz 16.1.2014, 06:01
На сервере есть такая проблема, обычно на сервере это тупо ansi.
Хочешь что быбработало, используй unicode, точнее utf16le 

Автор: Romikgy 16.1.2014, 09:43
или ссылку на сайт или файл в бинарном виде... походу одна из видов кириликов ....

Автор: Illusion Dolphin 16.1.2014, 12:06
http://2cyr.com/decode/?lang=ru => Хотите похудеть

Автор: Akella 16.1.2014, 15:45
как распознать кракозябры
http://habrahabr.ru/post/147843/

Автор: lollollollol 16.1.2014, 17:34
ну да, я понял что это ansi, только не понял как из этого программно получить нормальный русский текст? 
Ну например открываю файл, читаю строку, строка в переменной 
Код

var
     text:string;

Как получить русский текст? Из какой в какую кодировку кодировать? Или может как0то посимвольно обрабатывать?

Добавлено через 4 минуты и 30 секунд
Расширенный режим: исходная кодировка: windows-1251
отображается как: windows-1251
т.е. получается оно просто windows-1251 кодирует в windows-1251 но на выходе заветные символы, как программно в делфи того же добиться?

Автор: lollollollol 16.1.2014, 19:12
Ничего не выходит, уже и всё из HtmlCPConvert перепробовал, и все примеры в гугле которе нашел. 

Я совсем не понимаю что требуется сделать чтобы вернуть в русский текст? Это же обычная windows1251, почему она так отображается?

Автор: lollollollol 16.1.2014, 23:14
а вот так текст в винхексе выглядит
Код

Õîòèòå ïîõóäåòü

Автор: ZBugz 17.1.2014, 06:33
У тебя не кодировка не читается, у тебя контролы не читают ansi в windows server. Такое бывает.
Поэтому юзай UNICODE, т.е. записывай в нем и читай его

Автор: Alexiski 17.1.2014, 08:53
Есть веоятность, что текст в 1251 был ошибочно воспринят как Latin-1 и уже в таком виде преобразовался в Unicode (Utf-8). То есть его нужно обратно в Latin-1, а потом уже прочитать как 1251. Как-то так..

Автор: lollollollol 17.1.2014, 10:51
Код

У тебя не кодировка не читается, у тебя контролы не читают ansi в windows server. Такое бывает.
Поэтому юзай UNICODE, т.е. записывай в нем и читай его 

Вот есть у меня гигобайты таких файлов, как теперь в русский текст вернуть их? какие функции использовать для преобразования в русский текст?


Нашел статью, http://habrahabr.ru/post/137061/
села как там сказано 
Код

  str:=Utf8ToAnsi(str);
  str:=AnsiToUtf8(str);

Не спасло абсолютно!

Добавлено через 2 минуты и 2 секунды
Код

str:=Utf8ToAnsi(str);

Даёт результат
Цитата

Oioeoa iiooaaou

Автор: lollollollol 17.1.2014, 11:23
Код

Функция SetCodePage, объявленная в модуле System.pas как

procedure SetCodePage(var S: AnsiString; CodePage: Word; Convert: Boolean);



У меня delphi 7  и нет этой функции, кто может скопировать у себя код этой функции и показать тут?

Автор: lollollollol 17.1.2014, 11:38
 smile 

Автор: lollollollol 17.1.2014, 15:13
Задача вообще решаема?

Автор: Romikgy 17.1.2014, 20:34
да

Автор: lollollollol 17.1.2014, 21:54
и в какую сторону копать?

Автор: Romikgy 17.1.2014, 22:29
что бы подсказать в какую сторону копать, надо видеть что именно копать.. надо видеть не только то что вы копируете с разных мест , а первоисточник!!! вы же , просто сообщаете что у вас ничего не получилось... все ф-ции даны по работе с текстом, надо только из них создать правильную комбинацию...

Автор: lollollollol 17.1.2014, 22:53
Извиняюсь, мой косяк, вот первоисточник. 
Вопрос, каким алгоритмом вернуть русский текст? 

Автор: Romikgy 17.1.2014, 23:41
этот файл ни в каком виде не похож на русский.... по наличию пробела в файле можно подумать что это utf8 , но не русский....

Автор: lollollollol 18.1.2014, 00:24
Ну дак я и говорю, русский файл был скачен на сервер, который не поддерживает русский язык. И в результате неведамым мне образом так сохранён. 
Как теперь его в русский вернуть?

Автор: ФедосеевПавел 18.1.2014, 11:26
lollollollol, за 4 дня пора бы уже ознакомиться с кодировками, основами unicode.

Твой файл 3.txt при открытии в режиме просмотра hex - выглядит так:
Код
EF BB BF C3 95 C3 AE C3 B2 C3 A8 C3 B2 C3 A5 20
C3 AF C3 AE C3 B5 C3 B3 C3 A4 C3 A5 C3 B2 C3 BC

Первые три байта EF BB BF напоминают http://ru.wikipedia.org/wiki/Маркер_последовательности_байтов.
Значит, открываем файл как utf-8, видим строку
Код
Õîòèòå ïîõóäåòü

Это уже можно принимать за искажённую строку. Выполнив несколько экспериментов по изучению перечня возможных кодировок на сервере (источнике данных - твоих файлов) при помощи сайта из поста Illusion Dolphin, можно понять, что в данном случае имеет место кодировка сохранения iso8859-15 (latin-9), читаемая нашими вьюверами как cp1251 (ansi).

Итак, чтобы получить из фразы "Хотите похудеть" в кодировке cp1251 файл 3.txt, нужно взять строку в кодировке cp1251 и провести преобразование iso8859-15 -> utf-8, т.е. ошибиться с кодировкой. И сохранить файл с BOM.

Обратное преобразование utf8 -> iso888859-15, и полученную строку с однобайтной кодировкой интерпретировать как строку в cp1251.
О готовых библиотеках для преобразования я ничего не знаю, т.к. ещё не приходилось заниматься, но можно их или поискать или выполнить самостоятельно - все таблицы кодировок опубликованы, например, http://ru.wikipedia.org/wiki/ISO8859.

По большому счету, из проблем - автоматический выбор таблицы кодировки. Думаю, что она решается или вопросом к пользователю с показом промежуточных результатов, или проверкой диапазона символов из файла диапазону символов в кадждой таблице. Не сбрасывай со счетов алгоритм на хабре, ссылку на который привел Akella. Может быть уже существуют готовые решения.

Автор: ФедосеевПавел 18.1.2014, 12:11
Есть официальный документ от Emarcadero - "Unicode_Delphi-RUS.pdf". Поищи его в сети.

Автор: Romikgy 18.1.2014, 17:16
сильно искаженный вариант... вот что зашифровано "Х о т и т е  п о х у д е т ь "

Автор: lollollollol 18.1.2014, 18:43
ФедосеевПавел, спасибо, подскажи 
Код

Обратное преобразование utf8 -> iso888859-15


Как это можно сделать?

Автор: ФедосеевПавел 18.1.2014, 20:09
Повторюсь, я не знаю - т.к. нужда ещё не заставляла.

Полагаю, что есть готовые решения с кодировками. Тем более в Delphi.
А если вручную, то как-то так: составить свою таблицу соответствия символа в utf8 символу в кодовой таблице и потом заменять (учитывая, что каждый символ в utf8 может иметь размер от 1 до 6 байт).

Для самостоятельной работы можешь почитать http://sirserge.altai.info/articles/?id=41, http://sirserge.altai.info/articles/?id=44, http://sirserge.altai.info/articles/?id=45, http://ru.wikipedia.org/wiki/Маркер_последовательности_байтов, http://ru.wikipedia.org/wiki/ISO8859, http://ru.wikipedia.org/wiki/Windows-1251, http://ru.wikipedia.org/wiki/UTF-8, "Unicode_Delphi-RUS.pdf", http://wiki.freepascal.org/Theodp+http://forum.lazarus.freepascal.org/index.php/topic,16991.0.html?PHPSESSID=1cff40939067637b3894eb182f725fa9, Google и Yandex (Delphi+utf8+iso8859).

P.S. По поводу кодировки iso888859-15 я, конечно же, ошибся. Там iso888859-1.

Автор: ФедосеевПавел 18.1.2014, 22:16
Посмотри http://forum.sources.ru/index.php?showtopic=198926&hl=utf8.

Автор: lollollollol 19.1.2014, 00:24
Гениально!


Рабочий код, может кому пригодится!!!


Код

function StringToWideStringEx(const S: AnsiString; CodePage: Word): WideString;
var
  InputLength,
  OutputLength: integer;
begin
  InputLength := Length(S);
  OutputLength := MultiByteToWideChar(CodePage, 0, PAnsiChar(S), InputLength, nil, 0);
  SetLength(Result, OutputLength);
  MultiByteToWideChar(CodePage, 0, PAnsiChar(S), InputLength, PWideChar(Result), OutputLength);
end;

function WideStringToStringEx(const WS: WideString; CodePage: Word): AnsiString;
var
  InputLength,
  OutputLength: integer;
begin
  InputLength := Length(WS);
  OutputLength := WideCharToMultiByte(CodePage, 0, PWideChar(WS), InputLength, nil, 0, nil, nil);
  SetLength(Result, OutputLength);
  WideCharToMultiByte(CodePage, 0, PWideChar(WS), InputLength, PAnsiChar(Result), OutputLength, nil, nil);
end;


function TranslateString(const S: AnsiString; CP1, CP2: Word): AnsiString;
begin
  Result:= WideStringToStringEx(StringToWideStringEx(S, CP1), CP2);
end;


Используем так:

Код

str:=TranslateString(str,65001,28591);




Спасибо огромное всем кто откликнулся!!!!!

Добавлено через 11 минут и 4 секунды
Ещё вопрос по теме:

Если выполнить эту функцию на сервере где нет русского языка, преобразование будет выполнено верно? 

Автор: ZBugz 19.1.2014, 08:27
Цитата(lollollollol @ 19.1.2014,  00:24)
Если выполнить эту функцию на сервере где нет русского языка, преобразование будет выполнено верно?

Ну это тебе проще проверить. напиши проект пустой с этой функцией и проверь smile 
А вообще бы раньше бы написал бы, что у тебя делфи 7. С ней там как раз надо работать через такие вот примеры свыше.

Добавлено через 4 минуты и 45 секунд
Я еще такое юзал как то давно (по названию функции понятно):
Код

function UTF8ToStrSmart(Value: String): String;


      function UTF8ToStr(Value: String): String;
      var
        buffer: Pointer;
        BufLen: LongWord;
      begin
        BufLen := Length(Value) + 4;
        GetMem(buffer, BufLen);
        FillChar(buffer^, BufLen, 0);
        MultiByteToWideChar(CP_UTF8, 0, @Value[1], BufLen - 4, buffer, BufLen);
        Result := WideCharToString(buffer);
        FreeMem(buffer, BufLen);
      end;


var
  Digit: String;
  i: integer;
  HByte: Byte;
  Len: Byte;
begin
  Result := '';
  Len := 0;
  if Value = '' then Exit;
  for i := 1 to Length(Value) do
  begin
    if Len > 0 then
    begin
      Digit := Digit + Value[i];
      Dec(Len);
      if Len = 0 then
        Result := Result + UTF8ToStr(Digit);
    end else
    begin
      HByte := Ord(Value[i]);
      if HByte in [$00..$7f] then       //Standart ASCII chars
        Result := Result + Value[i]
      else begin
        //Get length of UTF-8 char
        if HByte and $FC = $FC then
          Len := 6
        else if HByte and $F8 = $F8 then
          Len := 5
        else if HByte and $F0 = $F0 then
          Len := 4
        else if HByte and $E0 = $E0 then
          Len := 3
        else if HByte and $C0 = $C0 then
          Len := 2
        else begin
          Result := Result + Value[i];
          Continue;
        end;
        Dec(Len);
        Digit := Value[i];
      end;
    end;
  end;
end; 
 




Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)