Что нового

[Данные, строки] Помогите с бинарным файлом

Rjevsky

Новичок
Сообщения
102
Репутация
4
Здравствуйте. У нас в организации используется очень своеобразная почтовая программа Argomail, которая создаёт файлы с расширением *.msg. Эти файлики раскладывает серверная часть на подключаемый сетевой диск. Требуется написание скрипта, который, при наличии нового *msg выдавал всплывающее сообщение, причём с указанием темы и от кого файл отправлен. В общем самая главная трудность - считать от кого файл и его тему.
В TotalCommander по F3 в кодировке ASCII среди "кракозябр" можно найти всю необходимую информацию. В общем в этом и заключается вопрос: как сформировать массив или строку в удобном для поиска виде, причём не по всему файлу, т.к. файлы могут быть очень объёмными, а только по его начальным ~100 - 150 байтам.

В принципе кое-что я хоть коряво, но набросал. Но как оказалось мой скрипт отказывается работать с некоторыми файлами - съедает куски теста. Сам скрипт и проблемный файлик прилагаю.
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4,020
Репутация
626
По всей видимости письмо - это архив. но мой рар сказал что он битый.
твой декодер неправильно расшифровывает, по крайней мере я ничего путного беглым взглядом не увидел. но т.к. основная идея у тебя есть, напишу сюда как считывать строку за строкой, а дальше думаю сам разберешься, что делать со считанными строками.
Код:
#include <Array.au3>
$sMsgPath = @ScriptDir & '\S0002852.msg'
$hMsg = FileOpen ($sMsgPath, 0); Файл открывать через хендл, а потом обращаться уже к хендлу
While 1; Бесконечный цикл
	$sLine = FileReadLine($hMsg); Считываем первую строку, за след. шаг будет считываться уже вторая строка
	If @error = -1 Then ExitLoop; Если достигнут конец файла, выйти из цикла
	MsgBox(0, '', $sLine); Вывод строки
	;$a = StringToAscIIArray($l, 2); 
	;_ArrayDisplay($a); 
WEnd

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

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
А разве в самой программе нельзя настроить отправку уведомлений о приходе почты?
 
Автор
R

Rjevsky

Новичок
Сообщения
102
Репутация
4
msg - это не архив. Это файл со служебной информацией и приаттаченным к письму ахивом.

Ваш пример съедает в данном случае информацию также как и мой, а именно в третьей строке:
(привожу в ASCII, что бы было понятней)

вместо
_001080622 0910191441241БТF` 000А\ГРОДНО\УПРАВЛЕНИЕ\ОАОАGД`000А
выдаёт (+-пару символов)
_001080622 0910191441241БТF` 000

К тому же очень не хочется тратить время на чтение всего файла
Сегодня в справке нашёл _WinAPI_ReadFile может через эту функцию както замутить?

А разве в самой программе нельзя настроить отправку уведомлений о приходе почты?
Эта почто писалась в 80-х годах и предсталяет из себя DOS оболочку типа FAR. Как сама почта, так и функционал оставляет желать лучшего :smile:
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4,020
Репутация
626
и все равно, что-то функция декодировки вызывает у меня сомнения.
если разобраться, она сравнивает свой аргумент со строками - "-128" при условии что сумма аргумента и его абсолютной части равно нулю. тут сразу возникает несколько НО
1. условие равенства нулю числа со своим модулем, просто условие отрицательности числа. можно было бы просто указать $asci < 0
2. тесно связано с 1 - условие означает что аргумент - число. стало быть ни одно из подусловий в этой ветке If...Else не выполнится. ибо там везде сравнения со строками - "-128" и т.д. если нужно было сравнивать с числами, то кавычки ни к чему
3. альтернативная ветка else - если число не отрицательное (стало быть положительное), значит нужно вернуть его символ соответствующий его ASCII - коду. из первых двух пунктов следует, что выполняться всегда будет именно эта ветвь.
4. а теперь самое главное, функция применяется над элементами массива, значениями которого являются ASCII коды символов соответствующей строки. учитывая все вышесказанное, функция это число снова переводит в символ. то есть в результате комбинации Chr(Asc(symbol)) мы снова получим symbol. получается тождественная функция.
я сам в этих кодировках и прочих не особо силен. а так, в ТС я тоже увидел ГРОДНО и т.д. :smile:
 
Автор
R

Rjevsky

Новичок
Сообщения
102
Репутация
4
2kaster: декодирование делал нучным способом:создал письмо с полным алфавитом, проанализировал, какие цифры были присвоены в полученном массиве и сопоставил их в If...Then... Т.к. autoit русский шрифт представлял в виде отрицательных чисел, в коде и идёт проверка на отрицательность. Мой метод вполне работоспособен-запустите приаттаченный файл и убедитесь в этом. Хуже дело обстоит с чтением файла... Вот где требуется настоящая помощь, а то я уже в отчаянии...
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4,020
Репутация
626
хм... что-то я не увидел отрицательных чисел
Код:
#include <Array.au3>
$s = 'АаБбВвГгДдЕеЁёЖжЗзИиЙйКкЛлМмНнОоПпРрСсТтУуФфХхЦцЧчШшЩщЪъЫыЬьЭэЮюЯя' 		
$let = StringSplit($s, '')
$d = StringToASCIIArray($s)
Local $b[67][2]
For $i = 1 to 66
	$b[$i][0] = $let[$i]
	$b[$i][1] = AscW($let[$i])
Next
_ArrayDisplay($d)
_ArrayDisplay($b)

но опять же, если хочешь сравнивать аргумент с числами, то кавычки не нужны. они инструктируют интерпретатор о том, что между ними строка а не число


Добавлено:
Сообщение автоматически объединено:

упс. невнимательно прочитал. это уже в теле письма такие коды у русских букв? тогда ясно. можешь прислать письмо с исключительно русским алфавитом в теле?
только, посмотреть смогу только завтра. удачи
 
Автор
R

Rjevsky

Новичок
Сообщения
102
Репутация
4
Kaster сказал(а):
упс. невнимательно прочитал. это уже в теле письма такие коды у русских букв? тогда ясно. можешь прислать письмо с исключительно русским алфавитом в теле?
только, посмотреть смогу только завтра. удачи
так у меня нет проблем с алфавитом. беда в том, что при чтении файла построчно гдето теряются символы. В данном прмере в 3-й строке. Тоесть FileReadLine считывает не всю строку, а только её часть, а остальное игнорирует!
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Rjevsky [?]
беда в том, что при чтении файла построчно гдето теряются символы
А файл через FileOpen($file, 0) читается? есть ведь поддержка бинарного чтения (не 0 а 16).
 

ynbIpb

Скриптер
Сообщения
399
Репутация
110
а смещение темы письма в файле всегда одно?
читай бинарно и кодировка наверное досовская?
 
Автор
R

Rjevsky

Новичок
Сообщения
102
Репутация
4
ynbIpb сказал(а):
а смещение темы письма в файле всегда одно?
читай бинарно и кодировка наверное досовская?
проблема только в этом файле. остальные нормально читаются.
Да, кодировка, есстественно, досовская. Сегодня поэксперементировал: если читать так: $chars1 = BinaryToString(StringMid($chars, 60)) то я могу прочитать теряющийся текст. Но это не решение проблемы. Т.к. кажется я понял в чём дело:

В справке по FileReadLine есть пояснение:
Returns the text of the line read, any newline characters ( CHR(10) or @LF ) at the end of a line read in are automatically stripped.
Скорее всего, читая бинарный файл, в строке встречается один из этих симолов и autoit думает, что строка окончена и переходит на другую строку. Те сегодня этот сивол тут появился, завтра - может выскочить в другом месте.


CreatoR сказал(а):
А файл через FileOpen($file, 0) читается? есть ведь поддержка бинарного чтения (не 0 а 16).
Попробовал с 16 - ничего не изменилось.
 

snoitaleR

AutoIT Гуру
Сообщения
855
Репутация
223
Rjevsky
А что мешает использовать FileRead() вместо FileReadLine()?
 
Автор
R

Rjevsky

Новичок
Сообщения
102
Репутация
4
snoitaleR сказал(а):
Rjevsky
А что мешает использовать FileRead() вместо FileReadLine()?
я же не зря в разделе для новичков писал. :smile: Почитал справку. Буду пробовать :smile:
 

snoitaleR

AutoIT Гуру
Сообщения
855
Репутация
223
Rjevsky
Я подумал, что есть какие-то ограничения в использовании функции FileRead() и хотел узнать поподробней...
Это был не упрек... :smile:
 
Автор
R

Rjevsky

Новичок
Сообщения
102
Репутация
4
Вот и решение:

Код:
#include<Array.au3>
$bytestoread = 300
$file = FileOpen("S0002852.msg", 16)
Dim $a[1]
For $x = 1 to $bytestoread
	$chars = FileRead($file, 1)
        If @error = -1 Then ExitLoop
_ArrayAdd($a, $chars)
Next
FileClose($file)
_ArrayDisplay($a)


Всем спасибо за участие!
 
Верх