#File Handling

1 messages · Page 1 of 1 (latest)

maiden sage
#

I need some suggestions as i have never worked with files , reading writing... i read documentation and tutorials and it sounds good ... But I have this question... Just like we instantiated the Scanner object in try-with-resources should i do the same for file object so that we only have one instance of file object and it works throughout the program... but even if i do that i'll create only one file ryt? for example File objFile = new File("E:\\Work\\JAVA\\Notes\\Adi.txt"); here only Adi.txt file will be created instead i want to just specify path and create multiple files with the same instance? but finally i can think that i'll have to create a file instance every time i want to create a new file... am i ryt?

paper roseBOT
#

<@&987246399047479336> please have a look, thanks.

radiant zenith
#

uve probably ran into old tutorials

#

use this:

paper roseBOT
#

File IO in Java should be done preferably with NIO (Java 7+), revolving around the classes Files and Path; and not with the old interface File, BufferedReader, FileReader and similar.

NIO is simple to use. The path to a file is represented using the Path class:

Path path = Path.of("myFile.txt");

All file operations can be found in the Files class:

// Reading
List<String> allLines = Files.readAllLines(path);
// or as a single string
String content = Files.readString(path);
// or with a stream
try (Stream<String> stream = Files.lines(path)) {
  stream.forEach(System.out::println);
}

// Writing
Files.write(path, lines);
// or as a single string
Files.writeString(path, "hello world");
// or with extra options
Files.writeString(path, "hello world",
  StandardOpenOption.WRITE,
  StandardOpenOption.CREATE,
  StandardOpenOption.APPEND);

If you need more control over the process, you can fallback to the old interface, but prefer using the bridge methods from NIO (Files.newBufferedReader, Files.newInputStream, path.toFile() and similar) to benefit from advantages such as correct encoding and better error detection.

Here is a simple example of how to read a file line-wise with the old interface

try (BufferedReader br = Files.newBufferedReader(path)) {
  String line;
  while ((line = br.readLine()) != null) {
    System.out.println(line);
  }
}

it is way more verbose than NIO but it gives more control.

You must not forget to close file handles, even in all exceptional cases. Closing a handle manually is very hard, which is why you should always use try-with-resources for this to let Java automatically close the handle for you:

try (SomeResource resource = ...) {
  ...
} // Automatically closed here, even in exceptional cases
safe pumice
#

java.io.File is ancient. It's really just wrapping up a path-name. The new file-io package is java.nio.file and Path replaces the File class.

The rest is as Zabuzard's tag suggests.

maiden sage
maiden sage
#

Maybe I answered my own question... I can leave a scanner object for multiple inputs but with files maybe i need to be more cautious and close it when my work is done... also there was this term i found Sync and Async which said during an error the data may get lost ... does that mean if i catch an exception the program will end without saving the previous data to the files if i don't Sync it?? if so then maybe i'll have to read how to use syncing here properly.

safe pumice
#

A Scanner is an object that is connected to input.

A File or Path is just a file-name. It's not connected to anything. You can use File or Path with another method or type to read, write files, delete or lookup files.

#

Hence Path is a much better name for it.

#

A Reader is connected to input (and that could be a file, just as Scanners can be connected to several different sources of input).

#

try-with-resources is about closing those connections. This is ideal to do for files you're reading, but it can be critical for files you're writing (since they may not have 'flushed' their buffer to the file until it is closed - which try-with-resources does for you)

#

Failing to close files you're reading is still bad - it ties up resources that might not be released until the application exits.

radiant zenith
#

just to make sure this is clear. when u write new File("foo.txt"), this does NOT create a file at all

#

its just a badly named class

#

which is why u should use the replacement Path instead

jovial tusk
safe pumice
#

ideally

maiden sage
#

so basically I have two options... Using Try-with-resources or manually open-> read/write -> close... ryt?

safe pumice
#

But you should use try-with-resources in almost every case.

jovial tusk
radiant zenith
#

in many cases u will use the one liners Files.write(...) and Files.readAllLines(...)

#

those dont need any extra closing or try-with-resource since they are one-shot methods

#

the connection is opened and closed by the method itself

#

u dont need to do anything extra

#

(please just read the explanation given by the bot, it has all of this)

#

if u need to do more sophisticated stuff, for example Files.lines(), u would put it into a try-with-resources. same with the bridge methods to the old io pipes

maiden sage
#

I see... Okay i'll use try with resources when necessary

radiant zenith
#

btw, when u use a Scanner tied to System.in, closing that would be wrong

maiden sage
#

try(Scanner sc = new Scanner(System.in)) this thing is wrong?

radiant zenith
#

yes

#

thats wrong

#

this scanner should not be closed

#

closing the scanner closes the underlying resource. in this case, System.in.
that means ull never be able to read any user input anymore since u cant open System.in anymore.
System.in is managed by the JVM, its not ur responsibility to open/close it

maiden sage
#

But use this in the main method ... the very first sentence... so the scanner closes only after the program ends?

radiant zenith
#

scanners themselves arent resources that need closing

#

its what ur scanner is tied to that potentially needs to be closed

#

for example if u open a scanner to read from a file

safe pumice
#

Yes. When the program ends, System.in no longer exists.

radiant zenith
#

new Scanner(new File("foo.txt"))

#

this needs closing bc u need to close the file

#

but System.in is managed by the JVM, u dont need to close it

maiden sage
#

I see...

#

Okay i'll change it... instead of try(Scanner sc = new Scanner(System.in)) i'll simply instantiate it in the main method... Scanner sc = new Scanner(System.in);

radiant zenith
#

yup

#

its just, imagine u want to create a second scanner later on

safe pumice
#

Imagine you have a team working on your program and the requirements change. They want to read something else from System.in, but you've broken it. The correct choice is never to close System.in

radiant zenith
#

it would crash

#
try (Scanner scanner = new Scanner(System.in)) {
  ...
}

...

// Crashes here:
try (Scanner scanner = new Scanner(System.in)) {
  ...
}
#

says something like System.in was closed, cant be used anymore

maiden sage
#

Okay... but it's also bad practice to create multiple instances of scanner ryt? insted create one scanner and pass it to further classes that need it?

#

For example

Scanner sc = new Scanner(System.in);
void doStuffs(){}//uses scanner
}
class Random2 {
Scanner sc = new Scanner(System.in);
void doSomething(){}//uses scanner
}
radiant zenith
#

generally yes but sometimes its handy to create multiple. especially if the two locations are very far apart

#

sth u should keep in mind is that there is always only max one scanner (tied to the same resource) at a given moment

#

if u have two scanners open to the same resource at the same time, they can get in their way

maiden sage
#

I see... We can have more if we manage them with caution and not let one another get in the way... Understood

safe pumice
#

Multiple instances of Scanner on the same input source is pretty much always bad (as is the case for any buffering consumer)

maiden sage
#

input source you mean... For example System.in enable Keyboard input... new File("Adi.txt") to take input from a file... ?

radiant zenith
#

thing is, scanners read data from the resource they are tied to

#

and then they buffer it

#

and that can lead to unexpected results

#

for example lets say u have

#
Scanner first = new Scanner(System.in);
Scanner second = new Scanner(System.in);

System.out.println("Enter a number:");
int x = first.nextInt();

System.out.println("Now a word: ");
String text = second.nextLine();
#

when first.nextInt() is hit, the program blocks and u have to input something into the console

#

lets say instead of just entering a number u enter 5 hello and then hit the enter key

#

the first scanner now consumes the entire content

#

it reads 5 hello

#

it returns back 5 and puts hello into its internal buffer

#

now, when second.nextLine() attempts to read content, it does not see the hello

#

the hello is in the first scanners internal buffer. so not visible to second anymore

#

when u call first.nextLine() u get hello

#

when u call second.nextLine(), u dont get it

#

thats generally unexpected and confusing

#

especially since the way how scanner buffers is an internal detail that could potentially change in an upcoming java version

#

meaning the behavior isnt even stable

maiden sage
#

Okay... i get it... also if i were to use ```
System.out.println("Enter your first name:");
String name = first.next();
System.out.println(name);

the output will be "hello" since it was in the buffer already and it won't even bother waiting for me to enter my name... ryt?
radiant zenith
#

yes

#

scanner first consumes from its buffer

#

and if that is empty it will trigger resource.read()

#

with resource being the InputStream u tied it to

#

(for example System.in)

#

and thats what will block the program and wait for u to enter sth on the console

maiden sage
#

Hehe i guessed it rytpeepo_happy

#

Well One questions... How do you guys know this much? Got experience over the years... Or It's just common sense or A dedicated course like "How JVM works"

radiant zenith
#

ull be there as well after ur doing this for that many years, lol

#

also, especially scanner stuff, is asked here on the server on a weekly basis

#

🙂

maiden sage
#

🥲 oh... DW I'll master it soon and help you to help with weekly Scanner doubtspeepo_heart

#

Anw thanks guys my doubt's clear... I'll close this thread (after gulping all the knowledge)