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?
#File Handling
1 messages · Page 1 of 1 (latest)
<@&987246399047479336> please have a look, thanks.
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
zabuzard • used /tag id: nio
·
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.
Oh... thanks.
i see... but one question still unclear... can i put try(Scanner sc = new Scanner, *File object*) both together? if not then should i not treat file handling like i treat scanner? and use file.close() everywhere to avoid errors ryt?
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.
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.
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
Don't keep file open for long, I would say even, prepare the content in advance, open it, write it, close it
ideally
Okay... i will
so basically I have two options... Using Try-with-resources or manually open-> read/write -> close... ryt?
But you should use try-with-resources in almost every case.
They are the same, one just auto close
no
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
ah... sure...
I see... Okay i'll use try with resources when necessary
btw, when u use a Scanner tied to System.in, closing that would be wrong
try(Scanner sc = new Scanner(System.in)) this thing is wrong?
But use this in the main method ... the very first sentence... so the scanner closes only after the program ends?
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
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
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);
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
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
}
id say it depends
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
I see... We can have more if we manage them with caution and not let one another get in the way... Understood
Multiple instances of Scanner on the same input source is pretty much always bad (as is the case for any buffering consumer)
input source you mean... For example System.in enable Keyboard input... new File("Adi.txt") to take input from a file... ?
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
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?
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
Hehe i guessed it ryt
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"
Got experience over the years...
^ thats it
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
🙂
