I have this homework which I need to define a function that does the following:
Write a function which given a text file object open in read and write mode and a string, inserts the text of the string in the file at the current read/write position. In other words, the function writes the string in the file without overwriting the rest of it. When exiting the function, the new read/write position has to be exactly at the end of the newly inserted string.
The algorithm is simple; the function needs to:
read the content of the file starting at the current read/write position
write the given string at the same position step 1 started
write the content read at step 1. at the position where step 2. ended
reposition the read/write cursor at the same position step2. ended (and step 3. started).
I'm very confused by the steps 1-4 as to what I need do to, and the professor has been no help.
here is the code that I did, but I don't think the function follows the parameter given
def readWrite(file, string):
file.read()
file.seek(0)
file.write(string)
give_file = input("enter a file name: ")
give_string = input("enter a string: ")
try:
readFile = open(give_file, "a+")
file_content = readWrite(readFile, give_string)
except FileNotFoundError:
print("File does not exist")
exit(1)
The whole code should ask for a simple .txt file, which it would take it and a string, and add it to the original file.
example:
the file is Twinkle.txt
Twinkle, twinkle, little bat!
How I wonder what you're at!
Up above the world you fly,
Like a teatray in the sky.
output:
twinkle.txt
1 Twinkle, twinkle, little bat!
2 How I wonder what you're at!
3 Up above the world you fly,
4 Like a teatray in the sky.
I have found the way to do it and here is the function:
def readWrite(file, string):
if not file.readable():
print("This file is not readable")
file.close()
return
if not file.writable():
print("This file is not writable")
file.close()
return
initialPosition = file.tell()
print(initialPosition)
readContent = file.read()
file.seek(initialPosition)
file.write(string)
secondPosition = file.tell()
print(secondPosition)
file.write(readContent)
file.seek(secondPosition)
basically, this takes in the file and appends to it the file name and line numbering to each row. (the code for line numbering is in the main body below).
main body:
give_file = input("enter a file name: ")
try:
openFile = open(give_file, "r+")
position = openFile.tell()
except FileNotFoundError:
print(give_file, " does not exist or could not open")
exit(1)
counter = 0
for line in openFile:
counter += 1
openFile.seek(position)
readWrite(openFile, give_file + "\n" + "\n")
spacing = 1
while spacing <= counter:
readWrite(openFile, str(spacing) + " ")
openFile.readline()
spacing += 1
openFile.close()
there might be shorter more elegant solutions out there, but this one works for me
I don't think I know the full answer, but I know it involves dealing with file streams. Look up the python docs for the TextIO object for that. file.write(content) in save_file deletes the existing content of the file in my experience. I believe you want to open the file in append mode at the bottom, for which the string parameter in open is 'a'
this link might help: https://www.guru99.com/reading-and-writing-files-in-python.html
Related
I am trying to create a memory set, saved in a separate text file stored in a different location. I have tried to use some of the suggestions on this site, but maybe my code is different. I am using Python 3.6.
Here is my code:
df = open("Memory.txt", 'r')
askforfname = df.readlines()
df.close()
print (askforfname)
if '\n' in open("Memory.txt", 'r').readlines():
df.close()
name = input("What is your name?: \n")
Bigname = name.title()
df = open("Memory.txt", 'w')
df.write(Bigname)
df.close()
else:
df = open("Memory.txt", 'r')
returning_name = df.readlines()
print("Welcome back" + str(returning_name))
df.close()
I am using print(askforfname) in the fourth line just to make sure the data is being read from the proper line, and it is. But it just skips over the if command, as if it came out false, and continues right the the else command, even if the line is blank. I am just a beginner in programming, and don't know much, so i don't know if I'm just making a simple mistake lol. And yes, I understand my code must be inefficient, but since I am new, this is just me experimenting with code.
Let names.txt be a simple .txt file with a few names in it:
ken
dennis
guido
bjarne
Say you're Bjarne and want to check whether your name is in the file. Probably the most efficient approach would be not to read the file into memory at all, but rather lazily get its contents. Apart from that, you would be better off using with context manager, instead of manually managing closing your file objects like that:
myself = 'Bjarne'
with open('names.txt', 'r') as f:
for line in f:
if myself.lower() in line:
print('Here am I!')
else:
print('No, this is not me')
Your Memory.txt file is an empty file and the result of if condition will be False. You need to have at least a blank line in your file for if condition to return True.
Yes, inefficient, but also harder to read and understand with repeated opening and line reading. Please to not post such code.
.readlines produces a list of strings representing lines, terminated by \n if the line in the file is so terminated. Your test is correct, if obscured.
>>> '\n' in ['']
False
>>> '\n' in ['a']
False
>>> '\n' in ['a\n']
False
>>> '\n' in ['\n']
True
It must be that your file does not contain a blank line ending with a newline.
First, there must be something in Memory.txt.
'\n' indicates a blank line in the file.
There is already a very clear example, I'm giving you some tips:
If the file is large, you can read multiple times, limiting the
size of the file each time it is read to ensure it does not take up
too much memory:
name = Jack
with open('Memory.txt', 'r') as f:
while True:
content = f.read(2048)
if content == '':
break
else:
if name.lower() in content:
print('name is here')
else:
print('name is not here')
If this file is small, the memory can hold the contents of the file, you can use readlines() and read().
def is_number(file):
cList = file.read()
chars=len(cList)
t = 0
retlist=[]
while t<chars:
try:
int(cList[t])
int(cList[t + 1])
x = (cList[t] + cList[t + 1])
retlist.append(int(x))
t+=1
except ValueError:
try:
x = int(cList[t])
retlist.append(x)
except ValueError:
pass
t+=1
retlist.sort()
return retlist
Ok so this is my code that reads a file and takes all the numbers up to 99 and adds them to a list. But when i return it the list it's suddenly empty for some reason, can't figure out why please help!
def main():
while True:
try:
f = input("Enter the name of the file: ")
file = open(f + ".txt", "r")
is_number(file)
break
except IOError:
pass
print("The file %s could not be found, try again!" % (f))
numList = is_number(file)
print(numList)
main()
The code that calls the function.
Python (and most other languages) have the notion of a "file pointer" -- it's a reference to some location in the file. All reading and writing starts at the file pointer. For example, if the file pointer is at the beginning of the file, calling read() will read the entire file. If the file pointer were moved, say, 100 characters forward, calling read() would skip those first 100 characters.
Reading will always advance the file pointer to immediately after the point it stopped reading. So, for example, if you asked it to read only 100 bytes, the file pointer will advance 100 bytes and the next read would read from there.
In your code, is_number accepts a file handle and immediately reads the entire contents of the file. When it does this, the file pointer is moved to the end of the file. After your loop exits, you call is_number again on the last file that was opened. Since the file pointer is at the end of the file and hasn't been moved, there's nothing to read so numList is set to the empty string.
Just to add to Bryan's answer, you can use the seek() method of files to restart reading from the beginning. For example, if f is the name of your file handle, f.seek(0) will point to the beginning of the file.
I want to replace a string in a file created by my program, But I cant use .replace because It's not in 3.3, How do I replace a line from a file using two inputs(the previous string, replacement), Here Is the code so far:
#Data Creator
def Create(filename):
global UserFile
UserFile = open(str(filename), "w")
global file
file = (filename)
UserFile.close()
#Data Adder
def Add(data):
UserFile = open(file, "a")
UserFile.write(str(data))
UserFile.close()
#Data seeker
def Seek(target):
UserFile = open(file, "r")
UserFile.seek(target)
global postition
position = UserFile.tell(target)
UserFile.close()
return position
#Replace
def Replace(take,put):
UserFile = open(file, "r+")
UserFile.replace(take,put)
UserFile.close
Create("richardlovesdogs.txt")
Add("Richard loves all kinds of dogs including: \nbeagles")
Replace("beagles","pugs")
How do I do this, So that It replaces the word "beagles" with "pugs"?
I'm learning python so any help would be appreciated
Edit :
ive changed the replace code to this
#Replace
def Replace(take,put):
UserFile = open(file, 'r+')
UserFileT = open(file, 'r+')
for line in UserFile:
UserFileT.write(line.replace(take,put))
UserFile.close()
UserFileT.close()
but in the file it outputs:
Richard loves all kinds of dogs including:
pugsles
how do i change it so it outputs only "pugs" not "pugsles"
The first idea which came to my mind is to loop over lines and check if the given line contains the word which you want to replace. Then just use string method - replace. Of course, in the end the result should be put/written to the file.
Perhaps what you were thinking of was the sed command in Unix shell, which will let you replace a specific text in a file with a replacement text from the shell itself.
As others have said, replacing text in Python has always been str.replace().
Hope this helps!
The fastest way to do this, without loading the whole file into memory, is using the file seek, tell and flush. Set your starting pointer to position 0, and increment through the file by len(replacement_word). If the few-byte snippet matches then you set a marker where you are within the file.
After you've scanned the file, you rebuild the file using your markers and joining the segments with your replacement string between them.
This question already has answers here:
Python error message io.UnsupportedOperation: not readable
(5 answers)
Closed 6 months ago.
I am working on a problem that says to make a program that gets a user input for a file and then within the file removes a string that the user specifies. I'm not sure how to go from what I have(below) to what the question asks for. As always any and all help is greatly appreciated.
def main():
outfile = open(input("Enter a file name: "), "a")
string = input("Enter the string to be removed: ")
for string in outfile.readlines():
string = string.replace(string, "")
outfile.close()
print("Done")
main()
I took one of the suggestions and tried to get it to work but as I said in my comment below the code below does not return an error it creates an empty file. What am I missing to get the new file to be the old file with the string removed?
def main():
inpath = input("Enter an input file: ")
line = input("Enter what you want to remove: ")
outpath = input("Enter an output file: ")
with open(inpath, "r") as infile, open(outpath, "w") as outfile:
for line in infile:
outfile.write(line.replace(line, "") + "\n")
print("Done.")
main()
A few side notes before getting into the details: When you call string.replace(string, ""), you're telling the string to replace its entire self with the empty string—you might as well just do string = "". Presumably the first string is the search string to replace, so give it a different name, and then use it as, e.g., string.replace(searchString, ""). Also, you don't want to name a variable string, because it's the name of a standard library module. You're calling your input file "outfile", which is apt to be confusing. You probably want to use a with statement instead of an explicit close. Finally, you can iterate the lines in a file with just for line in f:; you don't need for line in f.readlines() (and, if you ever need to deal with Python 2.x, you'll be much happier avoiding readlines(), because it will read the entire file into memory, and then make a huge list of lines in memory).
The first problem, as JBernardo pointed out, is that you've opened the file in "a" mode, which means "write-only, appending to the end". You can use "a+" or "r+" if you want to read and write.
However, that won't really help you. After all, you can't write to the file in the middle of reading it.
There are a few common ways around this.
First, just write to standard output, and let the user do whatever he wants with the results—e.g., redirect it to a file. (In that case, you have print your prompt, "Done" message, etc. to standard error instead, so they don't get redirected to the file.) This is what many Unix tools like sed or sort do, so it's appropriate if you're building a Unix-style tool, but may not be right for other purposes.
def stderrinput(prompt):
sys.stderr.write(prompt)
sys.stderr.flush()
return input()
def main():
with open(stderrinput("Enter a file name: "), "r") as infile:
searchString = stderrinput("Enter the string to be removed: ")
for line in infile:
print(infile.replace(searchString, ""))
sys.stderr.write("Done\n")
Second, write to another file. Open the input file in "r" mode, and the output file in "w", mode, and then you're just copying lines:
def main():
inpath = input("Enter an input file: ")
outpath = input("Enter an output file: ")
with open(inpath, "r") as infile, open("outpath", "w") as outfile:
for line in infile:
outfile.write(line.replace(searchString, "") + "\n")
Third, read and process the whole file in memory, then truncate and rewrite the whole file:
def main():
path = input("Enter an input/output file: ")
with open(path, "r+") as inoutfile:
lines = [line.replace(searchString, "") for line in inoutfile]
inoutfile.seek(0)
inoutfile.truncate()
inoutfile.writelines(lines)
Finally, write to a temporary file (as with the second option), then move that temporary file on top of the original input file. Something like this:
def main():
path = input("Enter an input/output file: ")
with open(path, "r") as infile, tempfile.NamedTemporaryFile("w", delete=False) as outfile:
for line in infile:
outfile.write(line.replace(searchString, ""))
shutil.move(outfile.name, pathname)
This last one is a little tricky, because of the differences between POSIX and Windows. However, it has some big advantages. (For example, if your program gets killed in the middle of operation, no matter how it happens, you're guaranteed to have either the original file or the new file, not some half-written mess.)
So I have a program which runs. This is part of the code:
FileName = 'Numberdata.dat'
NumberFile = open(FileName, 'r')
for Line in NumberFile:
if Line == '4':
print('1')
else:
print('9')
NumberFile.close()
A pretty pointless thing to do, yes, but I'm just doing it to enhance my understanding. However, this code doesn't work. The file remains as it is and the 4's are not replaced by 1's and everything else isn't replaced by 9's, they merely stay the same. Where am I going wrong?
Numberdata.dat is "444666444666444888111000444"
It is now:
FileName = 'Binarydata.dat'
BinaryFile = open(FileName, 'w')
for character in BinaryFile:
if charcter == '0':
NumberFile.write('')
else:
NumberFile.write('#')
BinaryFile.close()
You need to build up a string and write it to the file.
FileName = 'Numberdata.dat'
NumberFileHandle = open(FileName, 'r')
newFileString = ""
for Line in NumberFileHandle:
for char in line: # this will work for any number of lines.
if char == '4':
newFileString += "1"
elif char == '\n':
newFileString += char
else:
newFileString += "9"
NumberFileHandle.close()
NumberFileHandle = open(FileName, 'w')
NumberFileHandle.write(newFileString)
NumberFileHandle.close()
First, Line will never equal 4 because each line read from the file includes the newline character at the end. Try if Line.strip() == '4'. This will remove all white space from the beginning and end of the line.
Edit: I just saw your edit... naturally, if you have all your numbers on one line, the line will never equal 4. You probably want to read the file a character at a time, not a line at a time.
Second, you're not writing to any file, so naturally the file won't be getting changed. You will run into difficulty changing a file as you read it (since you have to figure out how to back up to the same place you just read from), so the usual practice is to read from one file and write to a different one.
Because you need to write to the file as well.
with open(FileName, 'w') as f:
f.write(...)
Right now you are just reading and manipulating the data, but you're not writing them back.
At the end you'll need to reopen your file in write mode and write to it.
If you're looking for references, take a look at theopen() documentation and at the Reading and Writing Files section of the Python Tutorial.
Edit: You shouldn't read and write at the same time from the same file. You could either, write to a temp file and at the end call shutil.move(), or load and manipulate your data and then re-open your original file in write mode and write them back.
You are not sending any output to the data, you are simply printing 1 and 9 to stdout which is usually the terminal or interpreter.
If you want to write to the file you have to use open again with w.
eg.
out = open(FileName, 'w')
you can also use
print >>out, '1'
Then you can call out.write('1') for example.
Also it is a better idea to read the file first if you want to overwrite and write after.
According to your comment:
Numberdata is just a load of numbers all one line. Maybe that's where I'm going wrong? It is "444666444666444888111000444"
I can tell you that the for cycle, iterate over lines and not over chars. There is a logic error.
Moreover, you have to write the file, as Rik Poggi said (just rember to open it in write mode)
A few things:
The r flag to open indicates read-only mode. This obviously won't let you write to the file.
print() outputs things to the screen. What you really want to do is output to the file. Have you read the Python File I/O tutorial?
for line in file_handle: loops through files one line at a time. Thus, if line == '4' will only be true if the line consists of a single character, 4, all on its own.
If you want to loop over characters in a string, then do something like for character in line:.
Modifying bits of a file "in place" is a bit harder than you think.
This is because if you insert data into the middle of a file, the rest of the data has to shuffle over to make room - this is really slow because everything after your insertion has to be rewritten.
In theory, a one-byte for one-byte replacement can be done fast, but in general people don't want to replace byte-for-byte, so this is an advanced feature. (See seek().) The usual approach is to just write out a whole new file.
Because print doesn't write to your file.
You have to open the file and read it, modify the string you obtain creating a new string, open again the file and write it again.
FileName = 'Numberdata.dat'
NumberFile = open(FileName, 'r')
data = NumberFile.read()
NumberFile.close()
dl = data.split('\n')
for i in range(len(dl)):
if dl[i] =='4':
dl[i] = '1'
else:
dl[i] = '9'
NumberFile = open(FileName, 'w')
NumberFile.write('\n'.join(dl))
NumberFile.close()
Try in this way. There are for sure different methods but this seems to be the most "linear" to me =)