Win a copy of Think Java: How to Think Like a Computer Scientist this week in the Java in General forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

FileWriter.write(String str)

 
sarah Marsh
Ranch Hand
Posts: 282
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello:

After I create a fileWriter, I use
fileWriter.write(message);
to write a very long string to a file.

There's another process B reading the file, how to make sure when process B reads the file, the file is already generated totally?

Thanks a lot!
 
Keith Lynn
Ranch Hand
Posts: 2409
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I would wrap a PrintWriter around the FileWriter before writing to the file. Also if you use synchronized methods you can prevent the thread that tries to read from the file from executing until the method that writes to the file is finished.
 
Jeff Albertson
Ranch Hand
Posts: 1780
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Because you are dealing with separate processes, the solution is probably outside the realm of Java. The standard solution, as well as a best practice, is to write to a temporary file and then have the writer *rename* the file to its proper directory. Not only does this solve your problem, it keeps your target directory free from junk files caused by the writing program pooping out half way through its writing task, for example.
[ February 03, 2006: Message edited by: Jeff Albertson ]
 
Jeff Albertson
Ranch Hand
Posts: 1780
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
BTW, synchronization has no effect on separate processes...
 
sarah Marsh
Ranch Hand
Posts: 282
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Actually, the process B is a FTP process, how to make sure in this case?
 
Keith Lynn
Ranch Hand
Posts: 2409
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
What I meant was have two methods, one in which the writing is done, and one in which the reading is done.
 
Jeff Albertson
Ranch Hand
Posts: 1780
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by sarah Marsh:
Actually, the process B is a FTP process, how to make sure in this case?


That wasn't addressed to my posts, eh? In renaming, the writer (process A) does the renaming. Process B is unaware of this.
 
wise owen
Ranch Hand
Posts: 2023
 
Jeff Albertson
Ranch Hand
Posts: 1780
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I'm just pouring vinegar on this thread!

If you are thinking of using locks, be warned. As the API for java.nio.channels/FileLock states:

Whether or not a lock actually prevents another program from accessing the content of the locked region is system-dependent and therefore unspecified. The native file-locking facilities of some systems are merely advisory, meaning that programs must cooperatively observe a known locking protocol in order to guarantee data integrity. On other systems native file locks are mandatory, meaning that if one program locks a region of a file then other programs are actually prevented from accessing that region in a way that would violate the lock. On yet other systems, whether native file locks are advisory or mandatory is configurable on a per-file basis. To ensure consistent and correct behavior across platforms, it is strongly recommended that the locks provided by this API be used as if they were advisory locks.

I've always found file locks to be advisory. YMMV
 
sarah Marsh
Ranch Hand
Posts: 282
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Jeff,

I posted the second one before I saw your response.

But how to make sure the file creation is done before the renaming? synchronization here?

Thanks.
 
Ernest Friedman-Hill
author and iconoclast
Marshal
Pie
Posts: 24211
35
Chrome Eclipse IDE Mac OS X
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by sarah Marsh:
Jeff,

I posted the second one before I saw your response.

But how to make sure the file creation is done before the renaming? synchronization here?

Thanks.


They're both done by the same process, so you simply do them in order.

1) Write file
2) Close it
3) Rename it
 
sarah Marsh
Ranch Hand
Posts: 282
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Should I do something like this:
fileWriter.write(message);
fileWriter.close();
// then rename it
...


fileWriter.close(); will wait for writing to be done?
 
Jeff Albertson
Ranch Hand
Posts: 1780
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by sarah Marsh:

fileWriter.close(); will wait for writing to be done?


I took a quick in the API assuming there would be such an assurance, but I didn't find it. It may be there, but if not, you can always explicitly sync up with your file system:

It's important that you do this in order: flush/sync/close. If you sync first, then any data buffered in memory is not considered and if you sync after closing, that's an error -- one must sync on an open file.

Again, I'm not sure this is strictly needed, but it can't hurt (okay, sync can slow things down a little, but that's the price of ordering operations.)
[ February 03, 2006: Message edited by: Jeff Albertson ]
 
sarah Marsh
Ranch Hand
Posts: 282
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
what if I use FileWriter(File file) not FileWriter(FileDescriptor fd),
there's no sync() method on 'file' object? Thanks again!
 
Jeff Albertson
Ranch Hand
Posts: 1780
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
... You'll have to rewrite your code. File objects merely represent the path rather than the file as a resource. What's happening in your code is that the FileWriter's constructor is creating a FileOutputStream but it is not exposing it. You'll have to rewrite your code slightly to be more deliberate.
 
Jim Yingst
Wanderer
Sheriff
Posts: 18671
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I never liked FileWriters much anyway, as they don't let you specify an encoding. So this is just another reason not to use them. Note that you can also use a FileChannel or MappedByteBuffer, both of which have a force() method that does basically the same thing as sync().

As for assurances in the API, in fact the API for Writer specifically tells us that (a) close() implies flush(), but also (b) flush() does not guarantee an immediate write to the file:

"If the intended destination of this stream is an abstraction provided by the underlying operating system, for example a file, then flushing the stream guarantees only that bytes previously written to the stream are passed to the operating system for writing; it does not guarantee that they are actually written to a physical device such as a disk drive."

So, it does seem that a sync() or force() is necessary to ensure the file is completely written before the move, in general. Annoying but true...
 
Jeff Albertson
Ranch Hand
Posts: 1780
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Jim Yingst:
I never liked FileWriters much anyway...


I'm always suspicious of derived classes that only define constructors.
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic