i am a nibble in java. i have my own efforts to get the things done. but certainly i am facing a challenge. i have a dummy program that searches for files of a particular extension(.txt) supplied as a command line argument. i am trying to make file objects of these searched file for further manipulations. but i can't understand how to do this in my code.. here is my code sample...
public class Find {
public static class Finder extends SimpleFileVisitor<Path> {
private final PathMatcher matcher;
private int numMatches = 0;
Finder(String pattern) {
matcher = FileSystems.getDefault().getPathMatcher("glob:" + pattern);
}
void find(Path file) {
Path name = file.getFileName();
if (name != null && matcher.matches(name)) {
numMatches++;
System.out.println(file);
}
}
// Prints the total number of
// matches to standard out.
void done() {
System.out.println("Matched: "+ numMatches);
}
// Invoke the pattern matching
// method on each file.
//#Override
public FileVisitResult visitFile(Path file,
BasicFileAttributes attrs) {
find(file);
return CONTINUE;
}
// Invoke the pattern matching
// method on each directory.
//#Override
public FileVisitResult preVisitDirectory(Path dir,
BasicFileAttributes attrs) {
find(dir);
return CONTINUE;
}
//#Override
public FileVisitResult visitFileFailed(Path file, IOException exc) {
System.err.println(exc);
return CONTINUE;
}
}
public static void main(String[] args) throws IOException {
Iterable<Path> root;
root = FileSystems.getDefault().getRootDirectories();
// System.out.println(name.getAbsolutePath());
for (Path startingDir : FileSystems.getDefault().getRootDirectories()) {
String pattern = args[0];
Finder finder = new Finder(pattern);
Files.walkFileTree(startingDir, finder);
}
}
}
here is what i am trying to do. the output of my program is a long list of text files with their absolute path. now i want to make objects of these files so that i can upload these to a URL. to upload them i have to make a stream with file object to be sent..how to get absoluteFilename?? to get this you must have a file object...right.... and my revised question is : how to make file objects of searched files???
FileInputStream fileInputStream = null;
try {
new FileInputStream("absoluteFilename");
byte[] buffer = new byte[MAX_SIZE];
int bufferIndex = 0;
while (fileInputStream.available() > 0) {
buffer[bufferIndex++] = (byte) fileInputStream.read();
}
byte[] fileContent = new byte[bufferIndex];
System.arraycopy(buffer,0,fileContent,0,bufferIndex);
URL serverUrl = new URL(url);
URLConnection connection = serverURL.openConnection();
connection.setConnectTimeout(60000);
connection.getOutputStream().write(fileContent);
} catch (Exception fatal) {
//proper handling??
Related
I am new to Java. Looking for code to search for files with .ofg extension in all the sub-directories of /var/data.
The desired outputs are
the subdirectory name(s), which has the files with those files
the full names of the files
the number of those files in that subdirectory.
There are some tutorials available, but nothing i could find fitting to my code base; like
public class FindFiles {
int inProcThreshold = 0;
protected File recurfile(File file) {
File[] dirlist = file.listFiles();
for (File f : dirlist) {
if (f.isDirectory()) {
return f;
}
}
return null;
}
protected int numOfInProcs(String location, int level, int maxdepth) {
File base = new File(location);
File[] firstlevelfiles = base.listFiles();
while (level <= maxdepth) {
for (File afile : firstlevelfiles) {
if (afile.isDirectory()) {
base = recurfile(afile);
} else {
if (afile.getName().endsWith(".txt")) {
inProcThreshold++;
}
}
}
level++;
}
return inProcThreshold;
}
public static void main(String[] args) {
FindFiles test = new FindFiles();
String dirToList = "I:\\TEST-FOLDER";
String ext = ".txt";
int count = test.numOfInProcs(dirToList, 0, 10);
System.out.println("Number of txt files are " + count);
}
}
This is the code I am trying but it returns 0 as output to me. I am trying to search for files with extension.txt in the I:\TEST-FOLDER subfolders.
Use this filter by giving directory addres in dirName Parameter it will list all directories with extension .ofg
import java.io.File;
import java.io.FilenameFilter;
public class Filter {
public File[] finder( String dirName){
File dir = new File(dirName);
return dir.listFiles(new FilenameFilter() {
public boolean accept(File dir, String filename)
{ return filename.endsWith(".ofg"); }
} );
}
}
I think what you are looking for is Files.find. Pass it a Predicate which checks that path.toString().endsWith(".ofg"),
It will return a Stream of Path objects representing the matching files. You can extract all the data you want by iterating on this Stream.
If you are not required to write the recursive part yourself (for practice or as task), you could use Files#walkFileTree with a custom implementation of the FileVisitor Interface (As #Mena proposed in his comment).
Extend the SimpleFileVisitor class (or implement the FileVisitor interface) and provide your code to be executed on each file:
public class OfgFolderCollectingFileVisitor extends SimpleFileVisitor<Path> {
/** Stores the matching file paths */
private final List<Path> collectedPaths = new LinkedList<>();
#Override
public FileVisitResult visitFile(final Path file, final BasicFileAttributes attrs) throws IOException {
// check if the current file is an .ofg file
if (file.toString().endsWith(".ofg")) {
// it is -> add it's containing folder to the collection
this.collectedPaths.add(file.getParent());
}
return super.visitFile(file, attrs);
}
public List<Path> getCollectedPaths() {
return this.collectedPaths;
}
}
Then pass an instance of your implementation to Files#walkFileTree and check the collected paths afterwards:
final OfgFolderCollectingFileVisitor visitor = new OfgFolderCollectingFileVisitor();
try {
Files.walkFileTree(Paths.get("/var/data"), visitor);
} catch (final IOException ex) {
ex.printStackTrace();
return;
}
// let's see if something matched our criteria
final List<Path> ofgContainers = visitor.getCollectedPaths();
System.out.printf("Files found: %d%n", ofgContainers.size());
if (!ofgContainers.isEmpty()) {
System.out.printf("%nContaining directories:%n");
for (final Path ofgContainer : ofgContainers) {
System.out.printf("- %s%n", ofgContaininer);
}
}
Here is some example output (yes, folder2 and it's subfolder contain an .ofg file)
Files found: 3
Containing directories:
- \var\data\folder1\folder1.1
- \var\data\folder2
- \var\data\folder2\folder2.2
I need to get all the absolute file path of the files with extension .pdf. I am using the code mentioned below, but I'm able to only get the absolute file path of only one file.
How can I modify the code to get all the absolute file paths ?
public class FindFiles {
String absoluteFilePath = "";
String fileName;
public String PdfFiles(String parentDirectory, String fileExtension) {
FileFilter fileFilter = new FileFilter(fileExtension);
File parentDir = new File(parentDirectory);
// Put the names of all files ending with .pdf in a String array
String[] listOfTextFiles = parentDir.list(fileFilter);
if (listOfTextFiles.length == 0) {
System.out.println("There are no files in this direcotry!");
}
for (String file : listOfTextFiles) {
//construct the absolute file paths...
absoluteFilePath = new StringBuffer(parentDirectory).append(File.separator).append(file).toString();
fileName = file.toString();
}
return absoluteFilePath;
}
public static void main(String args[]) {
FindFiles f = new FindFiles();
f.PdfFiles("", "");
}
}
you are overrding absoluteFilePath every time in the loop;
try with
absoluteFilePath += new StringBuffer(parentDirectory).append(File.separator).append(file).toString();
Don't be bothered, use java.nio.file:
final Path dir = Paths.get(baseDir).toAbsolutePath();
final String filter = "*." + extension;
final List<Path> ret = new ArrayList<>();
try (
final DirectoryStream<Path> dirstream
= Files.newDirectoryStream(dir, filter);
) {
for (final Path entry: dirstream)
ret.add(entry);
}
return ret;
If you use Java 8, it's even more simple.
A more efficient solution for your problem can be given using classes in java.nio package.
E.g. For checking whether a file is a pdf file or not, use Files.probeContentType(Path path).
Instead of writing loops to visit all directories and files inside these directories, use Files.walkFileTree(Path start, FileVisitor<? super Path> visitor)
Solution for your problem using these classes are
public class FindPdfFiles {
public static void main(String[] args) throws IOException{
final Path path = Paths.get("C:\\SearchDirectoryForPDF");
Files.walkFileTree(path, new FindPdfFilesFilter());
}
}
class FindPdfFilesFilter extends SimpleFileVisitor<Path> {
#Override
public FileVisitResult visitFile(Path path, BasicFileAttributes arg1)
throws IOException {
final String mimeTypeOfFile = Files.probeContentType(path);
if(mimeTypeOfFile != null && !mimeTypeOfFile.isEmpty() && mimeTypeOfFile.toLowerCase().contains("pdf")) {
System.out.println(path.toString());
}
return FileVisitResult.CONTINUE;
}
}
I'm not sure if that's the right way to ask this, but I'm gonna try to explain my case and what I need.
I have a big java project, that upload files in many different java classes, like too many, and I have around 7 different main folders where the files are uploaded. The files at the moment are saved inside the webapp context, and I need to save them outside of context.
If there were only a few classes that upload these files I could spend a few days changing every class and direct it to a path outisde of context, but there are way too many classes, so I have to figure out a way to do it without changing every class, or any class at all, which would be ideal.
Every upload is done in the following way:
I get real path of one of my main folders:
String realpath = httpServletRequest.getSession()
.getServletContext()
.getRealPath("/mainfolder1/mainsubfolder1/");
Then I get the file and set custom file name:
FormFile file = myForm.getFile();
String contentType = file.getContentType();
String fileName = file.getFileName();
int fileSize = file.getFileSize();
customFileName = "anyName" + fileName.substring(fileName.lastIndexOf("."));
Then I validate and save the file:
if (fileSize > 0 && contentType != null && fileName.length() > 0){
InputStream in = file.getInputStream();
OutputStream bos = new FileOutputStream(realpath + "/" + customFileName);
int byteRead = 0;
byte[] buffer = new byte[8192];
while ((byteRead = in.read(buffer, 0, 8192)) != -1){
bos.write(buffer, 0, byteRead);
}
bos.close();
in.close();
}
Very simple way to save my files, and as you can see, they are saved inside context.
So if I could somehow override java.io.FileOutputStream, to not only save it inside context, but to make a copy outside of context too, that would be great, like save it in the specified path and also on some other path outside of context.
But I don't know if this is possible, or how to reproduce this behaviour.
What I need is to keep the class code exactly as it is but write the file 2 times:
First here: "/insideContext/mainfolder1/mainsubfolder1/"
Then here: "/outsideContext/mainfolder1/mainsubfolder1/"
Is this possible? If not, what would be the best way to accomplish this?
I'd refactor and use Decorator or Wrapper pattern. More about it here
Below some simple idea you could use.
public class ContextAwareDuplicatorOutputStream extends OutputStream {
FileOutputStream insideContext;
FileOutputStream outsideContext;
public ContextAwareDuplicatorOutputStream(String insideContextPath,
String outsideContextPath, String fileName)
throws FileNotFoundException {
insideContext = new FileOutputStream(insideContextPath
+ File.pathSeparator + fileName);
outsideContext = new FileOutputStream(outsideContextPath
+ File.pathSeparator + fileName);
}
#Override
public void close() throws IOException {
insideContext.close();
outsideContext.close();
}
#Override
public void flush() throws IOException {
insideContext.flush();
outsideContext.flush();
}
#Override
public void write(byte[] b) throws IOException {
insideContext.write(b);
outsideContext.write(b);
}
#Override
public void write(byte[] b, int off, int len) throws IOException {
insideContext.write(b, off, len);
outsideContext.write(b, off, len);
}
#Override
public void write(int b) throws IOException {
insideContext.write(b);
outsideContext.write(b);
}
}
Since you don't want to edit anything on your code, create a ServletContextListener that monitor the folder where you upload, and on the new file event, you copy it to the proper directory. Here is awnsered how to monitor a directory. Directory listener in Java
Below here is a small code, not really perfect, but the idea is there
public class FileMonitorServletContextListener implements
ServletContextListener {
public interface FileMonitor {
void start(String fromFolder, String toFolder);
void stop();
}
public class SimpleThreadedWatcher implements FileMonitor {
private class SimpleThread extends Thread {
private boolean running = true;
private String fromFolder;
private String toFolder;
public SimpleThread(String fromFolder, String toFolder) {
this.fromFolder = fromFolder;
this.toFolder = toFolder;
}
private void copy(Path child, String toFolder) {
// Copy the file to the folder
}
#Override
public void run() {
try {
WatchService watcher = FileSystems.getDefault()
.newWatchService();
Path fromPath = Paths.get(fromFolder);
watcher = FileSystems.getDefault().newWatchService();
WatchKey key = fromPath.register(watcher,
StandardWatchEventKinds.ENTRY_CREATE);
while (running) {
for (WatchEvent<?> event : key.pollEvents()) {
// Context for directory entry event is the file
// name of
// entry
#SuppressWarnings("unchecked")
WatchEvent<Path> ev = (WatchEvent<Path>) event;
Path name = ev.context();
Path child = fromPath.resolve(name);
// print out event
System.out.format("%s: %s\n", event.kind().name(),
child);
copy(child, toFolder);
boolean valid = key.reset();
if (!valid) {
break;
}
}
Thread.sleep(1000);
}
} catch (Exception e) {
throw new RuntimeException("Error: ", e);
}
}
public void stopWorking() {
running = false;
}
}
private SimpleThread worker;
#Override
public void start(String fromFolder, String toFolder) {
worker = new SimpleThread(fromFolder, toFolder);
worker.start();
}
#Override
public void stop() {
worker.stopWorking();
}
}
FileMonitor fileMonitor = new SimpleThreadedWatcher();
#Override
public void contextDestroyed(ServletContextEvent arg0) {
fileMonitor.stop();
}
#Override
public void contextInitialized(ServletContextEvent arg0) {
fileMonitor.start("FROM", "TO");
}
}
I have a folder with 3 picture inside of them which I wish to zip and email. I have a method that does this which I've used with previous problems and it works fine. However this time it keeps generating an invalid zip and when I open the zip it only has 1 picture inside with a size of 0.
I can't seems to figure out why though. This is the method:
//generate the zip file for the picture
String zipFile = context.getExternalFilesDir(null) + "/ArcFlash/Checklist.zip";
String srcDir = context.getExternalFilesDir(null) + "/ArcFlash/CheckListMedia";
FileOutputStream fos = new FileOutputStream(zipFile);
ZipOutputStream zos = new ZipOutputStream(fos);
File srcFile = new File(srcDir);
addDirToArchive(zos, srcFile, context);
here is my addDirToArchive method which generates the zip:
private static void addDirToArchive(ZipOutputStream zos, File srcFile, Context ctx)
{
File[] files = srcFile.listFiles();
for (int i = 0; i < files.length; i++)
{
// if the file is directory, use recursion
if (files[i].isDirectory())
{
addDirToArchive(zos, files[i], ctx);
continue;
}
try
{
System.out.println("tAdding file: " + files[i].getName());
// create byte buffer
byte[] buffer = new byte[1024];//2048
FileInputStream fis = new FileInputStream(files[i]);
String target = ctx.getExternalFilesDir(null) + "/";
String oldPath = files[i].getPath();
String newPath = oldPath.replace(target, "");
zos.putNextEntry(new ZipEntry(newPath));
int length;
while ((length = fis.read(buffer)) > 0)
{
zos.write(buffer, 0, length);
}
zos.closeEntry();
// close the InputStream
fis.close();
}
catch (Exception ex)
{
Log.i("customException", "error zipping: " + ex.getMessage());
}
}
}
EDIT
Using the code samples below, here is how to do what you want:
final Path basePath = Paths.get(context.getExternalFilesDir(null));
final Path srcDir = Paths.resolve("ArcFlash/CheckListMedia");
final Path zipFile = Paths.resolve("ArcFlash/Checklist.zip");
final Map<String, Object> env = new HashMap<>();
env.put("create", "true");
final URI zip = URI.create("jar:file:" + zipFile.toAbsolutePath().toString());
try (
final FileSystem fs = FileSystems.newFileSystem(zip, env, null);
) {
Files.walkFileTree(srcDir, new CopyFileVisitor(srcDir, fs.getPath("/")));
}
First, a sample of how to create a zip file:
public final class ZipZip
{
public static void main(final String... args)
throws IOException
{
final Map<String, Object> env = new HashMap<>();
env.put("create", "true");
final URI zip = URI.create("jar:file:/tmp/t.zip");
final Path sourceFile = Paths.get("/tmp/foo.txt");
Files.deleteIfExists(Paths.get("/tmp/t.zip"));
try (
final FileSystem fs = FileSystems.newFileSystem(zip, env, null);
) {
final Path zipdir = fs.getPath("/dir");
Files.createDirectory(zipdir);
final Path zipfile = zipdir.resolve("t.txt");
Files.copy(sourceFile, zipfile);
}
}
}
Then, I have recently written a FileVisitor to recursively copy a directory, which is used here; here is its code:
public final class CopyFileVisitor
implements FileVisitor<Path>
{
private final Path srcdir;
private final Path dstdir;
public CopyFileVisitor(final Path srcdir, final Path dstdir)
{
this.srcdir = srcdir.toAbsolutePath();
this.dstdir = dstdir.toAbsolutePath();
}
#Override
public FileVisitResult preVisitDirectory(final Path dir,
final BasicFileAttributes attrs)
throws IOException
{
Files.createDirectories(toDestination(dir));
return FileVisitResult.CONTINUE;
}
#Override
public FileVisitResult visitFile(final Path file,
final BasicFileAttributes attrs)
throws IOException
{
System.out.printf("%s -> %s\n", file.toAbsolutePath(),
toDestination(file));
Files.copy(file, toDestination(file));
return FileVisitResult.CONTINUE;
}
#Override
public FileVisitResult visitFileFailed(Path file, IOException exc)
throws IOException
{
throw exc;
}
#Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc)
throws IOException
{
if (exc != null)
throw exc;
return FileVisitResult.CONTINUE;
}
private Path toDestination(final Path victim)
{
final Path tmp = victim.toAbsolutePath();
final Path rel = srcdir.relativize(tmp);
return dstdir.resolve(rel.toString());
}
}
I strongly recommend you to use this library for zipping/unzipping contents:
http://www.lingala.net/zip4j/
Be sure you are adding correct headers while making the file.
i code a program that searches for files in hard disk successfully. but now i want to add one more capability to it. i want that my program will upload these searched file on to a server through http. so can anyone explain what will be the strategy for this?
Here is my little program
public class Find {
public static class Finder extends SimpleFileVisitor<Path> {
private final PathMatcher matcher;
private int numMatches = 0;
Finder(String pattern)
{
matcher = FileSystems.getDefault().getPathMatcher("glob:" + pattern);
}
// Compares the glob pattern against
// the file or directory name.
void find(Path file)
{
Path name = file.getFileName();
if (name != null && matcher.matches(name))
{
numMatches++;
System.out.println(file);
}
}
// Prints the total number of
// matches to standard out.
void done()
{
System.out.println("Matched: "
+ numMatches);
}
// Invoke the pattern matching
// method on each file.
//#Override
public FileVisitResult visitFile(Path file,
BasicFileAttributes attrs)
{
find(file);
return CONTINUE;
}
// Invoke the pattern matching
// method on each directory.
//#Override
public FileVisitResult preVisitDirectory(Path dir,
BasicFileAttributes attrs)
{
find(dir);
return CONTINUE;
}
//#Override
public FileVisitResult visitFileFailed(Path file,IOException exc)
{
System.err.println(exc);
return CONTINUE;
}
}
static void usage()
{
System.err.println("java Find <path>" +" -name \"<glob_pattern>\"");
System.exit(-1);
}
public static void main(String[] args)throws IOException
{
if (args.length < 1 )
{
usage();
}
Iterable<Path> root;
root = FileSystems.getDefault().getRootDirectories();
for (Path startingDir : FileSystems.getDefault().getRootDirectories())
{
String pattern = args[0];
Finder finder = new Finder(pattern);
Files.walkFileTree(startingDir, finder);
//finder.done();
}
}
}
OK, so assuming you've got an absolute filename of the File.
Just a rough idea of what should be done (not tested):
FileInputStream fileInputStream = null;
try {
new FileInputStream("absoluteFilename");
byte[] buffer = new byte[MAX_SIZE];
int bufferIndex = 0;
while (fileInputStream.available() > 0) {
buffer[bufferIndex++] = (byte) fileInputStream.read();
}
byte[] fileContent = new byte[bufferIndex];
System.arraycopy(buffer,0,fileContent,0,bufferIndex);
URL serverUrl = new URL(url);
URLConnection connection = serverURL.openConnection();
connection.setConnectTimeout(60000);
connection.getOutputStream().write(fileContent);
} catch (Exception fatal) {
//proper handling??
} finally {
if (fileInputStream != null) {
try {
fileInputStream.close();
} catch (Exception ignored) {}
}
}