1

Using this Python code I get printed lines of file in UPPERCASE but file remains unchanged (lowercase.)

def open_f():
    while True:
        fname=raw_input("Enter filename:")
        if fname != "done":
            try:
                fhand=open(fname, "r+")
                break
            except:
                print "WRONG!!!"
                continue

        else: exit()
    return fhand

fhand=open_f()
for line in fhand:
    ss=line.upper().strip()
    print ss
    fhand.write(ss)
fhand.close()

Can you suggest please why files remain unaffected?

7
  • 1
    You are trying to read and write to the same file. This isn't going to work. Write to a second file and then replace the first. Commented Jan 13, 2016 at 15:42
  • 1
    @pcarter 'r+' opens the file for both reading and writing. Commented Jan 13, 2016 at 15:44
  • @heinst Yes I saw that, but he's reading a line from the file and trying to write it back to the same file. Where is it going to write it back to? Changing text files in place is very difficult. It's much simpler to read from the original file, write to a temp file and then replace the original file with the temp one. Commented Jan 13, 2016 at 15:47
  • Yes but you are telling him it can't work, when it can. Its just not the right way of going about what hes trying to do. Commented Jan 13, 2016 at 15:51
  • @DmitriiGangan: you'll have to learn about tell() and seek() Commented Jan 13, 2016 at 15:57

4 Answers 4

3

Code:

def file_reader(read_from_file):
    with open(read_from_file, 'r') as f:
        return f.read()

def file_writer(read_from_file, write_to_file):
    with open(write_to_file, 'w') as f:
        f.write(file_reader(read_from_file))

Usage:

  1. Create a file named example.txt with the following content:

Hi my name is
Dmitrii
Gangan.

  1. Create an empty file called file_to_be_written_to.txt

  2. Add this as the last line file_writer("example.txt", "file_to_be_written_to.txt") of your .py python file.

  3. python <your_python_script.py> from the terminal.

NOTE: They all must be in the same folder.

Result:

file_to_be_written_to.txt:

Hi my name is
Dmitrii
Gangan.

Sign up to request clarification or add additional context in comments.

3 Comments

Instead of using list(f) + f.write(''.join(...)), you can use f.read() + f.write(...) (faster, uses less memory, fewer code to write)
@AndreaCorbellini So I replaced list(f) with f.read() but I am not understanding how I would replace my line using the join method as I cannot simply do f.write() since f cannot refer to the file to be written and the file to be read from.
Ah, nevermind. I got it. I am going to edit my answer right now. So, +1 thanks.
0

This program should do as you requested and allows for modifying the file as it is being read. Each line is read, converted to uppercase, and then written back to the source file. Since it runs on a line-by-line basis, the most extra memory it should need would be related to the length of the longest line.

Example 1

def main():
    with get_file('Enter filename: ') as file:
        while True:
            position = file.tell()              # remember beginning of line
            line = file.readline()              # get the next available line
            if not line:                        # check if at end of the file
                break                           # program is finished at EOF
            file.seek(position)                 # go back to the line's start
            file.write(line.upper())            # write the line in uppercase


def get_file(prompt):
    while True:
        try:                                    # run and catch any error
            return open(input(prompt), 'r+t')   # r+t = read, write, text
        except EOFError:                        # see if user if finished
            raise SystemExit()                  # exit the program if so
        except OSError as error:                # check for file problems
            print(error)                        # report operation errors

if __name__ == '__main__':
    main()

The following is similar to what you see up above but works in binary mode instead of text mode. Instead of operating on lines, it processes the file in chunks based on the given BUFFER_SIZE and can operate more efficiently. The code under the main loop may replace the code in the loop if you wish for the program to check that it is operating correctly. The assert statements check some assumptions.

Example 2

BUFFER_SIZE = 1 << 20


def main():
    with get_file('Enter filename: ') as file:
        while True:
            position = file.tell()
            buffer = file.read(BUFFER_SIZE)
            if not buffer:
                return
            file.seek(position)
            file.write(buffer.upper())
        # The following code will not run but can replace the code in the loop.
        start = file.tell()
        buffer = file.read(BUFFER_SIZE)
        if not buffer:
            return
        stop = file.tell()
        assert file.seek(start) == start
        assert file.write(buffer.upper()) == len(buffer)
        assert file.tell() == stop


def get_file(prompt):
    while True:
        try:
            return open(input(prompt), 'r+b')
        except EOFError:
            raise SystemExit()
        except OSError as error:
            print(error)

if __name__ == '__main__':
    main()

4 Comments

Thank you very much. This is exactly what I was looking for. If it's not trouble to you could you, please, explain: position = file.tell() ... file.seek(position) As I've seen file.tell() allways return the same value (in each iteration). So what is the purpose of .tell() and .seek() Thank you
Comments have been added to the program to help explain what it is doing. If you found this answer satisfied your question, please consider marking it as accepted. Thanks for asking something interesting!
Thank you. The only issue I've faced is:that i need to save file pointer position2=file.tell() after file.readline() and at the end of the loop return pointer to that position file.seek(position2). LINK TO CODE. Otherwise I get "infinite loop". Could you please explain why it happens? Because file pointer position after file.write() is exactly the same as file.readline()? I use Python 2.7 Could
@DmitriiGangan That is really weird. Since you write what you read, you should not have to move to the end of what was just written. My guess is that it has something to do with the encoding of your file or what characters are being used to move to the next line. If the file does not use multibyte characters, it might be better to convert its contents while in binary mode.
0

I suggest the following approach:

1) Read/close the file, return the filename and content

2) Create a new file with above filename, and content with UPPERCASE

def open_f():
    while True:
        fname=raw_input("Enter filename:")
        if fname != "done":
            try:
                with open(fname, "r+") as fhand:
                    ss = fhand.read()
                break
            except:
                print "WRONG!!!"
                continue

        else: exit()
    return fname, ss

fname, ss =open_f()
with open(fname, "w+") as fhand:
    fhand.write(ss.upper())

Comments

0

Like already alluded to in comments, you cannot successively read from and write to the same file -- the first write will truncate the file, so you cannot read anything more from the handle at that point.

Fortunately, the fileinput module offers a convenient inplace mode which works exactly like you want.

import fileinput
for line in fileinput.input(somefilename, inplace=True):
    print(line.upper().strip())

1 Comment

I didn't try to copy the unattractive interactive prompting - IMHO it should not be part of the opening function; but an altogether better design would be to have your script get the file name as a command-line argument. That way, you can benefit frnom the shell's history, filename completion, wildcarding etc functionality without extending your script at all.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.