Forum Stats

  • 3,838,495 Users
  • 2,262,375 Discussions
  • 7,900,672 Comments

Discussions

copy files from one directory to another - more dynamic?

user2018218
user2018218 Member Posts: 5 Red Ribbon
edited Apr 16, 2018 5:59PM in Java Programming

Hey all, I have a product that I do multiple integration, implementation, installation, migrate,  etc... on. I am trying to streamline the process by writing a java method to copy files from one location to another.

Sounds simple enough, but let me explain a little.

I found some java code that does the basic file copies, and it works great.

However, the current code that I am using uses:

FileUtils.copyDirectory(srcDir, destDir);

Which takes in a File as it's parameters.

The issue that I have is that while the installation, implementation, etc... is pretty much the same, the OS's are not, along with the location of directories, file name, etc...

So What I did was create a global config file and class, which I love. It works great for what I need.

config.properties file:

domain=

envname=prod

hostname=

prodline=prod

prodline2

profile1=PRD

profile2=

server=

backup_dir=c:\\temp\\test\\TGTBackup

dst_dir=c:\\temp\\test\\persist

export_dir=c:\\temp\\test\\EnvExports

ldb_dir=c:\\temp\\test\\db

persist_dir=c:\\temp\\test\\persist

src_dir=c:\\temp\\test\\persist

sys_dir=c:\\temp\\test\\system

I have a config class:

public static class ImportCfg {

     private static Properties defaultProps = new Properties();

     static {

          try {

               FileInputStream in = new FileInputStream("config.properties");

               defaultProps.load(in);

               in.close();

          } catch (Exception e) {

          e.printStackTrace();

          }

     }

     public static String getProperty(String key) {

     return defaultProps.getProperty(key);

     }

}

So I put in the source, and target system information into my config.properties file for each OS, and when I compile the application it carries these global variable with it.

And in my methods, or main class I can put in stuff like this:

String backup_dir = ImportCfg.getProperty("backup_dir");

String export_dir = ImportCfg.getProperty("export_dir");

String src_dir = ImportCfg.getProperty("src_dir");

String dst_dir = ImportCfg.getProperty("dst_dir");

and pass it to my methods to make sure that it runs against the correct directory, etc...

Back to the copy files question.

I would like it to where I can pass in a String representation of the paths, but since it takes a File instead of String, I am trying to figure out how to do that.

Currently I have to call my String variable config like:

String dst_dir = ImportCfg.getProperty("dst_dir");

Then pass that to the File:

File destFolder = new File(dst_dir);

Then pass that to the method

ie.copyDirectory(srcFolder, destFolder);

What i would like to do is pass Strings like dst_dir, directly into the copyDirectory method?

It looks like it is done in Java 9, you can pass the parameters in as a string, but the customer that I have is only on Java 7, and doesn't have any plans to upgrade soon.

}

Answers

  • handat
    handat Member Posts: 4,688 Gold Crown
    edited Apr 3, 2018 7:35PM

    You already answered your own question, you need java9 which has the method signature you want and your currently used java7 does not. There isn't much you can do about that unless you write your own wrapper method or extend FileUtils and write your own overloaded implementation of copyDirectory with the method signature you want.

    But really, I don't see that you actually have a real problem. Also, you only need to compile your java code once and don't need to compile it for each OS. You just need to replace your properties file that you bundle with your compiled class.

    If your goal is just to get rid of the intermeditary destFolder, then you could just do this:

    ie.copyDirectory(srcFolder, new File(dst_dir));

  • Unknown
    edited Apr 3, 2018 8:06PM
    And in my methods, or main class I can put in stuff like this:String backup_dir = ImportCfg.getProperty("backup_dir");String export_dir = ImportCfg.getProperty("export_dir");String src_dir = ImportCfg.getProperty("src_dir");String dst_dir = ImportCfg.getProperty("dst_dir");and pass it to my methods to make sure that it runs against the correct directory, etc...

    And add appropriate exception handling?

    I would like it to where I can pass in a String representation of the paths, but since it takes a File instead of String, I am trying to figure out how to do that.

    Aw c'mon - you already know how to do that EASILY

    String src_dir = ImportCfg.getProperty("src_dir");String dst_dir = ImportCfg.getProperty("dst_dir");

    Those give you strings

    File file_src_dir = new File (ImportCfg.getProperty("src_dir"));File file_dst_dir = nw File (ImportCfg.getProperty("dst_dir"));

    And those give you File instances that you can pass to the existing method.

    It makes no sense to me at all why you would want to do something else that will require even more work.

    You are making a TERRIBLE mistake if you actually use the code you posted since it doesn't have ANY exception handling or checking of the values read from that config file.

    Any of my guys would break that code with the first unit test they used on it.

    The first test would be to execute your code WITHOUT a config file at all.

    The second test would be to provide one or more missing/invalid parameters in the config file.

    The STANDARD method of implementing parameter file use is to write MODULAR code. One module specialized for reading/writing config files.

    Another module, specific to the app, specialized for validating the values that are read/written. The second module would add the simple two additional internal parameters your app needs.

    Both modules would have proper exception handling.

    Do things the SIMPLE WAY and focus your efforts on writing modular, bulletproof code that is easy to understand and maintain.

  • user2018218
    user2018218 Member Posts: 5 Red Ribbon
    edited Apr 16, 2018 3:48PM

    Appreciate the feed back. Yes I plan on adding exception handling. I am just trying to see if it works right now.

    You know the old adage about putting the cart before the horse. I guess I could try and put in exception handling first?

  • user2018218
    user2018218 Member Posts: 5 Red Ribbon
    edited Apr 16, 2018 3:52PM

    I get what you are saying, but doing it is a different thing. I am taking data from an old system, and importing it into a new system.

    The old system only has java up to java 7, and refuses to upgrade that system because (well everything works in it as it), they don't want to introduce anything to it that could cause any issues later on down the road.

    So to recap, going from java 7 source,  to java 8+ target. The code I wrote is for the source system for now.

  • Unknown
    edited Apr 16, 2018 5:59PM
    You know the old adage about putting the cart before the horse.

    Aren't you already doing that by not defining the requirements first.

    Reread my reply and focus on the part where I said to write 'modular code'.

    As I just said in your other thread there is NO SUCH THING as platform independent code when it comes to working at the OS level.

    You need code/modules specific to the platform you are on. At app startup you determine the platform and then load singletons for the OS specific modules to be used.

    So What I did was create a global config file and class, which I love. It works great for what I need.

    That is a good example of code that is NOT modular or platform specific.

    Os's have DIFFERENT naming conventions for folders and files, different case sensitivity, different available commands, different parameters (often in different order) for those different commands.

    Create a separate config file for each platform. Create separate code that deals with that config file (audits/validates it, updates it, etc) and any os specific things.

    Use ALIASES for commands and parameter names and map those aliases as needed to the OS specific name.

    For example use something like 'DELETE_FILE' as the alias for a command that deletes a file. Then for each OS you can map that alias to 'del', 'delete' or whatever the correct command is for that OS.

    Yes I plan on adding exception handling.

    The problem with 'adding' it later is that you need to know what the actual requirements are BEFORE you start trying to define the architecture for the code itself. Some code may need a try-catch block around each statement - especially for os specific things.

    1. requirements first to map out WHAT needs to be done, WHAT order it needs to be done in and WHAT to do when problems happen

    2. write pseudo-code or stub out functions and methods BEFORE writing ANY code. That means if you need code to delete a file then:

    a. create a method - e.g. 'deleteFile'

    b. determine the parameters needed for that method - full path? file name? an instance of File?

    c. determine what exceptions or results are expected - what if the file doesn't exist? Is that ok or is that a problem because the file SHOULD exist? What if the file can't be deleted? Is that ok? Should an exception be raised?

    Should that exception be handled within the method? Or be thrown back to the caller?

    3. that stub code should have stubbed exception blocks as placeholders for the exceptions that might occur. Only if NO EXCEPTIONS are going to be handled by the method should the method NOT have an exception handler.

    So you do NOT add handlers later. You determine UP FRONT what code needs handlers and stub them in as placeholders.

    That makes it clear to other devs that may have to take over the code that a decision was made that an exception handler was needed.

    Experts, intermediates, beginners - all levels of developer work on projects/code.

    The expert should either be doing, or approving the architecture and requirements. At least an intermediate should be doing the stub work (and there should be standards in your org for what the stub needs to contain.

    Beginners work WITHIN the framework created by the experts and intermediates.

This discussion has been closed.