Найти - Пользователи
Полная версия: Форматное чтение из файла
Начало » Python для новичков » Форматное чтение из файла
1 2
Mottle
Доброе время суток!

Подскажите, пожалуйста, как прочитать из файла по формату?

В Fortran'е это выглядит так:

open(30,file=FileName)
read(30,100) a,b,(c(j),d(j),j=1,5),e,f,g
close(30)

100 Format(I2,1X,A6,1X,5(A2,F6.2),1X,I1,2F13.5)
Пытался делать так:
f=open(FileName,'r')
aaa=f.readline()
f.close()

a=aaa[0:2]
b=aaa[3:9]
.
.
.
Но, по-моему, как-то не спортивно получается…
knkd
</НЕНАВИСТЬ-НЕНАВИСТЬ-НЕНАВИСТЬ>
НЕНАВИЖУ ФОРТРАНОВСКИЙ ФОРМАТНЫЙ ВВОД
</НЕНАВИСТЬ-НЕНАВИСТЬ-НЕНАВИСТЬ>

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

Просто если между цифрами гарантировано остаются промежутки, то лучше использовать “строка”.split() и так и брать переменные из полученого списка. Если промежутков нет - тогда уже как не крути а придётся разбирать ручками, особенно если в одной строке форматы разные.
Андрей Светлов
Действительно, попробуйте объяснить вашу задачу на обыкновенном русском.
Я - ничего не понял.
На фортране писать не приходилось - только читать код некоторых алгоритмов. Согласитесь, это - абсолютно разные вещи.
Поэтому понять ничего не могу.
Mottle
Прощу прощения.
Попробую еще раз.

Строка выглядит так:
двузначное целое число, пробел, строка из щести символов, пробел, далее подряд пять раз строка из двух символов, шестизначное вещественное число, пробел.

12 аа ааа бб 12.456 вв 00.000 гг 00.000 дд 00.000 ее 00.000

Использование “строка”.split() не подходит так как в подстроке, которая должна быть прочитана в одну переменную могут встречаться пробелы.
pyuser
в C тоже есть функция форматированного чтения из строки: sscanf :)
пример использования есть в учебнике ctypes: http://python.net/crew/theller/ctypes/tutorial.html,
еще есть модуль scanf (http://hkn.eecs.berkeley.edu/~dyoo/python/scanf/), но его придется обработать напильником, чтобы работал с кирилицей, ну и еще можно почитать документацию по Python'у (для python 2.6 это пункт 8.2.6.2. Simulating scanf())
knkd
Понятно.
Позже попробую найти свои старые модули.

В общем идея такая:
Чтоб не разбирать руками, я делал файл-шаблон и разбирал уже по инструкциям из него.

Для вашего случая например, первая строка будет выглядеть примерно так:
2i 6s 2s 7f 2s 7f 2s 7f 2s 7f 2s 7f
А потом цикл который отмеряет куски строки и определяет тип переменной (str, int, float) по этому шаблону, результат собирается в список.
Если файлов с разным форматом много, то это намного проще чем задавать всё вручную.

Добавлено позже:
Сканф конечно лучше :)

Добавлено ещё позже:
Хотя по-моему он воспринимает пробел как разделитель.
PooH
Можно регуляркой разбирать, а регулярку строить по форматной строке
knkd
PooH
Можно регуляркой разбирать, а регулярку строить по форматной строке
Красивее конечно получится, но с циклом “шагами” проще локализовать место ошибки.

Этот фортрановский формат, же редкая зараза, особенно если без пробелов - один символ сместился и всё, тю-тю…
sypper-pit
он(PooH) предлогает отрабатывать регулярными вырожениями, это вполне нормальный способ , и найти и отладить ошибку особо не представляется сложным
Griffon
Я вот так реализовал бы:
def get_long_format(short_format_list):
short_format_list = list(short_format_list)
result = []
while short_format_list:
e = short_format_list.pop(0)
if isinstance(e, (tuple, list)):
buf = list(e[:-1] * e[-1])
buf.extend(short_format_list)
short_format_list = buf
else:
rep = {"s":str, "f":float, "i":int}
result += [(int(e[:-1]), rep[e[-1]])]
return result

def get_by_format(s, long_format):
result = []
i = 0
for k, f in long_format:
result.append(f(s[i:i+k]))
i += k + 1
return result

>> sformat = ("2i", "6s", ("2s", "6f", 4), "2s", "6s")
>> lformat = get_long_format(sformat)
>> lformat
[(2, <class 'int'>), (6, <class 'str'>), (2, <class 'str'>), (6, <class 'float'>), (2, <class 'str'>), (6, <class 'float'>), (2, <class 'str'>), (6, <class 'float'>), (2, <class 'str'>), (6, <class 'float'>), (2, <class 'str'>), (6, <class 'str'>)]

>> s = "12 аа ааа бб 12.456 вв 00.000 гг 00.000 дд 00.000 ее 00.000"
>> get_by_format(s, lformat)
[12, 'аа ааа', 'бб', 12.456, 'вв', 0.0, 'гг', 0.0, 'дд', 0.0, 'ее', '00.000']
Разбил что бы промежуточный результат было видно.

Интересно увидеть регуляркой.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB