Simple question about File class in kotlin - kotlin

I'm trying to read from a file in kotlin using the File class. It's just a simple txt file with a list of names with each name occupying an independent row. This is my project structure:
and here's my function for pulling out a name depending on the day of the year:
private fun getNameOfTheDay(): String {
val cal = Calendar.getInstance()
val day = cal[Calendar.DATE]
return File("data${File.separator}names.txt")
.bufferedReader()
.lineSequence()
.elementAt(day - 1)
}
I keep on getting a FileNotFound exception so I would assume that my file path is somehow wrong... What am I doing wrong here? Sorry for the dumb question, I'm still learning. By the way the function shown above is called from the MainActivity. Thanks in Advance!

Filenames can be absolute or relative. Absolute filenames start from the top level (e.g. the root directory on Unix-like filesystems, which Macs have; or a drive letter on Windows), and so specify the filename unambiguously. Relative filenames don't, and so give a file in (or in relation to) the current working directory.
In this case, data/names.txt is a relative filename. It assumes that the current directory has a subdirectory called data, and refers to a file in that.
However, the file is actually in the directory app/src/main/java/com/example/mynameis/data/ within your project — so this would only work if the current directory was /<pathToYourProject>/app/src/main/java/com/example/mynameis/, which is highly unlikely! So that probably explains the failure.
I don't know about Android projects, but in normal JVM projects the standard practice is to put data files in a src/main/resources/ directory. Gradle (or Maven) knows to copy them into the classpath when building the project. You would then load it from the classpath, e.g. with:
javaClass.getResource("data/names.txt").readText()
See e.g. this question for more details and variations.
The advantage of loading from the classpath instead of a file path is that you don't need to know exactly where the file is; it could be loose on the filesystem, or bundled into a jar or other archive (even compressed), with ways to select between different versions depending on the run profile — all completely transparent to your code.
As I said, I don't know Android, and can't find any direct answers on StackOverflow. (This question seems to suggest using a android.resource:// URI, but I don't know if that would apply here.) Maybe these external sites can give you some hints.

You should try "data\names.txt". Oftentimes slashes don't work for file paths.

Related

Canonical way to map SourceFile class attribute to actual file system path

The SourceFile attribute only contains the file name, not a full or relative path. This is not much information to go with because javac will place the .class file in a potentially unrelated directory (relative to the -d argument), based on the package in which the class is declared. While this is required for finding and loading the class at run time, it makes the .class file location only a hint to where the .java file might be located in the source tree.
The documentation of the
com.sun.jdi.ReferenceType.sourcePaths(String) method suggests a heuristics to obtain a file system path:
In the reference implementation, for strata which do not explicitly specify source path (the Java programming language stratum never does), the returned strings are the sourceNames(String) prefixed by the package name of this ReferenceType converted to a platform dependent path.
There is no obvious way to do better than that. Of course, if the file does not exist at the expected location, one could search the source tree and check if the file name happens to be unique, and use that as the location. But beyond that, there are not many options.
Are there any other, non-obvious ways to solve this?

Can we make Spoon's output follow the same directory path as the original?

For now, Spoon's directory structure of output will follow the package path written in *.java file. In fact, there are many other files even *.java files, whose real file paths are different from package paths.
So, my Spoon's output folder was disordered.
In short the answer for this question is: no.
Spoon uses standard Java organization to process output files, meaning: each Java file is output in its package hierarchy as it should be done for source files (see: https://docs.oracle.com/javase/tutorial/java/package/managingfiles.html).
However if your problem is related to file created because of inner classes: you could solve it using the following option:
[--output-type ]
States how to print the processed source code:
nooutput|classes|compilationunits (default: classes)
with value "compilationunits".
Finally if it's really an issue for you, don't hesitate to propose a new feature through a pull request on the Github repository!

Get bytecode (.class files) from user-selected source items

I want my plugin (an automated termination analysis tool) to run on code the user selects inside Eclipse. Naturally, the user selects source code (a .java file, a method in the outline, ...). However, my program needs the compiled .class file(s) as input.
How can I get the .class files for selected source items? Related to this, how can I get a bytecode descriptor to the selected source method? In case of generics and varargs transforming a (Eclipse) source descriptor to the corresponding bytecode descriptor seems nontrivial to me.
I do not want to run javac on my own and I do not want to guess how the .class file is named (this is nasty for inner classes) and then try to find it on the disk (if it exists? maybe I can force Eclipse to compile?).
The Bytecode Outline plugin uses the following solution (see JdtUtils.getByteCodePath):
Based on the source element, find the output location, e.g. /home/user/workspace/project/build/)
Use the package information to find the right directory inside build/, e.g. /home/user/workspace/project/build/some/package/
Find the "outermost" class definition (important for inner classes), use this name as the file name of the .class file, e.g. /home/user/workspace/project/build/some/package/Foo.class
in case of an inner class, do weird magic (JdtUtils.getClassName) and modify the name of the resulting class file accordingly (maybe resulting in Foo$1.class)
So the problem of this question is solved, where the translation of inner classes to the corresponding file names could be improved. According to the author, though, the current approach (using "magic") works for "95% of the cases" and he does not know about any related bugs in the past few years.

Implement a self extracting archive?

I know i can use 7z or winrar but i want to learn this for myself.
How would i implement a self extracting archive? I can use C# or C++ but let me run down the problem.
When i open the exe i need some kind of GUI asking where to extract the files. Once the user says ok I should obviously extract them. I implemented a simple example in C# winforms already BUT my problem is HOW do i get the filenames and binary of the files into an exe?
One upon a time i ask Is it safe to add extra data to end of exe? and the answer suggested if i just add data to the end of the exe it may be picked up by a virus scanner. Now its pretty easy to write the length of the archive as the last 4bytes and just append the data to my generic exe and i do believe my process can read my own exe so this could work. But it feels hacky and i rather not have people accuse me of writing virus just because i am using this technique. Whats the proper way to implement this?
Note: I checked the self-extracting tag and many of the question is how to manipulate self extracting and not how to implement. Except this one which is asking something else Self-extracting self-checking executable
-edit- I made two self extracting with 7z and compared them. It looks like... well it IS the 7z.sfx file but with a regular 7z archive appended. So... there is nothing wrong with doing this? Is there a better way? I'm targeting windows and can use the C# compiler to help but i don't know how much extra work or how difficult it may be programmatically and maybe adding data to end of exe isnt bad?
It is possible. I used the following technique once, when we needed to distribute updates for the application, but the computers were configured so that the end user had no permissions to change application files. The update was supposed to log on to administrator account and update required files (so we came across identical problem: how to distribute many files as a single executable).
The solution were file resources in C#. All you need to do is:
Create a resource file in your C# project (file ending with .resx).
Add new resource of type "file". You can easily add existing files as byte[] resources.
In program you can simply extract resource as file:
System.IO.FileStream file = new System.IO.FileStream("C:\\PathToFile",
System.IO.FileMode.OpenOrCreate);
System.IO.BinaryWriter writer = new System.IO.BinaryWriter(file);
writer.Write(UpdateApplication.Data.DataValue, 0, UpdateApplication.Data.DataValue.Length);
(Here UpdateApplication.Data denotes binary resource).
Our solution lacked compression, but I believe this is easily achieved with libraries such as C#ZipLib.
I hope this solution is virus-scanner-safe, as this method creates complete, valid executable file.

bazaar merge questions2

in my previous question on how to avoid merging specific files i received an answer
see
Bazaar merge questions
the solution is running a resolve command that takes the .THIS files for specific files that i dont want to merge. (like *.hex, *.s19...)
My question is how i make resolve command to run on all the files in all directories without making batch file that contains all the directoreis names. (what will work but needs modifications every project)
P.S i know what * is stand for , what is the meaning of ** ?
thanks
If I understand correctly, it means "subtree". In other words, subdirectories and their subdirectories, and their subdirectories, etc. So, "*/.hex" would match all files with the "hex" extension in the current directory and anywhere in the subtree under that.