Форум » [x]Harbour » Беда с функцией AfterATNUM() .... » Ответить

Беда с функцией AfterATNUM() ....

Andrey: Делал обработку текстового файла (в конце строки всегда стоит CHR(13)+CHR(10) ) Не могу получить первую строку функцией AfterATNUM() .... Результирующий файл различается от входящего ! Может как нибудь по другому можно ? Вот примерный текст программы: [more] FUNCTION MAIN() LOCAL nI, nLen, cSource, cTarget := "", cTemp cSource := FILESTR("User5.txt") nLen := NUMAT( CHR(13)+CHR(10), cSource ) ? " Kol-vo CHR(13)+CHR(10) = ",nLen FOR nI := 1 TO nLen ? nI cTemp := AfterATNUM( CHR(13)+CHR(10), cSource, nI ) ? cTemp,"-",LEN(cTemp) // ---- обработка строки ------ // cTemp := MyCRYPT(cTemp) cTarget := cTarget + cTemp + CHR(13)+CHR(10) NEXT STRFILE(cTarget,"User52.txt",.F.) WAIT RETURN NIL [/more]

Ответов - 52, стр: 1 2 3 All

Dima: Можно так сделать и не придумывать велосипед FUNCTION MAIN() LOCAL nI, nLen, cSource, cTarget := "", cTemp /* cSource := FILESTR("User5.txt") nLen := NUMAT( CHR(13)+CHR(10), cSource ) ? " Kol-vo CHR(13)+CHR(10) = ",nLen FOR nI := 1 TO nLen ? nI cTemp := AfterATNUM( CHR(13)+CHR(10), cSource, nI ) ? cTemp,"-",LEN(cTemp) // ---- обработка строки ------ // cTemp := MyCRYPT(cTemp) cTarget := cTarget + cTemp + CHR(13)+CHR(10) NEXT */ if hb_fuse("user5.txt")#-1 do while !hb_feof() Ctarget+=hb_freadln()+CHR(13)+CHR(10) // вот тут можно сразу писать в USER52.TXT , предварительно его открыв в // другом Hb_fselect() hb_fskip() enddo Hb_fuse() STRFILE(cTarget,"User52.txt",.F.) endif RETURN NIL

Dima: PS Для Xharbour - LibMisc.lib Для Harbour - Hbmisc.lib

Vlad04: В Xharbour чтение и разбор текстовых файлов делаю так: cFileNameTxt:="User5.txt" IF FILE(cFileNameTxt) cFileText := TFileRead():New( cFileNameTxt ) cFileText:Open() WHILE cFileText:MoreToRead() cLine:= cFileText:ReadLine() // ваша обработка строки END WHILE //ENDDO cFileText:Close() ENDIF <a href=http://www.es.7searchsoft.com/ >programas gratis</a>


Dima: Andrey пишет: Не могу получить первую строку функцией AfterATNUM() И нужно было использовать BeforATNUM и тогда 1 строка не потеряется и учитывать 4 параметр в этой функции

Andrey: Спасибо БОЛЬШОЕ Vlad04 и Dima !!!

Andrey: Dima пишет: И нужно было использовать BeforATNUM и тогда 1 строка не потеряется и учитывать 4 параметр в этой функции Что-то не получается и с ней !!! Я могу конечно обойтись и как вы предложили и как у меня уже есть сделанные функции, но хотелось бы разобраться с этими НЕПОНЯТНЫМИ функциями. Уж больно исходник маленьким получается, без доп.библиотек ! Вот исправленный текст FUNCTION MAIN() LOCAL nI, nLen, cSource, cTarget := "", cTemp, nSkipChars cSource := FILESTR("User5.txt") ? "Len User5.txt =",LEN(cSource) nLen := NUMAT( CHR(13)+CHR(10), cSource ) ? " Kol-vo CHR(13)+CHR(10) = ",nLen FOR nI := 1 TO nLen ? nI //nSkipChars := ATNUM( CHR(13)+CHR(10), cSource, nI-1 ) //? nSkipChars cTemp := BeforATNUM( CHR(13)+CHR(10), cSource, nI ) ? cTemp,"-",LEN(cTemp) // ------------- обработка строки ---------------- // cTemp := MyCrypt(cTemp) cTarget := cTarget + cTemp + CHR(13)+CHR(10) ? LEN(cTarget) NEXT ? ? "Len User52.txt =",LEN(cTarget) STRFILE(cTarget,"User52.txt",.F.) WAIT RETURN NIL

Pasha: Намного эффективнее будет использование функций TokenInit - TokenNext - TokenEnd: Local cTokenEnv := '' Local cTok := Chr(13) + Chr(10) TokenInit(@c, cTok,, @cTokenEnv) while ! TokenEnd(@cTokenEnv) cLex := TokenNext(c,, @cTokenEnv)) enddo В случае AtNum - BeforeAtNum строка каждый раз в цикле просматривается с самого начала, что крайне неоптимально, а TokenNext "ползет" по строке, выбирая следующую лексему

Andrey: Pasha пишет: TokenInit(@c, cTok,, @cTokenEnv) Да действительно, это оптимальней и лучше для больших файлов !!! Спасибо БОЛЬШОЕ Паша !!! Вот рабочая программа FUNCTION MAIN() LOCAL nI := 1, cSource, cTarget := "" Local cTokenEnv := '', cLex Local cTok := Chr(13) + Chr(10) cSource := FILESTR("User5.txt") ? "Len User5.txt =",LEN(cSource) TokenInit(@cSource, cTok,, @cTokenEnv) DO while ! TokenEnd(@cTokenEnv) cLex := TokenNext(cSource,, @cTokenEnv) ? nI++ ? cLex, LEN(cLex) // ------------- обработка строки ---------------- // cTemp := MyCrypt(cTemp) cTarget := cTarget + cLex + CHR(13)+CHR(10) enddo ? ? "Len User52.txt =",LEN(cTarget) STRFILE(cTarget,"User52.txt",.F.) WAIT RETURN NIL

santy: Пример из хелпа xHarbour функции TokenInit() // This example does the same, but takes advantage of local tokenizer // environments. The performance is about 20% better compared to the // global tokenizer environment, since SaveToken() and RestToken() are // not needed. #define CRLF Chr(13)+Chr(10) PROCEDURE Main LOCAL cText := MemoRead( "Textfile.txt" ) LOCAL cToken, cTokenEnv LOCAL aLines := {} LOCAL nLines := 0 LOCAL nWords := 0 // initialize local tokenizer environment TokenInit( @cText, CRLF, 2, @cTokenEnv ) DO WHILE .NOT. TokenEnd( @cTokenEnv ) cToken := TokenNext( @cText, , @cTokenEnv ) IF cToken == "" // one blank space is an empty line for AChoice() cToken := " " ENDIF nLines ++ nWords += WordCount( @cToken ) AAdd( aLines, cToken ) ENDDO // display the text file AChoice( ,,,, aLines ) CLS ? "Line count:", nLines ? "Word count:", nWords RETURN FUNCTION WordCount( cText ) LOCAL cTokenEnv LOCAL nWords := 0 TokenInit( @cText, " ,.!?", @cTokenEnv ) DO WHILE .NOT. TokenEnd( @cTokenEnv ) TokenNext( @cText, , @cTokenEnv ) nWords ++ ENDDO RETURN nWords

Dima: Andrey У тебя вроде ж должен быть xHarbour Language Reference Guide , посеял что ли ? :)

Andrey: Dima пишет: У тебя вроде ж должен быть xHarbour Language Reference Guide Да есть он у меня, просто ночью делал и начал как в клипере с NUMAT() и на нем зациклился. А с TOKEN() у меня всегда непонятка была. Не люблю я его. Спасибо Паша направил на путь истинный... А уж после него и сам в Хелпе обнаружил...

Andrey: Теперь другая фигня ! Хочу в лог-файл добавлять данные, но чтоб пользователь не мог видеть и править их. Беру файл, построчно шифрую и записываю в другой. Потом проверяю: считываю шифрованный файл, построчно разбираю, дешифрую строку и записываю в другой файл. Не работает ! Остаются куски шифрованные ! Вот текст программы: FUNCTION MAIN() Local nI := 1, cSource, cTarget := "" Local cTokenEnv := '', cLex, cLex2 Local cTok := Chr(13) + Chr(10) Local cFileIsx := "User5.txt", cFileCrypt := "User5crypt.txt" Local cFileDeCrypt := "User5DeCrypt.txt", cPassWord := "testfile" CLEAR SCREEN ? ? cSource := FILESTR(cFileIsx) ? "Len "+cFileIsx+" =",LEN(cSource)," bytes" TokenInit(@cSource, cTok,, @cTokenEnv) DO while ! TokenEnd(@cTokenEnv) cLex := TokenNext(cSource,, @cTokenEnv) ? "Stroka:",nI++ //? cLex, LEN(cLex) // ------------- обработка строки ---------------- cLex := HB_Crypt( cLex, cPassWord ) cTarget := cTarget + cLex + cTok enddo ? ? "Len "+cFileCrypt+" =",LEN(cTarget)," bytes" STRFILE(cTarget,cFileCrypt,.F.) ? ? ? "DeCrypt file: "+cFileCrypt cSource := FILESTR(cFileCrypt) ? "Len "+cFileCrypt+" =",LEN(cSource)," bytes" cTarget := "" nI := 1 cTokenEnv := '' TokenInit(@cSource, cTok,, @cTokenEnv) DO while ! TokenEnd(@cTokenEnv) cLex := TokenNext(cSource,, @cTokenEnv) ? "Stroka:",nI++ // ------------- обработка строки ---------------- cLex2 := HB_DeCrypt( cLex, cPassWord ) // ? cLex2, LEN(cLex2) cTarget := cTarget + cLex2 + cTok enddo ? ? "Len "+cFileDeCrypt+" =",LEN(cTarget)," bytes" STRFILE(cTarget,cFileDeCrypt,.F.) ? WAIT RETURN NIL Кто поможет ? Может не надо использовать Chr(13) + Chr(10), а делать свои метки ?

Dima: Проверил на простом USER5.TXT Cодержимое 111 222 333 444 После отработки программы содержимое файла User5DeCrypt.txt == User5.txt PS В User5crypt.txt все chr(13)+chr(10) на своих местах

Andrey: Dima пишет: Проверил на простом USER5.TXT Это мало. Сделай из DBF-файла (записей 6) CVS-файл, с разделителем "," ! Можно через DBU.EXE

Dima: Сделал , все в норме. Дай свой текст USER5.TXT PS Глянь свой User5.txt в 16-ричном виде (можно через Far) , может у тебя где то chr(13) потерялся в конце какой то строки

Andrey: Dima пишет: Дай свой текст USER5.TXT Даю. Заодно и программу на хХарборе 1.0.0 http://files.mail.ru/IMUKCV

Dima: Andrey LOL Забей в файлике User5.txt всего одну строчечку и сделай после нее перевод строки , прогу запусти и глянь результат в User5DeCrypt.txt Строка такая w:\fond9\abonent4.exe"," или вот так ;) w:\fond9"," или так w:\fond9" ЗЫ Harbour 2.0.0 так же сработал (я о результате в User5DeCrypt.txt)

Andrey: Блин, фигня получается.... Файл считывается правильно, а дальше не работает: TokenInit(@cSource, cTok,, @cTokenEnv) DO while ! TokenEnd(@cTokenEnv) cLex := TokenNext(cSource,, @cTokenEnv) ? "Stroka:",nI++ ?? ":",cLex // ------------- обработка строки ---------------- cLex2 := HB_DeCrypt( cLex, cPassWord ) // ? cLex2, LEN(cLex2) cTarget := cTarget + cLex2 + cTok enddo Т.е. TokenNext(cSource,, @cTokenEnv) выдает неправильную строку !!! А что делать то ? Как исправить данную ситуацию ? Может не надо использовать Chr(13) + Chr(10), а делать свои метки ?

Dima: Crypt , Decrypt по таким строкам работает верно (проверил) Возможно где то косяк в твоей функции (я особо не вникал) Хотя довольно странно Так не работает w:\fond9" А так работает :\fond9" В обоих случаях в конце строки есть перевод строки.

Dima: Andrey пишет: А с TOKEN() у меня всегда непонятка была. Не люблю я его. Пробни то что то Vlad04 предложил или я.

Andrey: Dima пишет: Возможно где то косяк в твоей функции (я особо не вникал) Хотя довольно странно Косяк в выборке строки: TokenInit(@cSource, cTok,, @cTokenEnv) DO while ! TokenEnd(@cTokenEnv) cLex := TokenNext(cSource,, @cTokenEnv) ? "Stroka:",nI++ ?? ":",cLex enddo Отдельно даже сделал. Не работает TokenNext !

Dima: Содержимое user5.txt 12345 00000 11111 w:\fond9" 22222 absder проверка В 4 строке Фсё сломается , хотя после нее (и до нее) все верно....... Разделители у тебя указаны явно , ХЗ в чем дело. Перевод строки везде есть ЗЫ Результат

Andrey: Если заменить cTok := "{}" заместо Chr(13) + Chr(10) тоже самое происходит ! Видать все таки дело в TokenNext(cSource,, @cTokenEnv) ! Хотя если убрать " - то все нормально проходит !!! Все дело в кавычках " !!! Надо писать разработчикам TokenNext ! Кто сможет ?

Dima: Andrey пишет: Надо писать разработчикам TokenNext ! Кто сможет ? Могу ошибаться , но кажется Павел уже занимается этим.

Andrey: Переделал программу на твою функцию. С простой строчкой нормально, с CVS-строкой содержащие кавычки (") - опять косяки !!! Вот пример в архиве ---------- Андрей не надо выкладывать мое мыло ладно ? Ссылку потер Утилита dub.exe - сравнение 2х-файлов. Где бы такую Виндовую взять ?

Dima: Andrey Уверен что в твоем файлике каждая кавычка имеет пару (я не чекал) ? Просто вспомнил что если открывать CSV файлик в котором есть не парные кавычки в EXCEL то после такой кавычки (все что после нее) типа съедается EXCEL (пока не начнешь редактировать) Впрочем о чем это я ? Excel тут не при чем , это так просто вспомнилось... И потом , Андрей скажи ну зачем тебе в этом файле нужны кавычки ? Сейчас 20100601,114,"SERVER-XP","Андрей", Так уже не достаточно будет ? 20100601,114,SERVER-XP,Андрей, В качестве разделителя если не ошибаюсь (в CSV) принято ставить ; PS А не парные кавычки у тебя есть по ходу , только что заметил.

Pasha: Проблема заключается не в token в разных вариациях, а в HB_Crypt. В результате ее работы в зашифрованную строку случайным образом попадают коды #13#10, которые затем и портят всю малину

Dima: Pasha Можешь на примере показать (если это реально) ?

Dima: Andrey пишет: Утилита dub.exe - сравнение 2х-файлов. Где бы такую Виндовую взять ? Поиск поюзай ;) На вскидку (проверил) такая функция есть в Total Commander PS Юзани (нужна рега) _http://forum.ru-board.com/forum.cgi?action=filter&forum=35&filterby=topictitle&word=compare

Pasha: А что там показывать, двоичные коды, что ли ? результатом hb_crypt('20100601,114,"SERVER-XP","Андрей","","w:\fond9\abonent4.exe","4.66f",20100521,"Системный а.",101,T,F,F,318288412,10,"Net","Vxod",2,"Вход успешен !",1', cPassword) будет строка, содержащая Chr(13)+Chr(10) и никакой другой разделитель использовать нельзя, так как результат работы любого симметричного криптоалгоритма (хотя hb_crypt до криптоалгоритма не дотягивает) может содержать этот разделитель, что в дальнейшем исказит дешифровку. Андрею можно посоветовать сбрасывать лог не в текстовый файл, а в дбф с мемо-полем. Такой алгоритм будет работать

Dima: Pasha То есть функцией hb_crypt пользоваться не следует , так как результат может быть не предсказуем... Так ?

Pasha: Нет конечно. Результатом этой функции является зашифрованная строка, содержажая коды от 0 до 255 в любой последовательности. При этом нельзя использовать никакой разделитель строк, так как этот разделитель, состоящий из одного или более символов, может оказаться в зашифрованной строке. Ей можно пользоваться, когда длина строки содержится вне строки. К примеру, если использовать такой формат: 2-4 байта - длина строки, строка, следующая строка с префиксом - ее длиной, и т.д. Или файл с мемо-полем, что тоже самое.

Andrey: Pasha пишет: Или файл с мемо-полем, что тоже самое. Не хочу заморачиваться с dbf ! Pasha пишет: К примеру, если использовать такой формат: 2-4 байта - длина строки, строка, следующая строка с префиксом - ее длиной, и т.д. Вот это интересней, только не пойму как считывать строку ? Как будет выглядеть файл (2-3 строчки) ?

Pasha: Примерно так. Пусть aStr - массив строк Запись массива строк в строку: cStr := "" AEval(aStr, {|c| cStr += I2Bin(len(c)) + c}) Чтение из строки в массив строк: nPos := 1 while nPos <= len(cStr) nLen := Bin2I(Substr(cStr, nPos, 2)) nPos += 2 AADD(aStr, Substr(cStr, nPos, nLen)) nPos += nLen enddo внутрь цикла можно вставить шифровку/дешифровку

Andrey: Нет, ни как не въеду ! Дай пожалуйста образец файла, как он будет выглядеть ? Черкани 3 строчки файла....

Pasha: ДлинаСтр1 (2 байта) Стр1 ДлинаСтр2 (2 байта) Стр2 ...

Andrey: Pasha пишет: ДлинаСтр1 (2 байта) Стр1 ДлинаСтр2 (2 байта) Стр2 ... А как искать вхождения строк ? по маске "(xx)" или еще как ?

Pasha: Вхождения каких строк куда надо искать ? В этой теме поиск вхождения строк мы еще не обсуждали

Andrey: Pasha пишет: Чтение из строки в массив строк: nPos := 1 while nPos <= len(cStr) nLen := Bin2I(Substr(cStr, nPos, 2)) nPos += 2 AADD(aStr, Substr(cStr, nPos, nLen)) nPos += nLen enddo Я вот про это .....

Pasha: Андрей, ты говоришь загадками... Что-то с этим кодом непонятно ? И при чем здесь вхождение строк ?

Andrey: Ладно, буду делать рабочий тест. А там поглядим....

Vlad04: Еще вариант. Зашифрованный текст ( в данном случае разборка на строки не нужна) кодируем типа как почтовые программы. Или в цифры, как ниже: ( код на Паскале) function Koder(s: string): string; var i: integer; t: string; begin for i:=1 to Length(s) do begin t:=t+inttostr((ord(s[ i ])*2-100)*3)+' '; end; Result:=t; end; //****************************************************************** function Dekoder(s: string): string; var i,a: integer; t,z: string; begin z:=' '; a:=0; for i:=1 to Length(s) do begin if s[ i ]<>' ' then z:=z+s[ i ] else begin a:=strtoint(z); a:=round((a/3+100)/2); t:=t+chr(a); z:=' '; a:=0; end; end; Result:=t; end; Я в Делфях так делаю

gustow: Vlad04 пишет: t:=t+inttostr((ord(s)*2-100)*3)+' '; Влад, у тебя там, видимо, "ord(s[ i ])*2..." должно быть (судя по тому, что начиная со скобки после "s" в посте все идет курсивом). Обычная тут (в постах форума) ошибка (и у меня бывали) при наличии в коде работы с элементами массивов, где параметр цикла "i" (форумный движок воспринимает такое сочетание как тэг начала курсива)... Надо просто внутри "[ ]" ставить в начале и конце пробелы, тогда в посте все нормально выглядит (да и "предпросмотр" - вещь полезная :) особенно когда сюда копипастить кусок кода). Извиняюсь за "мелочные придирки" :) - просто иногда тяжело в большом куске кода бывает разобраться, просто скопипастив его из поста ("и чё оно не работает??.."), где потерялось "[ i ]".

Dima: gustow Поправил .

Dima: Andrey Не пробовал вместо HB_CRYPT , HB_UUEncode (HB_UUDecode) ?

Andrey: Dima пишет: Не пробовал вместо HB_CRYPT , HB_UUEncode (HB_UUDecode) ? Нет, не пробовал. Посмотрю конечно. Спасибо. Я понял, что Паша мне дал (ну заклинился на другом), сейчас это делаю ! Дошло наконец-то....

Andrey: ВОТ засада, то какая ! Если удалить хоть один байт с ТАКОГО файла (что Паша предложил), то раскодировать этот файл больше нельзя !!! И нафига такие заморочки с кодированием ? Есть ли другие способы ? Может заместо CHR(13)+CHR(10) взять разделитель типа [МояМетка] ? Вероятность того, что при шифрации строк может получиться такая комбинация - равна 0 !!!

Dima: Andrey пишет: Есть ли другие способы ? я же предлагал (на твоем примере не проверял). Dima пишет: Не пробовал вместо HB_CRYPT , HB_UUEncode (HB_UUDecode) ?

Pasha: Andrey пишет: ВОТ засада, то какая ! Если удалить хоть один байт с ТАКОГО файла (что Паша предложил), то раскодировать этот файл больше нельзя !!! И нафига такие заморочки с кодированием ? Есть ли другие способы ? Может заместо CHR(13)+CHR(10) взять разделитель типа [МояМетка] ? Вероятность того, что при шифрации строк может получиться такая комбинация - равна 0 !!! Чем больше символов содержит разделитель, тем меньше вероятность того, что он случайно будет содержаться в результате криптофункции. Так что это тоже вариант, хоть и не железный. А вариант с длиной строки - железобетонный Ж) А насчет удаления одного байта: надо тогда сформулировать, в чем заключается задача. Пользователь не должен видеть логи, но может захотеть их "испортить" ? Испортить файл с длиной строки и шифрованной строкой действительно можно удалением одного байта. Если шкодник захочет испортить файл с разделителем - он может стереть его содержимое. Помешать ему нельзя. Можно лишь фиксировать сам факт вмешательства - например, всегда дописывать в конец файла значение хэш, или, на худой конец, crc32

Dima: Pasha пишет: А насчет удаления одного байта: надо тогда сформулировать, в чем заключается задача +1

Andrey: Задача: Хочу в лог-файл добавлять данные, но чтоб пользователь не мог видеть и править их. Вариант удаления файла не рассматриваю, не важен пока. Если кто-то попортит файл, то хотелось бы вытащить оставшиеся данные. Т.е. шифрация всего файл-лога тоже не прокатывает, т.к. урезание нескольких байтов приведет к невозможности расшифровки всего остального файла. Вот и вся задача.

Dima: Andrey Ну прячь его где то подальше. Имя файлу придумай такое что бы ни ХТО не догадался ;) Как вариант можно лог в Zip архив запихать с паролем , правда тут придется подумать как лучше это сделать. Испортить зловред может ведь не только лог файл но и базу... PS Однако вумные юзеры у тебя.



полная версия страницы