Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Перекодировка файла DOS в Win1251 [D6, WinXP]


Страницы:   1 2

galexis ©   (2004-08-09 17:23:00) 

Открываю файл как AssignFile(F, FileEdit.Text);
                Reset(F);
                while not eof(f) do
                begin
                Readln(F, S);
                end;
файл ASCII, а надо win1251
И ведь знаю что легко и не раз делал, но замкнуло и все тут. И найти не могу. Помогите пожалуйста


Sandman25   (2004-08-10 09:11:00) [1]

[10] VMcL ©   (09.08.04 18:04)
[11] Мастер ©   (09.08.04 18:13)

Век живи - век учись.
Спасибо!


Anatoly Podgoretsky   (2004-08-10 09:11:00) [2]

Из всех предложеных вариантов, только вариант 2 от VMcL ©   (10.08.04 07:22) [34] будет безболезненый, остальные варианты страдают той или другой степень ошибок/проблем. Единственно, что надо сделать это только сменить имя функции, поскольку в Вин АПИ такое имя уже существует и могут быть из за этого проблемы.


VMcL   (2004-08-10 07:22:00) [3]

По сабджу.

function OEMToAnsi(const S: String): String;
begin
 SetLength(Result, Length(S));
 OEMToChar(PChar(S), PChar(Pointer(Result)));
end;


или

function OEMToAnsi(const S: String): String;
var
 Len: Integer;
begin
 Len := Length(S);
 SetLength(Result, Len);
 if Len > 0 then
   OEMToChar(PChar(S), PChar(Result));
end;


Проблема заключается в том, что internal функция LStrToPChar при преобразовании пустой строки [PChar(Result)] возвращает не nil, а указатель на символ #0, который находится в области памяти с запретом на запись. Функция OEMToChar, видя что ей передали не nil пытается записать по адресу PChar(Result) ноль, чтобы "вернуть" пустую строку и, конечно, возникает AV.

Если строку преобразовывать с помошью Pointer(Result), то пустая строка преобразуется в nil и всё ОК.

Замечание. Исследование проводилось на D6.

P.S. Вот код LStrToPChar:

function _LStrToPChar(const s: AnsiString): PChar;
asm
       TEST    EAX, EAX
       JE      @@handle0
       RET
@@zeroByte:
       DB      0
@@handle0:
       MOV     EAX, offset @@zeroByte   // !!!
end;


Proshka   (2004-08-10 03:19:00) [4]

а-а-а понял в
DosToWinнадо юзать OemToChar
у вас опечатка а я тупо скопировал :)


Proshka   (2004-08-10 01:30:00) [5]

голяк  :no: я путался по разному изголяться но у меня из строки
 0 ЏђЋѓђЂЊЊЂ/ adem    ;
получается только:
 0 _________/ adem    ;
а должно быть
 0 ПРОГРАММА/ adem    ;
вот
может есть какие идеи а


Alx2   (2004-08-09 20:29:00) [6]

>Proshka   (09.08.04 20:14)
Функицю перепиши по-другому:

Function DosToWin (Const stDOS : string) : string;
begin
Result := stDos;
if Result <>'' then CharToOem(PChar(Result),PChar(Result))
end;


Мастер   (2004-08-09 20:20:00) [7]

>Proshka   (09.08.04 20:14) [29]

Не используй при вызове переменную класса.


Proshka   (2004-08-09 20:14:00) [8]

ребят я наверно протупил гдето, но у меня в этой строчке
"RichEdit2.Lines.Add (DosToWin(RichEdit1.Lines.Strings[i]))"
постоянно насилуют Аксеса. Обидно что изза меня хороший парень страдает. помогите пожалуста понять почему так.


Андрей Сенченко   (2004-08-09 20:03:00) [9]

Модераторам просьба - удалите мой вариант. ибо нефиг тут некорректному коду делать


Alx2   (2004-08-09 19:57:00) [10]

>Андрей Сенченко ©   (09.08.04 19:54) [25]
Для строк - не определяет. Потому-что, например, неизвестно сколько ты в этот результат зальешь данных. В итоге ты передаешь функции API "битую ссылку". Эта функция считает, что ты позаботился о месте для размещения данных и заполняет их "не глядя". Нужно выполнить требование, чтобы Result имел длину не менее первого аргумента. Тут либо SetLength, либо еще чего наподобие :)


Андрей Сенченко   (2004-08-09 19:57:00) [11]

всё. ... извините, что ввел в заблуждение ... там функция в этом синтаксисе перекрыта была другой, объявленной напрямую в юните.
Действительно AV вышибает.


Андрей Сенченко   (2004-08-09 19:54:00) [12]

Мастер ©   (09.08.04 19:49) [22]

не память а адрес в памяти - так наверное ?

Alx2 ©   (09.08.04 19:50) [23]

странно что работает в этом случае ... то есть сам по себе запуск функции еще не определяет физического адреса для ее результата ?


Alx2   (2004-08-09 19:52:00) [13]

>Андрей Сенченко ©   (09.08.04 19:47)
Я схватил AV на твоей реализации в примере:  ShowMessage(WinToDos('Helo'));


Alx2   (2004-08-09 19:50:00) [14]

>Андрей Сенченко ©   (09.08.04 19:47) [21]
Function DosToWin (stDOS : string) : string;
begin
if stDOS <>'' then CharToOem(PChar(stDos),PChar(Result)) // вот с этого места: Result здесь не проинициилизирован. Куда будет сыпаться содержимое stDos? Туда,  куда указывает result. А указывать он пока может куда угодно.
else Result := '';
end;


Мастер   (2004-08-09 19:49:00) [15]

>Андрей Сенченко ©   (09.08.04 19:43) [19]

Function DosToWin (stDOS : string) : string;
begin
if stDOS <>'' then CharToOem(PChar(stDos),PChar(Result))
else Result := '';
end;


Под Result необходимо выделить память...


Андрей Сенченко   (2004-08-09 19:47:00) [16]

В итоге сразу AV поймаешь :)

Да вот что интересно то ... только что протестировал в реальной программе и не поймал ...
Входной файл имел вот такую вот структуру

REQUEST=SALE
ID=
CASHCODE=999
SHIFT=0
SCODE=9999
DATE= 9/08/2004
TIME=19:45
CHECKNUM=2
CARDNO=00100112882
CARDTYPE=SH
SUM1=30
SUM2=305
SUM=305
SUMTYPE=1
DISCTYPE=
DISCABS=0
DISCPERC=0
DOCNUM=
ERRORCODE=
MESSAGE=
CDEPT=1
VCODE=1

T=1,1,000001              ,"Товар в ассортименте            ",1.000,30,30,30,1,0,1         ,0
T=2,10,000010              ,"Обои в ассортименте             ",1.000,0,25,25,2,2,1         ,0
T=3,50,000050              ,"Смесители в ассортименте        ",1.000,0,250,250,2,2,1         ,0

Перекодируются только строки, начинающиеся на T=


Alx2   (2004-08-09 19:46:00) [17]

>Андрей Сенченко ©   (09.08.04 19:43) [19]
Твой последний вариант тоже не рабочий.


Андрей Сенченко   (2004-08-09 19:43:00) [18]

// Иначе будет  мусор

в последнем варианте его быть не должно по идее ... вот только если если по этому адресу была переменная большей длины - не знаю что произойдет.


Alx2   (2004-08-09 19:42:00) [19]

>Андрей Сенченко ©   (09.08.04 19:41) [17]
Опять нет инициализации для result. В итоге сразу AV поймаешь :)


Андрей Сенченко   (2004-08-09 19:41:00) [20]

Вот так в итоге ...

Function DosToWin (stDOS : string) : string;
begin
 if stDOS <>'' then CharToOem(PChar(stDos),PChar(Result))
 else Result := '';
end;

Function WinToDos (stWin : string) : string;
begin
 if stWin <>'' then CharToOem(PChar(stWin),PChar(Result))
 else Result := '';
end;


а вот насколько это быстрее - не на чем оценить


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо