How to remove contents of the file when opened using r+ mode? - file

I've got my file open using r+ mode. I've made some alteration to it, and I would like to remove the contents of it starting from X to the end of the file.
Unfortunately I have no clue how to do that. I've been browsing through the docs, but there's no mention of that.
I don't want to write :space: to the file so it "looks" like it's cleared, I would like to make it smaller as well.
Opening the file using w is not an option in this case.

Opening a file with r+ mode preserves the current content; as the result, I don't think there is a way to truncate the rest of the file using the functions available in Lua. This SO answer indicates that it can be done using reopen with w+, but since you indicated that you can't open it for writing, I don't think there is a way to do what you want.
Testing on this script produces new contentext (where ext is the leftover from the earlier content):
local f = io.open("somefile", "w")
f:write("some long text")
f:close()
local f = io.open("somefile", "r+")
f:write("new content")
f:close()

Based on my experience, the only way I have found to truncate a file in Lua is to write the contents to a secondary file in "w+" mode, and then rename the secondary file to overwrite the original file. You will probably want to use this method sparingly depending on the size of the file, of course.
In this example "path" is the path to the original file
local file, err = io.open( path + ".tmp", "w+" )
if not file then return end
file:write( truncated_data )
file:close( )
assert( os.rename( path + ".tmp", path ) )

Related

Reading a string from a file with C. Fopen with w+ mode is not working

I made a C program that reads a string from a .txt file, then it encrypts the string, and finally it writes the string in the same file.
The thing is that if I use fopen("D:\\Prueba.txt","w+"), the program doesn't work, it prints garbage like this )PHI N.
I've debugged and I know the error is there in that line, because if I use fopen("D:\\Prueba.txt","r+"), the program works, and it writes what it should.
But I want to use w+ because it will rewrite what the .txt file had. Why is w+ not working?
If you're opening with w+ to first read the content, that's not going to work. From C11:
w+: truncate to zero length or create text file for update.
What's probably happening is that you read data from the now empty file but don't correctly check that it worked. That would explain the weird "content" you see of )PHI N.
One solution is to open the file as with r, open another file with w, and transfer the contents, encrypting them as part of that process. Then close both, delete the original, and rename the new one to the original name. This will allow you to process arbitrarily-sized files since you process them a bit at a time.
If you don't want to use a temporary file, and you're sure you can store the entire content in memory, you could open it r+, get the content, the reopen it with a new mode, such as with:
FILE *readFh = fopen( "myfile.txt", "r+");
// Read in content, massage as needed.
FILE *writeFh = frepoen( NULL, "w+", readFh);
// Provided that worked, you should now have an empty file to write to.
// Write back your massaged data.

Read/Write highscore from a file (Lua - Corona SDK)

Here's my issue: I have a file with the highscore written in it (just the first line, no nicknames, just the highscore), I need to read that line and compare it with the actual score obtained in the game session, if the score is higher, overwrite the file with the new value, but if I try to read it I get a null value... Seems like i'm not reading it the right way. What's wrong with my code?
Thanks for the help!
local path = system.pathForFile( "data.sav", system.DocumentsDirectory )
local file = io.open( path, "w+" )
highscore_letta = file:read("*n")
print(highscore_letta)
if (_G.player_score > tonumber(highscore_letta)) then
file:write(_G.player_score)
end
io.close( file )
I had this problem myself. I found out that if you open a file in "w+" mode, the current contents are deleted, so that you can write new contents. So to read and write you have to open the file twice. First, you open the file in "rb" mode and get the file contents, then close it. Then you reopen it in "wb" mode, write the new number, and close it.
In Windows, you need "b" in the file mode. Otherwise, the strings that you are reading and writing may be modified in unexpected ways: for instance, a newline ("\n") may be replaced with carriage return–newline ("\r\n").
The file modes that Lua supports are borrowed from the C language. (I found a description on page 305 of what I guess is a draft of the C specification.) I think the Lua manual sort of assumes that you will know what these modes mean, as an experienced C programmer would, but to me it wasn't at all obvious.
Thus to read a number and then write a new one:
local filepath = "path/to/file"
-- Create a file handle that will allow you to read the current contents.
local read_file = io.open(filepath, "rb")
number = read_file:read "*n" -- Read one number. In Lua 5.3, use "n"; the asterisk is not needed.
read_file:close() -- Close the file handle.
local new_number = 0 -- Replace this with the number you actually want to write.
-- Create a file handle that allows you to write new contents to the file,
-- while deleting the current contents.
write_file = io.open(filepath, "wb")
write_file:write(new_number) -- Overwrite the entire contents of the file.
write_file:flush() -- Make sure the new contents are actually saved.
write_file:close() -- Close the file handle.
I created a script to do these operations automatically, as they're somewhat annoying to type every time.
The mode "r+" or "r+b" is supposed to allow you to read and write, but I couldn't get it to work when the original contents are longer than the new contents. If the original contents are "abcd", four bytes, and the new contents are "efg", three bytes, and you write at offset 0 in the file, the file will now have "efgd": the last byte of the original contents is not deleted.

Lua file:read unexpected behavior

I'm a complete newbie in Lua and i've stumbled upon a problem i don't understand.
So what i'm trying to do is open a file, read the data and save it into a different file with a different name.
Here is the code
local infile = io.open(folder..'/'..f, "r")
local instr = infile:read("*all")
infile:close()
local outfile = io.open(folder..'/'..newName, "w")
outfile:write(instr)
outfile:close()
The result i get is a Source file 288Kb and a Dest file 2Kb
So again, as i'm a newbie in Lua, the fact that the problem is in infile:read is a wild guess for me, but the way i see it, it's either infile:read or outfile:write.
UPD:
The content is absolutely arbitrary, which implies special symbols occur.
Thank you in advance,
Regards!
I've made it work by opening the in- and output file in binary mode by adding flag b in the io.open call., so the code I have now is
local infile = io.open(folder..'/'..f, "rb")
local instr = infile:read("*all")
Log(instr)
infile:close()
local outfile = io.open(folder..'/'..newName, "wb")
outfile:write(instr)
outfile:close()

Clear contents of a Text File

I am working on a sever/client applicataion. I want to maintain information of all active clients in a text file named "Information.txt".
I update this text file after every 3 seonds. So, I want the text file to clear all of its contents after every 3 seconds without deleting the file.
Is there any way to do it ? :(
I don't want to use freopen().
A problem with clearing the file periodically is that if your process crashes after the file has been cleared but before it has been written, you lose data: the old data is gone, but the new data is not there yet.
A common approach to this problem is to create a new file, writing it, and then moving the new file to replace the old one. This way you always have a file, and sometimes (for very brief periods of time) you have two files.
Try with
fopen(filename, flag)
Open your file with flag= "w" or "wb" and it will be cleared
Just open the file with fopen and setting the flag to w or w+ or wb
From fopen man page
w
Truncate file to zero length or create text file for writing. The
stream is positioned at the beginning of the file.
w+
Open for reading and writing. The file is created if it does not
exist, otherwise it is truncated. The stream is positioned at the
beginning of the file.

Deleting contents of a file in Tcl

I'm having some troubles deleting the contents of a text file. From what I can tell, I cannot seem to rename or delete this file and create a new one with the same name, due to permission issues with the PLM software we use. Unfortunately, I am on my own here, since no one seems to know what exactly is wrong.
I can read and write to this file, however. So I've been looking at the seek command and doing something like this:
set f [open "C:/John/myFile.txt" "a+"]
seek $f 0
set fp [tell $f]
seek $f 0 end
set end [tell $f]
# Restore current file pointer
seek $f $fp
while { $fp < $end } {
puts -nonewline $f " "
incr fp
}
close $f
This seems to replace all the lines with spaces, but I'm not sure this is the correct way to approach this. Can someone give me some pointers? I'm still relatively new to Tcl.
Thanks!
If you've got at least Tcl 8.5, open the file in r+ or w+ mode (experimentation may be required) and then use chan truncate:
chan truncate $f 0
If you're using 8.4 or before, you have instead to do this (and it only works for truncating to empty):
close [open $thefilename "w"]
(The w mode creates the file if it doesn't exist, and truncates it to empty on open if it does. The rest of the program might or might not like this!)
Note however that this does not reset where other channels open on the file think they are. This can lead to strange effects (such as writing at a large offset, with the OS filling out the preceding bytes with zeroes) even without locking.
close [open $path w]
And voila, an empty file. If this file does not yet exist, it will be created.
A really easy way to do this is to just over-write your file with an empty file. For example create an empty file (you can do this manually or using the following TCL code):
set blank_file [open "C:/tmp/blank.txt" "w"]
close $blank_file
Then just over-write your original file with the blank file as follows:
file rename -force "C:/tmp/blank.txt" "C:/John/myFile.txt"
Of course, you may have permissions problems if something else has grabbed the file.
You say the file is opened exclusively with another process but you can write to it ?! I think you have permission problems. Are you using Linux or Unix ?! (It seems it is a Windows system but permission problems usually occur on Linux/Unix systems, It is weird, isn't it ?!)
The file is not exclusively opened if you are able to read and write to it and you may have no appropriate permission to delete the file.
Also it is better to test the code on a file you know you have all permissions on it. If the code is working you can focus on your target file. Also you can Google for 'how to file operations in Tcl'. Read this Manipulating Files With Tcl

Resources