I want to insert my Random()'s return value into txt file without overwrite ('a') and to a specific location, like at the sixt character, but when I execute this, Random is insert to the third line.
`def Modif_Files(p_folder_path):
Tab = []
for v_root, v_dir, v_files in os.walk(p_folder_path):
print v_files
for v_file in v_files:
file = os.path.join(p_folder_path, v_file)
#with open(file, 'r') as files:
#for lines in files.readlines():
#Tab.append([lines])
with open(file, 'a') as file:
file.write("\n add " + str(Random())) #Random = int
#file.close
def Random():
global last
last = last + 3 + last * last * last * last % 256
return last
def main ():
Modif_Files(Modif_Path, 5) # Put path with a txt file inside
if __name__ == '__main__':
main()
`
After going through few other posts, it seems it is not possible to write in the middle of beginning of a file directly without overwriting. To write in the middle you need to copy or read everything after the position where you want to insert. Then after inserting append the content you read to the file.
Source: How do I modify a text file in Python?
Okay, I found the solution ; with open(file, 'r+') as file:
r+ and it work like a charm :)
The given answer is incorrect and/or lacking significant detail. At the time of this question maybe it wasn't, but currently writing to specific positions within a file using Python IS possible. I came across this question and answer in my search for this exact issue - an update could be useful for others.
See below for a resolution.
def main():
file = open("test.txt", "rb")
filePos = 0
while True:
# Read the file character by character
char = file.read(1)
# When we find the char we want, break the loop and save the read/write head position.
# Since we're in binary, we need to decode to get it to proper format for comparison (or encode the char)
if char.decode('ascii') == "*":
filePos = file.tell()
break
# If no more characters, we're at the end of the file. Break the loop and end the program.
elif not char:
break
# Resolve open/unneeded file pointers.
file.close()
# Open the file in rb+ mode for writing without overwriting (appending).
fileWrite = open("test.txt", 'rb+')
# Move the read/write head to the location we found our char at.
fileWrite.seek(filePos - 1)
# Overwrite our char.
fileWrite.write(bytes("?", "ascii"))
# Close the file
fileWrite.close()
if __name__ == "__main__":
main()
Related
I have a binary file. Now, I am trying to write some values from a particular offset till the EOF. I wrote a method to do that but not sure how to pass the EOF as an offset. I am trying to have a method where I can pass the starting offset and the end offset. Here I want the end offset can be either an address or EOF. How to pass the EOF as an offset to my method? for example my start is 129 and end is EOF or offset like 1129?
def writeValues(start, end=0):
try:
with open("current.xof", "r+b") as f:
for i in xrange(start, end+1):#write the data
f.seek(i)
f.write("\xAA") #write data
except IOError:
print("Error file not found")
Also, while writing to the binary file, I am ending up writing the Char values instead of hex values. So to fix that I tried a solution but not satisfied with that. I feel there should be an easier way to do that.
def updateChecksum(checksum, start, end):
'''update the checksum in bytes start - end'''
checksumList= (' '.join(checksum[i: i+2] for i in xrange(0,len(checksum), 2)))
checksumArr=checksumList.split(" ")
count = start
with open("current.xof", "r+b") as f:
for i in range(0,len(checksumArr)):
f.seek(count)
count = count + 1
f.write('%c' %(int(checksumArr[i], 16)))
You could try using end == 0 as a sentinel value meaning EOF, and interpret it yourself.
def writeValues(start, end=0):
try:
with open("current.xof", "r+b") as f:
for i in xrange(start, end+1):
if i == 0:
f.seek(0, 2) # 2 means seek from EOF
else:
f.seek(i)
f.write("\xAA") #write data
except IOError:
print("Error file not found")
I am ending up writing the Char values instead of hex values.
I'm not sure what this means. '\xaa' should print the byte 0xAA
>>> print '\x21'
!
I ended up modifying the code like below and got it working. Is there any way to improve this?
def writeValues(start, end=0):
try:
with open("current.xof", "r+b") as f:
if end == 0:
f.seek(0,2)
end_position = f.tell() #get the end position of the file
print(end_position)
for i in xrange(start, end_position+1):
f.seek(i)
f.write("\x00")
except IOError:
print("Error file not found")
I am trying to run the following code:
fname = raw_input ('Enter file name:')
fh = open (fname)
count = 0
for line in fh:
if not line.startswith ('X-DSPAM-Confidence:') : continue
else:
count = count + 1
new = fh #this new = fh is supposed to be fh stripped of the non- x-dspam lines
for line in new: # this seperates the lines in new and allows `finding the floats on each line`
numpos = new.find ('0')
endpos = new.find ('5', numpos)
num = new[numpos:endpos + 1]
float (num)
# should now have a list of floats
print num
The intention of this code is to prompt the user for a file name, open the file, read through the file, compile all the lines that start with X-DSPAM, and extract the float number on these lines. I am fairly new to coding so I realise I may have committed a number of errors, but currently when I try to run it, after putting in the file name I get the return:
I looked around and I have seen that mode 'r' refers to different file modes in python in relation to how the end of the line is handled. However the code I am trying to run is similar to other code I have formulated and it does not have any non-text files inside, the file being opened is a .txt file. Is it something to do with converting a list of strings line by line to a list of float numbers?
Any ideas on what I am doing wrong would be appreciated.
The default mode of handling a file is 'r' - which means 'read', which is what you want. It means the program is going to read the file (as opposed to 'w' - write, or 'a' - append, for example - which would allow you to overwrite the file or append to it, which you don't want in this case).
There are some bugs in your code, which I've tried to indicate in the edited code below.
You don't need to assign new = fh - you're not grabbing lines and passing them to a new file. Rather, you're checking each line against the 'XDSPAM' criteria and if it's a match, you can proceed to parse out the desired numbers. If not, you ignore it and go to the next line.
With that in mind, you can move all of the code from the for line in new to be part of the original if not ... else block.
How you find the end of the number is also a bit off. You set endpos by searching for an occurence of the number 5 - but what I think you want is to find a position 5 characters from the start position (numpos + 5).
(There are other ways to parse the line and pull the number, but I'm going to stick with your logic as indicated by your code, so nothing fancy here.)
You can convert to float in the same statement where you slice the number from the line (as below). It's acceptable to do:
num = line[numpos:endpos+1]
float_num = float(num)
but not necessary. In any event, you want to assign the conversion (float(num)) to a variable - just having float(num) doesn't allow you to pass the converted value to another statement (including print).
You say that you should have 'a list of floats' - the code as corrected below - will give you a display of all the floats, but if you want an actual Python list, there are other steps involved. I don't think you wanted a Python list, but just in case:
numlist = [] # at the beginning, declare a new, empty list
...
# after converting to float, append number to list
XDSPAM.append(num)
print XDSPAMs # at end of program, to print full list
In any event, this edited code works for me with an appropriate file of test data, and outputs the desired float numbers:
fname = raw_input ('Enter file name:')
fh = open (fname)
count = 0
for line in fh:
if not line.startswith ('X-DSPAM-Confidence:') : continue
else:
# there's no need to create the 'new' variable
# any lines that meet the criteria can be processed for numbers
count = count + 1
numpos = line.find ('0')
# i think what you want here is to set an endpoint 5 positions to the right
# but your code was looking for the position of a '5' in the line
endpos = numpos + 5
# you can convert to float and slice in the same statement
num = float(line[numpos:endpos+1])
print num
I have a list of terms in a file that I want to read, modify each term and output the new terms to a new file. The new terms should look like this: take the first two characters of the original term put them in quotes, add a '=>' then the original term in quotes and a comma.
This is the code I'm using:
def newFile(newItem):
original = line
first = line[0:2]
newItem = first+'=>'+original+','
return newItem
input = open('/Users/george/Desktop/input.txt', 'r')
output = open('/Users/george/Desktop/output.txt', 'w')
collector = ''
for line in input:
if len(line) != 0:
collector = newFile(input)
output.write(''.join(collector))
if len(line) == 0:
input.close()
output.close()
For example:
If the terms in the input.txt file are these:
term 1
term 2
term 3
term 4
The output is this:
te=>term 1
,te=>term 2
,te=>term 3
,te=>term 4
,
How can I add '' to the first two letters and to the term? And why the second, third and forth terms have ,te not te like it should?
Instead of using collector and newFile() you can use new variable:
modified_line = "'%s'=>'%s'," % (line[:2], line.strip())
and in your loop try this:
...
if len(line) > 2:
output.write('%s\n' % (modified_line))
Also:
if possible do not hard code file names in your program, use sys.argv, standard input/output or config file; of course if you are sure of input/output names then use them
in line[0:2] you can ommit 0 and use line[:2]
you should use try: - open file - read file etc. finally: close file
you don't need to check if len(line) == 0, for loop do it already and you will receive line with CRLF for empty lines, but end of input file is when for loop ends
I am building an application which accepts csv data as an uploaded file.
Here is the relevent part of my view:
def climate_upload(request):
...
reader = csv.reader(file, delimiter=';') # news csv reader instance
next(reader) # skip header row
for line in reader:
if not line:
continue
report = site_name
report.year = line[1]
report.month = line[2]
...
report.save()
file.close() # close file
...
So, this works fine on data which looks like this:
;"headers"
;2012;5;2012-06-01;27.1;24.5;29.8;26.8;85;0.8
;2012;5;2012-06-02;27.1;24.5;29.8;26.8;85;0.8
But fails on this:
"headers"
2012;5;2012-06-01;27.1;24.5;29.8;26.8;85;0.8
2012;5;2012-06-02;27.1;24.5;29.8;26.8;85;0.8
Note the lack of initial delimiter on each line.
Unfortunately MS Excel seems to spit out the second version. I assume that reader is not recognizing a new line as a delimiter. Is there some flag with reader which will force it to accept \n as a delimiter as well as ; ?
Any help much appreciated.
The delimiters or newlines aren't the problem - you're counting incorrectly.
The first element of a list has the index 0. So it should be
report.year = line[0]
report.month = line[1]
# etc.
I'm guessing you're running into a List index out of range exception on the last element (line[9]).
I'm working on a simple Python game where the computer tries to guess a number you think of. Every time it guesses the right answer, it saves the answer to a txt file. When the program is run again, it will guess the old answers first (if they're in the range the user specifies).
try:
f = open("OldGuesses.txt", "a")
r = open("OldGuesses.txt", "r")
except IOError as e:
f = open("OldGuesses.txt", "w")
r = open("OldGuesses.txt", "r")
data = r.read()
number5 = random.choice(data)
print number5
When I run that to pull the old answers, it grabs one item. Like say I have the numbers 200, 1242, and 1343, along with spaces to tell them apart, it will either pick a space, or a single digit. Any idea how to grab the full number (like 200) and/ or avoid picking spaces?
The r.read() call reads the entire contents of r and returns it as a single string. What you can do is use a list comprehension in combination with r.readlines(), like this:
data = [int(x) for x in r.readlines()]
which breaks up the file into lines and converts each line to an integer.