Форум: "Основная";
Текущий архив: 2004.08.22;
Скачать: [xml.tar.bz2];
ВнизПерекодировка файла DOS в Win1251 Найти похожие ветки
← →
galexis © (2004-08-09 17:23) [0]Открываю файл как AssignFile(F, FileEdit.Text);
Reset(F);
while not eof(f) do
begin
Readln(F, S);
end;
файл ASCII, а надо win1251
И ведь знаю что легко и не раз делал, но замкнуло и все тут. И найти не могу. Помогите пожалуйста
← →
Sandman25 © (2004-08-09 17:24) [1]OemToChar
← →
VMcL © (2004-08-09 17:25) [2]>>galexis © (09.08.04 17:23)
OemToChar(), CharToOem().
← →
galexis © (2004-08-09 17:36) [3]Только не бейте,
а как строку S перекодировать?
← →
VMcL © (2004-08-09 17:38) [4]>>galexis © (09.08.04 17:36) [3]
Нет слов, одни выражения.
FAQ: http://www.delphimaster.ru/cgi-bin/faq.pl?look=1&id=988619604&n=19
← →
Sandman25 © (2004-08-09 17:39) [5]SetLength(S2, Length(S1));
OemToChar(PChar(S1), PChar(S2));
← →
wnew © (2004-08-09 17:48) [6]The OemToCharBuff function translates a specified number of characters in a string from the OEM-defined character set into either an ANSI or a wide-character string. (OEM stands for original equipment manufacturer.) This function supersedes the OemToAnsiBuff function.
BOOL OemToCharBuff(
LPCSTR lpszSrc, // pointer to string to translate
LPTSTR lpszDst, // pointer to buffer for translated string
DWORD cchDstLength // size of buffer
);
Parameters
lpszSrc
Points to a buffer containing one or more characters from the OEM-defined character set.
lpszDst
Points to the buffer for the translated string. If the OemToCharBuff function is being used as an ANSI function, the string can be translated in place by setting the lpszDst parameter to the same address as the lpszSrc parameter. This cannot be done if the OemToCharBuff function is being used as a wide-character function.
cchDstLength
Specifies the number of characters to translate in the buffer identified by the lpszSrc parameter.
Return Values
The return value is always nonzero.
← →
Мастер © (2004-08-09 17:52) [7]
> VMcL © (09.08.04 17:38) [4]
> >>galexis © (09.08.04 17:36) [3]
>
> Нет слов, одни выражения.
> FAQ: http://www.delphimaster.ru/cgi-bin/faq.pl?look=1&id=988619604&n=19
В FAQ ошибка.
Правильно будет так:function Win2Dos(const aStr: String): String;
begin
Result := aStr;
if Result="" then Exit;
CharToOem(PChar(Result),PChar(Result));
end;
function Dos2Win(const aStr: String): String;
begin
Result := aStr;
if Result="" then Exit;
OemToChar(PChar(Result),PChar(Result));
end;
← →
galexis © (2004-08-09 17:55) [8]Всем спасибо! Все получилось!
← →
Sandman25 © (2004-08-09 17:55) [9][7] Мастер © (09.08.04 17:52)
Тогда уже так:
if Length(Result) = 0 then exit;
Все-таки быстрее, чем строки сравнивать
← →
VMcL © (2004-08-09 18:04) [10]>>Sandman25 © (09.08.04 17:55) [9]
Почти монопенисуально. Можешь посмотреть CPU Window.
← →
Мастер © (2004-08-09 18:13) [11]>Sandman25 © (09.08.04 17:55) [9]
>VMcL © (09.08.04 18:04) [10]
И даже медленнее за счет лишнего вызова LStrLen.
← →
Андрей Сенченко © (2004-08-09 19:26) [12]>> Мастер © (09.08.04 17:52) [7]
а если так ?function Win2Dos(const aStr: String): String;
begin
if aStr <>"" then CharToOem(PChar(Result),PChar(Result));
else Result := aStr;
end;
function Dos2Win(const aStr: String): String;
begin
if aStr <>""then OemToChar(PChar(Result),PChar(Result));
else Result := aStr;
end;
← →
Alx2 © (2004-08-09 19:32) [13]>Андрей Сенченко © (09.08.04 19:26) [12]
Забыл Result := aStr вначале каждой функции. Тогда работать будет и "else" не нужен.
← →
Андрей Сенченко © (2004-08-09 19:33) [14]символы
;
передelse
наглядно демонстрируют, что самому было лень Delphi загружать :)
← →
Андрей Сенченко © (2004-08-09 19:35) [15]Alx2 © (09.08.04 19:32) [13]
Нет .. именно это и имелось в виду - сразу пойти на более часто встречающийся вариант ( то ес есть непустую строку ) и сэкомить тем самым время выполнения одной операции присвоения.
← →
Alx2 © (2004-08-09 19:38) [16]>Андрей Сенченко © (09.08.04 19:35) [15]
Я имел в виду следущее:
begin
Result := aStr; // Инициализация для Result.
// Иначе будет мусор
if aStr <>"" then CharToOem(PChar(Result),PChar(Result));
else Result := aStr; // тогда это не надо.
← →
Андрей Сенченко © (2004-08-09 19:41) [17]Вот так в итоге ...
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;
а вот насколько это быстрее - не на чем оценить
← →
Alx2 © (2004-08-09 19:42) [18]>Андрей Сенченко © (09.08.04 19:41) [17]
Опять нет инициализации для result. В итоге сразу AV поймаешь :)
← →
Андрей Сенченко © (2004-08-09 19:43) [19]
// Иначе будет мусор
в последнем варианте его быть не должно по идее ... вот только если если по этому адресу была переменная большей длины - не знаю что произойдет.
← →
Alx2 © (2004-08-09 19:46) [20]>Андрей Сенченко © (09.08.04 19:43) [19]
Твой последний вариант тоже не рабочий.
← →
Андрей Сенченко © (2004-08-09 19:47) [21]В итоге сразу 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=
← →
Мастер © (2004-08-09 19:49) [22]>Андрей Сенченко © (09.08.04 19:43) [19]
Function DosToWin (stDOS : string) : string;
begin
if stDOS <>"" then CharToOem(PChar(stDos),PChar(Result))
else Result := "";
end;
Под Result необходимо выделить память...
← →
Alx2 © (2004-08-09 19:50) [23]>Андрей Сенченко © (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;
← →
Alx2 © (2004-08-09 19:52) [24]>Андрей Сенченко © (09.08.04 19:47)
Я схватил AV на твоей реализации в примере: ShowMessage(WinToDos("Helo"));
← →
Андрей Сенченко © (2004-08-09 19:54) [25]Мастер © (09.08.04 19:49) [22]
не память а адрес в памяти - так наверное ?
Alx2 © (09.08.04 19:50) [23]
странно что работает в этом случае ... то есть сам по себе запуск функции еще не определяет физического адреса для ее результата ?
← →
Андрей Сенченко © (2004-08-09 19:57) [26]всё. ... извините, что ввел в заблуждение ... там функция в этом синтаксисе перекрыта была другой, объявленной напрямую в юните.
Действительно AV вышибает.
← →
Alx2 © (2004-08-09 19:57) [27]>Андрей Сенченко © (09.08.04 19:54) [25]
Для строк - не определяет. Потому-что, например, неизвестно сколько ты в этот результат зальешь данных. В итоге ты передаешь функции API "битую ссылку". Эта функция считает, что ты позаботился о месте для размещения данных и заполняет их "не глядя". Нужно выполнить требование, чтобы Result имел длину не менее первого аргумента. Тут либо SetLength, либо еще чего наподобие :)
← →
Андрей Сенченко © (2004-08-09 20:03) [28]Модераторам просьба - удалите мой вариант. ибо нефиг тут некорректному коду делать
← →
Proshka (2004-08-09 20:14) [29]ребят я наверно протупил гдето, но у меня в этой строчке
"RichEdit2.Lines.Add (DosToWin(RichEdit1.Lines.Strings[i]))"
постоянно насилуют Аксеса. Обидно что изза меня хороший парень страдает. помогите пожалуста понять почему так.
← →
Мастер © (2004-08-09 20:20) [30]>Proshka (09.08.04 20:14) [29]
Не используй при вызове переменную класса.
← →
Alx2 © (2004-08-09 20:29) [31]>Proshka (09.08.04 20:14)
Функицю перепиши по-другому:
Function DosToWin (Const stDOS : string) : string;
begin
Result := stDos;
if Result <>"" then CharToOem(PChar(Result),PChar(Result))
end;
← →
Proshka (2004-08-10 01:30) [32]голяк :no: я путался по разному изголяться но у меня из строки
0 ЏђЋѓђЂЊЊЂ/ adem ;
получается только:0 _________/ adem ;
а должно быть0 ПРОГРАММА/ adem ;
вот
может есть какие идеи а
← →
Proshka (2004-08-10 03:19) [33]а-а-а понял в
DosToWin
надо юзатьOemToChar
у вас опечатка а я тупо скопировал :)
← →
VMcL © (2004-08-10 07:22) [34]По сабджу.
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;
← →
Anatoly Podgoretsky © (2004-08-10 09:11) [35]Из всех предложеных вариантов, только вариант 2 от VMcL © (10.08.04 07:22) [34] будет безболезненый, остальные варианты страдают той или другой степень ошибок/проблем. Единственно, что надо сделать это только сменить имя функции, поскольку в Вин АПИ такое имя уже существует и могут быть из за этого проблемы.
← →
Sandman25 © (2004-08-10 09:11) [36][10] VMcL © (09.08.04 18:04)
[11] Мастер © (09.08.04 18:13)
Век живи - век учись.
Спасибо!
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2004.08.22;
Скачать: [xml.tar.bz2];
Память: 0.54 MB
Время: 0.037 c