Copying lines into python - python

I am trying to write a program that copies every other line from thisFile.txt into thatFile.txt, but right now, I'm just having trouble getting the lines from thisFile.txt to copy into thatFile.txt.
I have two different methods that I'm trying to use to copy, one that is commented out and the other that's in a for loop before the commented section.
file_one=open('thisFile.txt','w+')
file_two=open('thatFile.txt','w+')
file_one.write('Hello\nHow\nAre\nYou')
for line in file_one:
file_two.write(line)
#line=' '
#while line !='':
# line=file_one.readline()
# file_two.write(line)
file_one.close()
file_two.close()

You've opened both files for reading and writing, but after writing to the first file are expecting to read from that file immediately. The file pointer is at the end of the file. If you .seek(0) back to the beginning of the file it will work:
file_one=open('thisFile.txt','w+')
file_two=open('thatFile.txt','w+')
file_one.write('Hello\nHow\nAre\nYou')
# rewind the file to prep for read.
file_one.seek(0)
for line in file_one:
file_two.write(line)
file_one.close()
file_two.close()

To address the first question (copying all lines). You need to open the file you want in mode='r' then write to the next file which is open with mode='w' (or simply 'r' and 'w').
with open('test.txt', 'r') as f1:
lines = f1.readlines()
with open('test2.txt', 'w') as f2:
for line in lines:
f2.write(line)
For the first file you take readlines() to actually read every single line.
To address the second issue (every other line):
with open('test.txt', 'r') as f1:
lines = f1.readlines()
with open('test2.txt', 'w') as f2:
for i,line in enumerate(lines):
if i % 2 == 0:
f2.write(line)
else:
pass
You just need to implement enumerate() to loop through the list and provide only the lines whose keys are even. You can change to odd of course.

Related

Can you delete all the lines of a .txt file after a specific line?

I am trying to delete all the lines in a text file after a line that contains a specific string. What I am trying to do is find the number of the line in said file and rewrite the whole text up until that line.
The code that I'm trying is the following:
import itertools as it
with open('sampletext.txt', "r") as rf:
for num, line in enumerate(rf, 1): #Finds the number of the line in which a specific string is contained
if 'string' in line:
print(num)
with open('sampletext_copy.txt', "w") as wf:
for line in it.islice(rf, 0, num):
wf.write(line)
Also would appreciate any tips on how to do this. Thank you!
You could do it like this:
with open('sampletext.txt', "r") as rf, open('sampletext_copy.txt', "w") as wf:
for line in rf:
if 'string' in line:
break
wf.write(line)
Basically, you open both files at the same time, then read the input file line-by-line. If string is in the line, then you're done - otherwise, write it to the output file.
In case if you want to apply changes to original file, it's possible to do using .truncate() method of file object:
with open(r"sampletext.txt", "r+") as f:
while line := f.readline():
if line.rstrip() == "string": # line.startswith("string")
f.truncate(f.tell()) # removes all content after current position
break
Here we iterating over file until reach this specific line and resize stream to size of bytes we've already read (to get it we use .tell()).
Just to complement Donut's answer, if you want to modify the file in place, there's a much more efficient solution:
with open('sampletext.txt', "r+") as f:
for line in iter(f.readline, ''): # Can't use for line in f: because it disables
# tell for txt
# Or for walrus lovers:
# while line := f.readline():
if 'string' in line:
f.seek(0, 1) # Needed to ensure underlying handle matches logical read
# position; f.seek(f.tell()) is logically equivalent
f.truncate()
break
If issue #26158 is ever fixed (so calling truncate on a file actually truncates at the logical position, not the arbitrary position of the underlying raw handle that's likely advanced a great deal due to buffering), this simpler code would work:
with open('sampletext.txt', "r+") as f:
for line in f:
if 'string' in line:
f.truncate()
break

copy a text file data to other one without first line

I need to copy a text file data which is like a table to the other one.
I want to copy to the other text file without the first line.Those data are spaced with space and look exactly like the following in excel.
https://i.imgur.com/YQXgTwu.png
I tried 2 method
first one is copy the whole thing in then find and remove that line which failed to write.
with open('path1') as fin, open('path2', 'w') as fout:
a=fin.read()
fout.write(a)
second one is using deque, trying to follow the example to copy just the last 3 line first, then figure out to copy more line later.
collections import deque
with open('path1') as fin, open('path2', 'w') as fout:
fout.writelines(deque(fin, 3))
Both of them make the text file at path2 get erased and become blank.
You can do it this way-
with open('path1', 'r') as reader, open('path2', 'w') as writer:
reader.readline() # read the first line and discard it
rem_lines = reader.readlines() # read all the remaining lines
writer.writelines(rem_lines) # write all the remaining lines to the second file
for big files, as reading the entire file in the memory might not be feasible, read the first file line by line and write to the second file.
with open('path1', 'r') as reader, open('path2', 'w') as writer:
reader.readline() # read the first line and discard it
for line in reader:
writer.write(line)
File objects are iterators, providing one line per iteration.
Therefore:
with open('path1') as fin, open('path2', 'w') as fout:
next (fin)
for line in fin:
fout.write(line)
i.e. simply skip the line by advancing one iteration
You need to read all lines of file1. You will get list of lines in file1.
with open("file1.txt", "r") as file:
file1Contents = file.readlines()
After that, you can append file1 without the first line into file2.
with open("file2.txt", "a") as file:
file.writelines(file1Contents[1:]) # remove the first line of file1
This will be done. Hope this helps.

Python: Why won't my loop iterate?

I have a simple bit of python code that opens two files, and loops through each string in one file, looking for the matching string (or part of it) in the other file. If it finds it, it should write that line to file. For some reason it isn't iterating through. Here is my code:
out = open("outputfile.txt", "w")
with open("inputfile1.txt", "r") as f:
with open("inputfle2.txt", "r") as map:
for line in f:
for mline in map:
if line[0:6] in mline:
out.write(line)
For some reason the resultant output file only contains one line. I have checked the line and it is correct, so the code is doing what I want but the loop is not iterating through both files for some reason. I know there's an obvious solution to this but hours of searching and fiddling with my code haven't yielded any results.
By the time that line gets to the second line of file f, mline already read through all the lines of map and exhausted the generator.
You need to cache map's content:
out = open("outputfile.txt", "w")
with open("inputfle2.txt", "r") as map:
map_lines = map.readlines()
with open("inputfile1.txt", "r") as f:
for line in f:
for mline in map_lines:
if line[0:6] in mline:
out.write(line)

Python: Open a file, search then append, if not exist

I am trying to append a string to a file, if the string doesn't exit in the file. However, opening a file with a+ option doesn't allow me to do at once, because opening the file with a+ will put the pointer to the end of the file, meaning that my search will always fail. Is there any good way to do this other than opening the file to read first, close and open again to append?
In code, apparently, below doesn't work.
file = open("fileName", "a+")
I need to do following to achieve it.
file = open("fileName", "r")
... check if a string exist in the file
file.close()
... if the string doesn't exist in the file
file = open("fileName", "a")
file.write("a string")
file.close()
To leave the input file unchanged if needle is on any line or to append the needle at the end of the file if it is missing:
with open("filename", "r+") as file:
for line in file:
if needle in line:
break
else: # not found, we are at the eof
file.write(needle) # append missing data
I've tested it and it works on both Python 2 (stdio-based I/O) and Python 3 (POSIX read/write-based I/O).
The code uses obscure else after a loop Python syntax. See Why does python use 'else' after for and while loops?
You can set the current position of the file object using file.seek(). To jump to the beginning of a file, use
f.seek(0, os.SEEK_SET)
To jump to a file's end, use
f.seek(0, os.SEEK_END)
In your case, to check if a file contains something, and then maybe append append to the file, I'd do something like this:
import os
with open("file.txt", "r+") as f:
line_found = any("foo" in line for line in f)
if not line_found:
f.seek(0, os.SEEK_END)
f.write("yay, a new line!\n")
There is a minor bug in the previous answers: often, the last line in a text file is missing an ending newline. If you do not take that that into account and blindly append some text, your text will be appended to the last line.
For safety:
needle = "Add this line if missing"
with open("filename", "r+") as file:
ends_with_newline = True
for line in file:
ends_with_newline = line.endswith("\n")
if line.rstrip("\n\r") == needle:
break
else: # not found, we are at the eof
if not ends_with_newline:
file.write("\n")
file.write(needle + "\n") # append missing data

How to delete parts of a file in python?

I have a file named a.txt which looks like this:
I'm the first line
I'm the second line.
There may be more lines here.
I'm below an empty line.
I'm a line.
More lines here.
Now, I want to remove the contents above the empty line(including the empty line itself).
How could I do this in a Pythonic way?
Basically you can't delete stuff from the beginning of a file, so you will have to write to a new file.
I think the pythonic way looks like this:
# get a iterator over the lines in the file:
with open("input.txt", 'rt') as lines:
# while the line is not empty drop it
for line in lines:
if not line.strip():
break
# now lines is at the point after the first paragraph
# so write out everything from here
with open("output.txt", 'wt') as out:
out.writelines(lines)
Here are some simpler versions of this, without with for older Python versions:
lines = open("input.txt", 'rt')
for line in lines:
if not line.strip():
break
open("output.txt", 'wt').writelines(lines)
and a very straight forward version that simply splits the file at the empty line:
# first, read everything from the old file
text = open("input.txt", 'rt').read()
# split it at the first empty line ("\n\n")
first, rest = text.split('\n\n',1)
# make a new file and write the rest
open("output.txt", 'wt').write(rest)
Note that this can be pretty fragile, for example windows often uses \r\n as a single linebreak, so a empty line would be \r\n\r\n instead. But often you know the format of the file uses one kind of linebreaks only, so this could be fine.
Naive approach by iterating over the lines in the file one by one top to bottom:
#!/usr/bin/env python
with open("4692065.txt", 'r') as src, open("4692065.cut.txt", "w") as dest:
keep = False
for line in src:
if keep: dest.write(line)
if line.strip() == '': keep = True
The fileinput module (from the standard library) is convenient for this kind of thing. It sets things up so you can act as though your are editing the file "in-place":
import fileinput
import sys
fileobj=iter(fileinput.input(['a.txt'], inplace=True))
# iterate through the file until you find an empty line.
for line in fileobj:
if not line.strip():
break
# Iterators (like `fileobj`) pick up where they left off.
# Starting a new for-loop saves you one `if` statement and boolean variable.
for line in fileobj:
sys.stdout.write(line)
Any idea how big the file is going to be?
You could read the file into memory:
f = open('your_file', 'r')
lines = f.readlines()
which will read the file line by line and store those lines in a list (lines).
Then, close the file and reopen with 'w':
f.close()
f = open('your_file', 'w')
for line in lines:
if your_if_here:
f.write(line)
This will overwrite the current file. Then you can pick and choose which lines from the list you want to write back in. Probably not a very good idea if the file gets to large though, since the entire file has to reside in memory. But, it doesn't require that you create a second file to dump your output.
from itertools import dropwhile, islice
def content_after_emptyline(file_object):
return islice(dropwhile(lambda line: line.strip(), file_object), 1, None)
with open("filename") as f:
for line in content_after_emptyline(f):
print line,
You could do a little something like this:
with open('a.txt', 'r') as file:
lines = file.readlines()
blank_line = lines.index('\n')
lines = lines[blank_line+1:] #\n is the index of the blank line
with open('a.txt', 'w') as file:
file.write('\n'.join(lines))
and that makes the job much simpler.

Categories