file copy in scala play - scala

i am to copy a file in scala But getting FileNotFound error, The assets folder is in the same directory where is src:
val src = new File("/assets/public/images/default/male.jpg")
val dest = new File("/assets/public/images/profile/male1.jpg")
new FileOutputStream(dest) getChannel() transferFrom(
new FileInputStream(src) getChannel, 0, Long.MaxValue )

In your code you are trying to copy the file using FileOutputStream, which requires a valid path to the existing file else it'll throw FileNotFoundException. (see the doc here)
val src = new File("/assets/public/images/default/male.jpg")
val dest = new File("/assets/public/images/profile/male1.jpg")
new FileOutputStream(dest) //dest should exist
Nevertheless, Play has its own utility to copy files. Here is the link.
import play.api.libs.Files
Files.copyFile(src, dest, true, true)
println(dest.getAbsolutePath()) // filepath of copied file
Also, since the files get copied to the working directory, you might not be able to see the new file in the folder structure of your favorite IDE.
Aside, you may get the path for public assets by using routes
val srcPath = routes.Assets.at("public/images/default/male.jpg").url

A general advise
When copying files on Java, use the FileUtils.copy(...) from the Apache commons project.
For your specific problem
You get "File not found" if the file cannot be found by the running process. This could be because your file is indeed not there or because the process is lacking rights to see the file.

Your wording is a little ambiguous, it seems you meant to give paths relative to the current working directory. That means that this code should be executed from a directory which contains the assets directory. If this is so, then you have made a mistake and given absolute paths to your file objects, not relative ones. All you have to do is remove the initial forward slash from those paths and it should work.
As it is, you are telling Scala/Java to look in the root directory for assets.

Related

scala issue with reading file from resources directory

I wrote something like this to read file from resource directory:
val filePath = MyClass.getClass.getResource("/myFile.csv")
val file = filePath.getFile
println(file)
CSVReader.open(file)
and the result I got was something like this:
file:/path/to/project/my_module/src/main/resources/my_module-assembly-0.1.jar!/myFile.csv
Exception in thread "main" java.io.FileNotFoundException: file:/path/to/project/my_module/src/main/resources/my_module-assembly-0.1.jar!/myFile.csv (No such file or directory)
Whereas, if I run the same code in IDE(Intellij), no issues and the path printed to console is:
/path/to/project/my_module/target/scala-2.11/classes/myFile.csv
FYI, its a multi build project with a couple of modules and I build the jars using sbt assembly
This is more related to Java or the JVM itself than to Scala or SBT.
There is a difference when running your application from the IDE vs the command line (or outside the IDE). The method getClass.getResource(...) attempts to find the resource URL in the current classpath, and that's the key difference.
If you look at the URL itself, you will find that in the first case you have a my_module-assembly-0.1.jar! bit in it, meaning that URL is actually pointing towards the contents of the JAR, not to a file accessible from the file system.
From inside your IDE your class path will include the actual files on disk, from the source folders, because the IDE assumes that there is not any JAR file itself. So when obtaining the URL given by getClass.getResource(...) you have an URL that does not have the my_module-assembly-0.1.jar! bit in it.
Since you want to read the contents of the file, you may want to do a getClass.getResourceAsStream(...). That will give you an InputStream that you can use to read the contents regardless you are in the IDE or anywhere else.
Your CSVReader class may have a method that allows it read the data from an InputStream or a Reader or something similar.
EDIT: As pointed out by Luis Miguel Mejia Suarez, a more Scala idiomatic way of reading files from your class path is using the Source.fromResource method. This will return a BufferedSource that then can be used to read the file contents.

After creating a File, how do I make sure it getting downloaded to the default download folder?

I'm trying out #tototoshi's scala-csv library and its very simple, looks like this:
def downloadFile = Action {
val f = new File("out.csv")
val writer = CSVWriter.open(f)
writer.writeAll(List(List("a", "b", "c"), List("d", "e", "f")))
writer.close()
Ok.sendFile(f, inline = false, _ => f.getName)
}
but now I the file is getting download to my project directory:
and I want it to get downloaded to the default download folder of whoever use this func, how can I do this?
the file is getting download to my project directory
This has nothing to do with Scala or with scala-csv, it's just the way new File(String) constructor works: if you pass a relative path like "out.csv" (or more generally, "directory/directory/..."), it uses the working directory, which is set by the "run configuration" when running in IDEA. Use an absolute path ("C:/directory/..." on Windows or "/directory/..." on Linux/Mac) instead.
to the default download folder
There is no built-in way to find default download folder in Java, it depends on the OS. See General Path To Downloads Folder for an answer for Windows.
You'll need to resolve the download folder yourself. The library will, given a path, write a CSV to that path. It'll include other CSV facilities, but definitely not path resolving code.
To the best of my knowledge, there's no one environment variable that will point to default "Downloads" directories...
If you're on *nix, typically downloads are in ~/Downloads, so your path will be "~/Downloads".replace("~", System.getProperty("user.home")). This can then be passed into java.io.File's constructor.
I don't know Windows' filesystem well enough to tell you if this will work for Windows as well, but a cursory search suggests it should work, too.

Scala io.Source.fromfile not finding my file even with absolute path specified

I am trying to access a file in Scala using io.Source.fromfile.
I have specified the full path, but i am still getting a no such directory or file error.
This is a general version of what my code looks like:
val lines = io.Source.fromFile("~/top/next/source/resources/desiredFile.txt").getLines()
I'm running Ubuntu if that makes any difference.
It probably because you are using tilde sign, use full absolute path.
If you want to avoid hard coding your home directory, you can get it from environment variables:
val home = System.getProperty("user.home")
val s = Source.fromFile(s"${home}/.....").getLines()
The compiler was assuming it should start in the project folder I was already in, so when I specified the directories above that folder, it tried to find them all as a sub-directory of my root project folder.
This would obviously cause an error.
I now have:
val lines = io.Source.fromFile("source/resources/desiredFile.txt")
which is working properly

Create a File in src directory of Eclipse plugin

I want to create a file in the current directory of eclipse plugin.
I tried to create the file using :
File file = new File("filename.txt");
But, it is not working.
EDIT: I want to create the file in the same directory as that of "src" folder
Are you trying to create empty file within the pproject dir tree? or you want to create new file programatically? If you want to create empy file, go to File>New>Empty file (or similar, I do not have eclipse installed, Im writing out of memory), and if programatically: you have written line that initializes file at given path (if file cannot be initialized (no such file, or similar) - this will throw an exeption), but does not create it. To create file you need to write second instruction, just like:
file.create();
If the location (inside your project) is correct, then simply do this (not including try catch etc):
File test = new File("test.txt");
test.createNewFile();

Reading files from directory in Play framework on Heroku

I have a directory with deep structure (lot of sub-directories and files) that I read from my play application. On my PC I read the directory using -
val directory = Play.getFile("directory")
for(file <- directory.listFiles) {
val lines = Source.fromFile(file).getLines()
}
This works perfectly on my PC but not on Heroku. On Heroku I get a NPE on line#2 (above code) which means that the directory object is not getting made.
This suggestion of a similar issue suggests that I could put my directory in public and read it as using the Play.resource API. But I DONT want to put my directory in public. And I have a need to list the contents of a directory as it could be changing... how can I do this in Play on Heroku?
As this suggests,in order to make Play.getFile("location_from_project_root") (or any other similar one) working in production environment, you have to explicitly ask from play to add the directory where you put the file ,to the dist.
Ex:
You want to access a file Project_Root/resources/mtFile.json, (inside /resources folder you created), you can use Play.getFile("/resources/mtFile.json")method.
But in order to make it works in any production environment, you have to add /resources folder to the dist. Otherwise that file will not be there. In order to do that you have to add these lines into your build.sbt file.
import com.typesafe.sbt.packager.MappingsHelper._
mappings in Universal ++= directory(baseDirectory.value / "resources")
Now, if you take a dist using activator dist command you can see that a directory called /resources has added into the root of the dist. Now Play.getFile("/resources/mtFile.json") should work in production environment.
Play.getFile(relativePath) retrieves a file relative to the current app's root path. Current app's root path may not be same on your PC and Heroku.
One more thing: Your statement that the directory object is not getting made is not true. listFiles operation is throwing NPE in your case.
Try this to get a list of files from your directory:
val listOfFilesInDirectory: List[java.io.File] = Option(getClass.getResource("/directory")).map(_.toURI).map(new java.io.File(_)).map(_.listFiles).flatten.toList
You can put your files under your conf folder, so that the files are not publicly available. Then use :
Play.resource("conf/directory"): Option[URL]
or
Play.resourceAsStream("conf/directory"): Option[InputStream]