#!/usr/bin/env python # coding: utf-8 # ## Practice - read last line from external file # Python Workbook, chp5 # August 7, 2020 (past several days, internet lookup has better solutions) # ### 0. Check python version, active conda env # In[1]: get_ipython().system('python --version') # In[2]: get_ipython().system('conda env list') # * is next to active conda env. # ### 1. Start practice # In[3]: f = open('demofile.txt', 'rt') blob = f.read() # read all print(blob) # In[4]: print(f.closed) # check if f is closed at this point. # In[5]: f = open('demofile.txt') # Open again to go back to file start point. line = f.readline() # read first line, no S print(line) # In[6]: f = open('demofile.txt') lines = f.readlines() # read all lines, iterable list. With S print(lines[-1]) # print last line f.close() # ### 2. Binary format reads 'rb' # In[7]: # Try binary format reading. with open('demofile.txt', 'rb') as f: # binary format first = f.readline() f.seek(-5, 2) # Go to pointer 5th bytes from end of file #last = f.read() # does readline work? May not read all of the last line. last = f.readline() # readline does work. Still not all of the line. print(first, last) # In[8]: # Seek from end of file needs a loop. with open('demofile.txt', 'rb') as f: # binary format first = f.readline() f.seek(-2, 2) # Go to pointer 2 bytes relative to end while f.read(1) != b"\n": # while read one byte is not equal to binary '\n' f.seek(-2, 1) # go back 1 byte. # after while loop, this is beginning of last line last = f.read() # read all bytes from here. # last = f.readline() gives same output. print(str(first)+"\n", str(last)) # ### 3. Good for short files, readlines() all at once, save, index [ ] into each line # In[9]: # Good for short text files. with open('demofile.txt', 'rt') as f: lines = f.readlines() first = lines[0] last = lines[-1] print(first, last) print(f.closed) # check file is cloased after "with" block end. # ### 4. seek(0) to go back to start, works with 'rt' # In[10]: f2 = open('demofile.txt') lines = f2.readlines() print("lines: ", lines) f2.seek(0) # Goto beginning of file blob= f2.read() print("blob: ", blob) f2.seek(0) one = f2.readlines(1) print("one: ", one) f2.seek(0) two = f2.readlines()[1] # Works! prints 2nd item. nifty. print("two: ", two) # ### 5. Only binary read 'rb' can use relative indexing # In[11]: # seek can be used with text format? # Yes, but can't do relative location other than 0, current point. # If the file is opened in text mode (without ‘b’), only offsets returned by tell() are legal. # none of the relative indexing from back/current location works without 'b' binary format. with open('demofile.txt', 'rb') as f: # need to be in binary format first = f.readline() print(first) f.seek(0, 0) last = f.readlines()[2] print(last) #f.seek(-2, 2) # not work, only 0 offset works with 2, 1 mode. f.seek(0, 2) # end of file work with text format file. print(f.tell()) f.seek(-11, 1) print(f.tell()) last = f.read() print(last) # In[12]: with open('demofile.txt') as f: # text format again f.seek(0, 2) # end of file loc = f.tell(); print(loc) f.seek(0, 0) # go back to beginning of tile print(f.tell()) first = f.readline() print(first, f.tell()) last = f.readlines()[-1] print(last, f.tell()) f.seek(31, 0) two = f.readlines() print(two, f.tell()) f.seek(31, 0) second = f.readline() print(second, f.tell()) third = f.readline() print(third) # ### 6. Doen't solve large file last line problem, but another way to move around 'rt' format. # In[14]: with open('demofile.txt') as f: # text format again # num_ln = len(f.readlines()); print(num_ln) num_ch_all = len(f.read()) print(num_ch_all) f.seek(0) # back to beginning num_ch_last = len(f.readlines()[-1]); print(num_ch_last) offset = num_ch_all - num_ch_last # offset from file beginning f.seek(offset, 0) print(f.tell()) print(f.read()) # In[ ]: