Меню
Видеоучебник

Работа с файлами

Урок 22. Основы алгоритмизации и программирования на языке Python

При работе со структурными типами данных ввод данных с клавиатуры и их вывод на экран имеют целый ряд недостатков. Так, ввод данных с клавиатуры занимает много времени, а при выводе на экран полученные данные сложно использовать где-то ещё. Эти недостатки устраняет файловый ввод-вывод данных. Именно о нём пойдёт речь в этом видеоуроке. Ученики узнают о том, какие есть основные инструменты обработки файлов в языке Python, а также запрограммируют файловый ввод-вывод при решении нескольких задач.

Конспект урока "Работа с файлами"

Вопросы:

·     Типы файлов, с точки зрения программиста.

·     Программирование файлового ввода/вывода.

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

С точки зрения программиста, все файлы можно разделить на 2 типа: текстовые и двоичные. В первых файлах хранится лишь текст, разделённый на строки, то есть единственный служебный символ, который может встретиться в текстовом файле – это символ перехода на следующую строку. В двоичных же файлах информация хранится в виде двоичного кода, так в них может храниться звук, изображение или другие типы информации. Мы будем изучать файловый ввод/вывод только для текстовых файлов.

В большинстве языков программирования файлы представляются через вспомогательные или иначе файловые переменные. Обработку фалов можно разделить на 3 этапа, порядок следования которых никогда не меняется. Обработка файла всегда начинается с того, что программа его открывает. При этом создаётся файловая переменная, которой в качестве значения присваивается нужный файл. После открытия файла следует считывание данных из него или, напротив, вывод данных в него. После того, как был осуществлён ввод/вывод данных, файл закрывается, при этом в нём сохраняются внесённые изменения.

Рассмотрим, как запрограммировать файловый ввод/вывод на языке Python. Для того, чтобы открыть файл, создаётся файловая переменная. Ей присваивается значение функции open, у которой нужно указать 2 строковых параметра. Первый параметр - это имя файла, который нужно открыть. Если файл находится не в одной папке с модулем, помимо имени файла в этой строке указывается ещё и адрес, по которому он находится. Второй параметр – это режим открытия файла. Всего есть три режима открытия файла: открытие файла для чтения обозначается буквой 'r' от английского слова «read», что означает «читать». При этом, если файл с заданным именем не будет найден по указанному адресу, то результатом этой функции будет исключение типа FileNotFoundError. Второй режим открытия файла – для записи. Он обозначается буквой 'r' от английского слова «write», что означает «писать». При открытии файла для записи все данные из него стираются. Если указанный файл не найден, по указанному адресу создаётся новый файл с указанным именем. И третий режим открытия – для добавления данных. Он обозначается буквой 'a' от английского слова «add», что означает «добавить». При таком открытии данные добавляются в конец файла. Если указанный файл не найден, то, как и в случае с режимом для чтения, будет возвращено исключение типа FileNotFoundError. Для того, чтобы закрыть файл, у соответствующей ему файловой переменной вызывается метод close без параметров.

Таким образом, в коде ввод данных из файла можно представить так.

f = open ('filename.txt', 'r')

<инструкции считывания данных>

f.close ()

А вывод данных в файл – так.

f = open ('filename.txt', 'w')

<инструкции вывода данных>

f.close ()

Для считывания данных из файла у файловой переменной может быть вызван метод readline, для считывания из файла одной символьной строки. Для считывания всех оставшихся данных из файла до самого конца используется метод read без параметров, он возвращает список символьных строк, содержащихся в файле. У метода read может быть один целочисленный неотрицательный параметр. Он означает количество символов, которое будет считано из файла. Все эти методы могут быть вызваны только в случае, если файл открыт для чтения.

Для вывода данных в файл используется метод write. В нём в качестве параметра указываются выводимые данные. При этом, если в файл нужно вывести числовые данные, то из них с помощью метода format сначала формируется символьная строка. Метод write возвращает количество символов, которые было выведено в файл.

Решим несколько задач с использованием файлового ввода/вывода. В файле input.txt в одной строке, через пробел, записаны целые неотрицательные числа. Заменить эти числа суммами их цифр.

Начнём написание программы. Вначале опишем функцию вычисления суммы цифр из числа. Назовём её sumDigits. У неё будет один параметр – целое число n. В теле функции объявим переменную s = 0. Её мы будем использовать для расчёта суммы цифр. Дальше напишем цикл while, который будет работать до тех пор, пока в n ещё остались цифры, то есть пока оно больше нуля. В теле цикла будем увеличивать переменную s на значение правой цифры числа n, выделенной как его остаток от деления на 10. После чего будем убирать из n его правую цифру, при помощи безостаточного деления его значения на 10. После цикла вернём значение s в основную программу.

def SumDigits (n):

    s = 0

    while n > 0:

        s = s + n % 10

        n = n // 10

    return s

Теперь начнём описание основной программы. Объявим файловую переменную f, и с помощью функции open откроем в ней файл для чтения. Создадим переменную t, в которую будем считывать данные из файла. Так как по условию в файле всего одна строка, для чтения данных мы можем использовать как метод readline, так и метод read без параметров. Так как мы считали данные из файла, закроем его, вызвав у переменной f метод close. Теперь в переменной t у нас хранится текстовая строка, состоящая из чисел, разделённых пробелами. Чтобы получить из неё числа, сначала присвоим t значение метода split, вызванного у этой строки. Теперь в t хранится список символьных строк, в каждой из которых хранится одно число. Чтобы преобразовать их в целочисленный тип данных, присвоим t список, состоящий из результатов функции int от его нынешних элементов. Таким образом мы получили список чисел.

Теперь в переменной f снова откроем файл input.txt, на этот раз для записи. Напишем цикл с параметром x, который будет принимать значения элементов списка t. В этом цикле в файл, соответствующий переменной f, с помощью метода write будем выводить значения функции sumDigits от параметра x. С помощью функции format сформируем строку, состоящую из указанного значения и пробела. Закроем файл, соответствующий переменной f. Описание программы завершено, сохраним её.

f = open ('input.txt', 'r')

t = f.readline ()

f.close ()

t = t.split ()

t = [int (x) for x in t]

f = open ('input.txt', 'w')

for x in t:

    f.write ('{:d} '.format (SumDigits (x)))

f.close ()

Теперь прямо в среде разработки создадим новый файл. Через пробел запишем в него числа: 1024, 18, 35 и 3. Сохраним созданный файл под именем input.txt в одной папке с описанным модулем. Закроем его. Теперь запустим на выполнение описанную программу и откроем файл input.txt. Теперь в нём содержатся числа: 7, 9, 8 и 3. Это суммы цифр тех чисел, которые содержались в нём изначально. Программа работает правильно.

Рассмотрим ещё одну задачу. В файле, имя которого указывает пользователь, содержится матрица  из чисел. Все её строки начинаются с нулей и единиц. Вывести в файл output.txt эту матрицу без первых цифр в строках. Отсортировав те строки, которые начинались с единиц по неубыванию, а те, которые начинались с нулей – по невозрастанию. Предусмотреть неверный ввод имени файла пользователем.

Начнём написание программы. С помощью инструкции print выведем на экран запрос на ввод имени файла-источника. Дальше напишем бесконечный цикл, в котором в блоке try, в переменной f_in, попытаемся открыть файл для чтения, имя которого считаем с помощью функции input. После открытия файла запишем инструкцию break, прерывающую цикл. Запишем блок except для исключения типа FileNotFoundError. В этом блоке запишем инструкцию print, которая будет выводить на экран сообщение о том, что заданный файл не найден, и запросом на повторный ввод имени файла.

После того, как мы открыли заданный файл для чтения, откроем в переменной f_out файл output.txt для записи. Дальше напишем цикл для считывания из файла строк матрицы. Это будет цикл с параметром line, изменяющимся в файле, соответствующем переменной f_in. В таком цикле параметр line будет принимать значения строк указанного файла. В этом цикле будем присваивать переменной s список чисел из строки line, полученных с помощью метода split, вызванного у строки. Преобразуем элементы этого списка в целочисленный тип с помощью выражения-генератора, результат которого присвоим переменной s. Как мы помним, от значения нулевого элемента списка s зависит то, как мы будем сортировать остальные его элементы. Если его нулевой элемент равен 1, то мы должны сортировать элементы по неубыванию, если же это 0 – по невозрастанию. Присвоим переменной s значение функции sorted от элементов списка s, от первого до последнего, с параметром reverse, равным значению нулевого элемента списка s, взятому с отрицанием. Почему мы можем сделать такую запись? Вспомним, что значения типа int можно неявно преобразовать в bool, при этом ноль преобразуется в ложь, а единица – в истину.

Теперь внутри этого цикла напишем вложенный цикл с параметром x, принимающим значения элементов списка s. В нём будем выводить в файл, соответствующий переменной f_out, значение параметра x, преобразованного в строку, состоящую из него самого и пробела. После этого цикла, для того, чтобы разделить строки матрицы, выведем в этот же файл символ перехода на следующую строку. Этот символ обозначается знаком «\n». Мы завершили основной цикл обработки матрицы. Закроем входной и выходной файлы, вызвав у переменных f_in и f_out метод close без параметров, после чего с помощью инструкции print выведем на экран сообщение о том, что работа программы успешно завершена.

print ('Введите имя файла-источника.')

while True:

    try:

        f_in = open (input (), 'r')

        break

    except FileNotFoundError:

        print ('Заданный файл не найден. Укажите другой файл.')

f_out = open ('output.txt', 'w')

for line in f_in:

    s = line.split ()

    s = [int (x) for x in s]

    s = sorted (s[1:], reverse = not s[0])

    for x in s:

        f_out.write ('{:d} '.format (x))

    f_out.write ('\n')

f_in.close ()

f_out.close ()

print ('Работа программы успешно завершена.')

Описание программы завершено. Сохраним её в каталоге по умолчанию. Теперь создадим файл с данными, чтобы протестировать её. Для этого объявим файловую переменную f и откроем в ней для записи файл input.txt из каталога по умолчанию. Загрузим из модуля random функцию randint. Создадим матрицу a из 5 строк и 7 столбцов, заполненную случайными числами от 10 до 99. Теперь напишем цикл с параметром row, в котором будем перебирать строки матрицы a. Внутри цикла будем выводить в файл f случайное число на промежутке от 0 до 1, преобразованное в строку. Дальше запишем вложенный цикл с параметром x, который будет принимать значения элементов списка row. В цикле будем выводить в файл f значение параметра x, преобразованное в символьную строку, состоящую из пробела и самого числа. После вложенного цикла, чтобы разделить строки матрицы в файле, будем выводить в него символ перехода на следующую строку. При выполнении цикла на экран были выведены цифры – количества символов, выводимых в файл при каждом использовании метода write. Они нам не интересны. После того, как мы вывели матрицу в файл, закроем его. Теперь просмотрим его прямо в среде разработки. Как видим, во всех строках элементы матрицы, начиная со второго, расположены вразнобой. С единицы начинаются первая, вторая и пятая строки. То есть в выходном файле элементы в этих строках должны быть отсортированы по неубыванию, остальные же строки должны быть отсортированы по невозрастанию.

Закроем файл и запустим описанную нами программу на выполнение. Введём в качестве имени файла произвольную символьную строку. Программа вывела сообщение о том, что такого файла не найдено и запрос на повторный ввод имени файла. Зададим имя файла input.txt. Было выведено сообщение о том, что работа программы успешно завершена. Откроем выходной файл. В нём действительно первая, вторая и пятая строки отсортированы по неубыванию, а остальные – по невозрастанию. Программа работает правильно, задача решена.

Мы узнали:

·     C точки зрения программиста, файлы делятся на текстовые и двоичные.

·     В языке Python обработку файлов можно разделить на 3 этапа: открытие файла, выполнение ввода/вывода информации и закрытие файла.

·     Файл в программе на языке Python может быть открыт для чтения, для записи или для добавления данных.

0
2032

Комментарии 0

Чтобы добавить комментарий зарегистрируйтесь или на сайт

Вы смотрели