Recently I got a comment to this answer that I should stay away from java.io if I want to use "pure NIO".
This is the simplified code (copy a file):
private static void copy(File source, File destination) throws IOException {
long length = source.length();
FileChannel input = new FileInputStream(source).getChannel();
FileChannel output = new FileOutputStream(destination).getChannel();
input.transferTo(0, length, output);
output.close();
input.close();
}
(code extremely simplified: removed try-finally and loop)
My question is how to get a FileChannel or other NIO class for reading a file without using java.io (FileInputStream)?
EDIT:
Java 6 (or before only)
Java 6 only has FileInputStream.getChannel(), FileOutputStream.getChannel(), and RandomAccessFile.getChannel()
Java 7 has java.nio.channels.FileChannel.open(...) and java.nio.Files.newByteChannel(...)
The javadoc of FileChannel says:
This class does not define methods for opening existing files or for creating new ones; such methods may be added in a future release. In this release a file channel can be obtained from an existing FileInputStream, FileOutputStream, or RandomAccessFile object by invoking that object's getChannel method, which returns a file channel that is connected to the same underlying file.
That is, with java 1.6 you can't get a FileChannel without using old java.io.
Related
I am working on a project which creates a file with .bat extension.
In C++ it is possible by using
fstream myfile ("example.bat");
fstream<<"echo \"hello\" ";
But how can I do it in Java (JDK 8)?
I would suggest reading up on Java File IO. Whatever you want to call the file you're saving, you can. There aren't any custom extensions as opposed to normal extensions.
Additional Resource
I think this code does what you want. createFile will throw FileAlreadyExistsException if specified file already exists.
Path myBat = Paths.get("example.bat");
Files.createFile(myBat);
try( BufferedWriter reader = Files.newBufferedWriter(myBat) ) {
reader.append("hello");
}
Edit:
I think try-with-resources is needed here.
How can I download .class file and and load it into jvm using class loader , I have write a simple code simulates downloading a .class file the I tried to load it into JVM
public class face {
public static void main(String[] args) throws IOException,
ClassNotFoundException {
File f = new File("Task.class");
int count;
byte[] buffer = new byte[1024];
DataInputStream dis = new DataInputStream(new FileInputStream(f));
StringBuilder all = new StringBuilder();
while ((count = dis.read(buffer)) > 0) {
// System.out.write(buffer, 0, count);
all.append(buffer);
// System.out.flush();
}
File b = new File("Task.class");
FileOutputStream fos = new FileOutputStream(b);
DataOutputStream dos = new DataOutputStream(fos);
dos.write(all.toString().getBytes());
ClassLoader lod = face.class.getClassLoader();
lod.loadClass(b.getAbsolutePath());
}
}
Use Class.forName(<package_qualified_class_name>)
First, I would like to applogies for the long list of suggestion here, but you have managed to cram an impressive number of mistakes into a small piece of code.
I suggest don't do any of these things
don't use DataInputStream or DataOutputStream when it doesn't add anything. You don't use any method which requires it.
don't write binary data to a StringBuilder. A StringBuilder is for text.
don't copy an entire buffer if you only read part of it. i.e. you need to record the length actual read and copy only the amount used.
don't append a byte[] to a StringBuilder. It won't do what you expect.
don't use a String to store binary data.
don't convert a String to byte[] using the default encoding unless you know you have ASCII data (which you don't)
don't write to a file you just read. As this doesn't make sense. You should have tested this works without the file copy and you would have found this didn't work, before you attempted something more complicated.
you can't write to a file which you still have open in windows. I suggest you close() a file when you are finished with it.
don't attempt to load a class using the file name. You load it by package.class name.
I suggest you try a one liner to load a class first and show this works. The class should appear in your class path, and when you write to the file, you should write it to a directory appropriate for the package.
Instead of doing all this, you could add a http://yourserver/basepath to your class path and it will load the classes from a web service. i.e. you might be able to do this without writing any code at all.
This question already has an answer here:
Get filename from an inputstream (Java)
(1 answer)
Closed 8 years ago.
I have a method accepts an InputStream as an argument. How do I find which file is being handled by the passed handler?
For example:
public performSomething(InputStream inputStream) {
System.out.println(FILENAME);
}
What should the FILENAME be replaced with such that the name of the file opened by the handler is displayed.
I guess you cannot, because the input stream might not belong to a file. It can be SocketInputStream, or ByteArrayInputStream for example. The input stream is just an abstraction
An input stream can be created to read from a file or from any other source of data. Therefore it makes no sense to have a filename attached to an input stream.
Simple Example :
InputStream input= assetInfo.openStream();
File t = new File("");
OutputStream out = new FileOutputStream(t);
int read=0;
byte[] bytes = new byte[1024];
while((read = input.read(bytes))!= -1){
out.write(bytes, 0, read);
}
Look in assetInfo to see if that class exposes that data (you can even look inside the class using reflection). Note that the creator or assetInfo made a design mistake not exposing this information, OR you are trying to make one now.
Even if you are certain you have a FileInputStream, you will still be unable to get the underlying file. FileInputStream does not retain its File argument, but immediately opens the file and retains just the FileDescriptor, a wrapper around the native int handle to the OS resource.
As of OpenJDK version 7, Update 40, a String path variable has been introduced, so with some luck you may try to reflectively get it.
Of course, this can be nothing more than heurstics. There is no official way through the public API.
I want to convert this code in java
fopen_s(&stream, "path", "w+");
w+ opens empty file with both reading and writing. If the given file exists, it's contents are destroyed.
any suggestions?
It seems 1.7 java is required for the nio, so my take is
RandomAccessFile f = new RandomAccessFile(name, "rw");
f.setLength(0);
I am not a Java programmer, but I had a short hunt around the web and it seems Java has a RandomAccessFile and you open it with the mode "rw".
The true equivalent is to use Files.newByteChannel.
final SeekableByteChannel channel = Files.newByteChannel(Paths.get("path"),
StandardOpenOptions.READ, StandardOpenOptions.WRITE,
StandardOpenOptions.TRUNCATE_EXISTING);
The READ and WRITE options determine if the file should be opened for reading and/or writing.
...
TRUNCATE_EXISTING - If this option is present then the existing file is truncated to a size of 0 bytes. This option is ignored when the file is opened only for reading.
Looks like you want either FileOutputStream or FileWriter, depending on what kind of data you want to write. Either of them can be instantiated with a filename.
FileOutputStream fis = new FileOutputStream("/path/to/file");
FileWriter fw = new FileWriter("/path/to/file2");
And both will clobber the file if it already exists. (Though constructors exists for appending instead of over-writing)
Quick way to achieve what you want:
import java.io.*;
// Create a new file output connected to "myfile.txt"
out = new FileOutputStream("myfile.txt");
// Create a new file input connected to "myfile.txt"
in = new FileInputStream("myfile.txt");
You might want to take a look at the java.io package at the official docs, especially the RandomAccessFile Class and also this quick guide.
Many I/O resources in Java such as InputStream and OutputStream need to be closed when they are finished with, as discussed here.
How can I search my project for places where such resources are not being closed, e.g. this kind of error:
private void readFile(File file) throws IOException {
InputStream in = new FileInputStream(file);
int nextByte = in.read();
while (nextByte != -1) {
// Do something with the byte here
// ...
// Read the next byte
nextByte = in.read();
}
// Oops! Not closing the InputStream
}
I've tried some static analysis tools such as PMD and FindBugs, but they don't flag the above code as being wrong.
It's probably matter of setting - I ran FindBugs through my IDE plugin and it reported OS_OPEN_STREAM.
If FindBugs with modified rules doesn't work for you, another slower approach is heap analysis. VisualVM allows you to query all objects of a specific type that are open at any given time within a heap dump using OQL. You could then check for streams open to files that shouldn't be accessed at that point in the program.
Running it is as simple as:
%>jvisualvm
Choose the running process. Choose option save heap dump (or something to that effect), open the heap dump and look at class instances for file streams in the browser, or query for them.
In Java 7, they added a feature of using closable resources in current scope (so called try-with-resources), such as:
public void someMethod() {
try(InputStream is = new FileInputStream(file)) {
//do something here
} // the stream is closed here
}
In older versions, the common technique is using try-catch-finally chain.