Can anybody clue me into what's happening here? Or a Fine Manual to Read? Or for that matter, if there's a newbie's guide to this forum, point me at that too.
Thanks,
BC
brianThu 2 Dec 2010
Can you echo the various names like fname, infile, and outfile to see what they look like?
Not sure how that code results in a NullErr looking at it, so could be some weird bug.
vkuzkokovThu 2 Dec 2010
From docs:
virtual File rename(Str newName)
Renaming this file within its current directory. It is a convenience for:
return this.moveTo(parent + newName)
So if we pass filename with no slashes we get NullErr as specified (rather indirectly). Use outfile := `${fname}.new`.toFile.normalize as workaround.
@brian Java's null types as default strike again! I think this this should fix it http://pastebin.ca/2008902
@boxcat Even with the fix you need to change your program because it is not allowed to rename a file to an existing filename. You would have to delete it first.
vkuzkokovThu 2 Dec 2010
@katox So why calling Uri.basename exactly?
katoxThu 2 Dec 2010
@vkuzkokov, because the doc says Renaming this file within its current directory. If you call it like File(`dir/xy`).rename("dir/ab") it would move it to "dir/ab" not to "dir/dir/ab". But it could be either way, I just find that a bit confusing ;)
vkuzkokovThu 2 Dec 2010
@katox I wasn't clear:
Str basename()
Return file name without the extension (everything up to the last dot) or "" if name is "".
Uri.name() (with extension) is what you want.
katoxThu 2 Dec 2010
Aww... that's a gotcha! I'm so used to shell, C, perl, python and similar implementations that I forgot that it differs in Java (which is the type of programming tasks so unsuitable for such tasks that I avoid it where possible). And I use it so often that I didn't even check docs.
In those when you call basename you get the last part of the path. Optionally you can add an argument what to strip of it. So you would have to call `path/xx.txt`.basename(".txt") to get xx and not xx.txt.
brianThu 2 Dec 2010
Well getting a NullErr is pretty confusing behavior for a null parent. I pushed a changeset to fix it.
@boxcat, a tip on how to change newlines with less lines of code:
// readAllStr automatically converts "\r\n" into "\n"
outFile.out.print(inFile.readAllStr).close
// all lines into memory then join
outFile.out.print(inFile.readAllLines.join("\n")).close
// if performance/memory is an issue you can use eachLine
out := outFile.out
inFile.eachLine |line| { out.printLine(line) }
out.close
boxcatThu 2 Dec 2010
@katox OK. Is needing to delete() first "the semantics of least surprise"?
Wouldn't POSIX semantics be to fail only if we can't zap the existing file? What's the rationale behind wanting a delete() first?
Isn't there a chance that this could lead to lots of extra boilerplate code, such as "test to see if the file exists, if it does, delete it before the rename", which is of course, not threadsafe, as someone else could create the file after the test and before the delete()?
tcolarThu 2 Dec 2010
Not sure about that, renaming a file "onto" an existing one can be dangerous.
Best is to use Brian examples to skip the need for a temporary file.
If you still want to use a temp file, what I would do is:
create temp file
parse original file and output results to temp file
copy temp file over original file (copyTo with overwrite enabled)
delete temp file
I think that's cleaner that trying to "rename" the temp file.
DanielFathThu 2 Dec 2010
I'm pretty sure that even in Linux adding same file as one already named isn't allowed. Same with renaming.
Rationale behind delete() first would also be a security concern. What if some program gets the right to change its filename and in changing it overwrites previous file without asking the owner of overwritten file about it?
katoxThu 2 Dec 2010
@boxcat I was just making a comment about the current implementation. I'd be happier with standard unix semantics but the problem is that Java doesn't guarantee anything.
boxcat Thu 2 Dec 2010
Hi,
I'm new to Fantom, but have been having a play with it a bit today.
Here's my first bit of Fantom code (a simple dos2unix
Safari, sogoodi. But when I pass in a filename which contains a
.
, I get this error, which is the rename operation failing:bje@bje-desktop:~/projects/fantom$ ./dos2unix.fan ip-info.txt sys::NullErr: java.lang.NullPointerException
Can anybody clue me into what's happening here? Or a Fine Manual to Read? Or for that matter, if there's a newbie's guide to this forum, point me at that too.
Thanks,
BC
brian Thu 2 Dec 2010
Can you echo the various names like fname, infile, and outfile to see what they look like?
Not sure how that code results in a NullErr looking at it, so could be some weird bug.
vkuzkokov Thu 2 Dec 2010
From docs:
So if we pass filename with no slashes we get
NullErr
as specified (rather indirectly). Useoutfile := `${fname}.new`.toFile.normalize
as workaround.Maybe something like
would be more appropriate.
DanielFath Thu 2 Dec 2010
Ok I did some test and hope this narrows it down for you.
katox Thu 2 Dec 2010
@brian Java's
null
types as default strike again! I think this this should fix it http://pastebin.ca/2008902@boxcat Even with the fix you need to change your program because it is not allowed to rename a file to an existing filename. You would have to delete it first.
vkuzkokov Thu 2 Dec 2010
@katox So why calling
Uri.basename
exactly?katox Thu 2 Dec 2010
@vkuzkokov, because the doc says Renaming this file within its current directory. If you call it like
File(`dir/xy`).rename("dir/ab")
it would move it to "dir/ab" not to "dir/dir/ab". But it could be either way, I just find that a bit confusing ;)vkuzkokov Thu 2 Dec 2010
@katox I wasn't clear:
Uri.name()
(with extension) is what you want.katox Thu 2 Dec 2010
Aww... that's a gotcha! I'm so used to shell, C, perl, python and similar implementations that I forgot that it differs in Java (which is the type of programming tasks so unsuitable for such tasks that I avoid it where possible). And I use it so often that I didn't even check docs.
In those when you call
basename
you get the last part of the path. Optionally you can add an argument what to strip of it. So you would have to call`path/xx.txt`.basename(".txt")
to getxx
and notxx.txt
.brian Thu 2 Dec 2010
Well getting a NullErr is pretty confusing behavior for a null parent. I pushed a changeset to fix it.
@boxcat, a tip on how to change newlines with less lines of code:
boxcat Thu 2 Dec 2010
@katox OK. Is needing to delete() first "the semantics of least surprise"?
Wouldn't POSIX semantics be to fail only if we can't zap the existing file? What's the rationale behind wanting a delete() first?
Isn't there a chance that this could lead to lots of extra boilerplate code, such as "test to see if the file exists, if it does, delete it before the rename", which is of course, not threadsafe, as someone else could create the file after the test and before the delete()?
tcolar Thu 2 Dec 2010
Not sure about that, renaming a file "onto" an existing one can be dangerous.
Best is to use Brian examples to skip the need for a temporary file.
If you still want to use a temp file, what I would do is:
I think that's cleaner that trying to "rename" the temp file.
DanielFath Thu 2 Dec 2010
I'm pretty sure that even in Linux adding same file as one already named isn't allowed. Same with renaming.
Rationale behind delete() first would also be a security concern. What if some program gets the right to change its filename and in changing it overwrites previous file without asking the owner of overwritten file about it?
katox Thu 2 Dec 2010
@boxcat I was just making a comment about the current implementation. I'd be happier with standard unix semantics but the problem is that Java doesn't guarantee anything.