How to get the root dir in Windows and Linux? - .net-core

I wrote a small software using .net6 which should run on Windows and Linux (Ubuntu). In this software I need to access a file in a folder.
Linux: /folder1/folder2/file.txt
Windows: d:\folder1\folder2\file.txt
The folder structure and the filename is the same on both systems.
This code works so far
string[] pfad;
pfad = new[] { "folder1", "folder2","file.txt" };
Console.WriteLine(System.IO.Path.Combine(pfad));
and delivers the correct folder structur under Linux and Windows.
How can I define the root directory?
/ in Linux and d:\ in Windows
Can I detect the OS type somehow or what is the best approach?
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); is "fix" under Windows to C:... - I want to use another drive.

Borrowing from stefan answer but using OperatingSystem class instead of RuntimeInformation (since OperatingSystem is part of System i believe it's preferable)
string rootPath;
if (OperatingSystem.IsWindows())
rootPath = #"d:\";
else if (OperatingSystem.IsLinux())
rootPath = "/";
else
{
// maybe throw an exception
}

You can use System.Runtime.InteropServices.RuntimeInformation like this:
string rootPath;
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
rootPath = #"d:\";
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
rootPath = "/";
}

Related

File path issue in mac

nopCommerce version: 4.1
I am using nopCommerce version 4.1 on mac os with visual studio for mac, when I run this solution, I get error on creating path.
Plugin 'Must be assigned to customer role'. Could not load file or
assembly
'/Users/alireza/Desktop/NopCommerce/Presentation/Nop.Web/Plugins\bin/Nop.Plugin.DiscountRules.CustomerRoles.dll'.
The system cannot find the file specified.\n\nCould not load file or
assembly
'/Users/alireza/Desktop/NopCommerce/Presentation/Nop.Web/Plugins\bin/Nop.Plugin.DiscountRules.CustomerRoles.dll'.
The system cannot find the file specified.\n\n
I found the solution by myself:
path = Environment.OSVersion.Platform == PlatformID.Win32NT
? path.Replace("~/", string.Empty).TrimStart('/').Replace('/', '\\')
: path.Replace("~/", string.Empty).TrimStart('/');
in the file opCommerce_4.10_Source/Libraries/Nop.Core/Infrastructure/NopFileProvider.cs
replace the the following function
public virtual string MapPath(string path)
with the following code :
public virtual string MapPath(string path)
{
// path = path.Replace("~/", string.Empty).TrimStart('/').Replace('/', '\\');
path = Environment.OSVersion.Platform == PlatformID.Win32NT
? path.Replace("~/", string.Empty).TrimStart('/').Replace('/', '\\')
: path.Replace("~/", string.Empty).TrimStart('/');
return Path.Combine(BaseDirectory ?? string.Empty, path);
}

Can't get the names of the files that exist in a specific directory using File or InputStream [duplicate]

I have a resources folder/package in the root of my project, I "don't" want to load a certain File. If I wanted to load a certain File, I would use class.getResourceAsStream and I would be fine!! What I actually want to do is to load a "Folder" within the resources folder, loop on the Files inside that Folder and get a Stream to each file and read in the content... Assume that the File names are not determined before runtime... What should I do? Is there a way to get a list of the files inside a Folder in your jar File?
Notice that the Jar file with the resources is the same jar file from which the code is being run...
Finally, I found the solution:
final String path = "sample/folder";
final File jarFile = new File(getClass().getProtectionDomain().getCodeSource().getLocation().getPath());
if(jarFile.isFile()) { // Run with JAR file
final JarFile jar = new JarFile(jarFile);
final Enumeration<JarEntry> entries = jar.entries(); //gives ALL entries in jar
while(entries.hasMoreElements()) {
final String name = entries.nextElement().getName();
if (name.startsWith(path + "/")) { //filter according to the path
System.out.println(name);
}
}
jar.close();
} else { // Run with IDE
final URL url = Launcher.class.getResource("/" + path);
if (url != null) {
try {
final File apps = new File(url.toURI());
for (File app : apps.listFiles()) {
System.out.println(app);
}
} catch (URISyntaxException ex) {
// never happens
}
}
}
The second block just work when you run the application on IDE (not with jar file), You can remove it if you don't like that.
Try the following.
Make the resource path "<PathRelativeToThisClassFile>/<ResourceDirectory>" E.g. if your class path is com.abc.package.MyClass and your resoure files are within src/com/abc/package/resources/:
URL url = MyClass.class.getResource("resources/");
if (url == null) {
// error - missing folder
} else {
File dir = new File(url.toURI());
for (File nextFile : dir.listFiles()) {
// Do something with nextFile
}
}
You can also use
URL url = MyClass.class.getResource("/com/abc/package/resources/");
The following code returns the wanted "folder" as Path regardless of if it is inside a jar or not.
private Path getFolderPath() throws URISyntaxException, IOException {
URI uri = getClass().getClassLoader().getResource("folder").toURI();
if ("jar".equals(uri.getScheme())) {
FileSystem fileSystem = FileSystems.newFileSystem(uri, Collections.emptyMap(), null);
return fileSystem.getPath("path/to/folder/inside/jar");
} else {
return Paths.get(uri);
}
}
Requires java 7+.
I know this is many years ago . But just for other people come across this topic.
What you could do is to use getResourceAsStream() method with the directory path, and the input Stream will have all the files name from that dir. After that you can concat the dir path with each file name and call getResourceAsStream for each file in a loop.
I had the same problem at hands while i was attempting to load some hadoop configurations from resources packed in the jar... on both the IDE and on jar (release version).
I found java.nio.file.DirectoryStream to work the best to iterate over directory contents over both local filesystem and jar.
String fooFolder = "/foo/folder";
....
ClassLoader classLoader = foofClass.class.getClassLoader();
try {
uri = classLoader.getResource(fooFolder).toURI();
} catch (URISyntaxException e) {
throw new FooException(e.getMessage());
} catch (NullPointerException e){
throw new FooException(e.getMessage());
}
if(uri == null){
throw new FooException("something is wrong directory or files missing");
}
/** i want to know if i am inside the jar or working on the IDE*/
if(uri.getScheme().contains("jar")){
/** jar case */
try{
URL jar = FooClass.class.getProtectionDomain().getCodeSource().getLocation();
//jar.toString() begins with file:
//i want to trim it out...
Path jarFile = Paths.get(jar.toString().substring("file:".length()));
FileSystem fs = FileSystems.newFileSystem(jarFile, null);
DirectoryStream<Path> directoryStream = Files.newDirectoryStream(fs.getPath(fooFolder));
for(Path p: directoryStream){
InputStream is = FooClass.class.getResourceAsStream(p.toString()) ;
performFooOverInputStream(is);
/** your logic here **/
}
}catch(IOException e) {
throw new FooException(e.getMessage());
}
}
else{
/** IDE case */
Path path = Paths.get(uri);
try {
DirectoryStream<Path> directoryStream = Files.newDirectoryStream(path);
for(Path p : directoryStream){
InputStream is = new FileInputStream(p.toFile());
performFooOverInputStream(is);
}
} catch (IOException _e) {
throw new FooException(_e.getMessage());
}
}
Another solution, you can do it using ResourceLoader like this:
import org.springframework.core.io.Resource;
import org.apache.commons.io.FileUtils;
#Autowire
private ResourceLoader resourceLoader;
...
Resource resource = resourceLoader.getResource("classpath:/path/to/you/dir");
File file = resource.getFile();
Iterator<File> fi = FileUtils.iterateFiles(file, null, true);
while(fi.hasNext()) {
load(fi.next())
}
If you are using Spring you can use org.springframework.core.io.support.PathMatchingResourcePatternResolver and deal with Resource objects rather than files. This works when running inside and outside of a Jar file.
PathMatchingResourcePatternResolver r = new PathMatchingResourcePatternResolver();
Resource[] resources = r.getResources("/myfolder/*");
Then you can access the data using getInputStream and the filename from getFilename.
Note that it will still fail if you try to use the getFile while running from a Jar.
As the other answers point out, once the resources are inside a jar file, things get really ugly. In our case, this solution:
https://stackoverflow.com/a/13227570/516188
works very well in the tests (since when the tests are run the code is not packed in a jar file), but doesn't work when the app actually runs normally. So what I've done is... I hardcode the list of the files in the app, but I have a test which reads the actual list from disk (can do it since that works in tests) and fails if the actual list doesn't match with the list the app returns.
That way I have simple code in my app (no tricks), and I'm sure I didn't forget to add a new entry in the list thanks to the test.
Below code gets .yaml files from a custom resource directory.
ClassLoader classLoader = this.getClass().getClassLoader();
URI uri = classLoader.getResource(directoryPath).toURI();
if("jar".equalsIgnoreCase(uri.getScheme())){
Pattern pattern = Pattern.compile("^.+" +"/classes/" + directoryPath + "/.+.yaml$");
log.debug("pattern {} ", pattern.pattern());
ApplicationHome home = new ApplicationHome(SomeApplication.class);
JarFile file = new JarFile(home.getSource());
Enumeration<JarEntry> jarEntries = file.entries() ;
while(jarEntries.hasMoreElements()){
JarEntry entry = jarEntries.nextElement();
Matcher matcher = pattern.matcher(entry.getName());
if(matcher.find()){
InputStream in =
file.getInputStream(entry);
//work on the stream
}
}
}else{
//When Spring boot application executed through Non-Jar strategy like through IDE or as a War.
String path = uri.getPath();
File[] files = new File(path).listFiles();
for(File file: files){
if(file != null){
try {
InputStream is = new FileInputStream(file);
//work on stream
} catch (Exception e) {
log.error("Exception while parsing file yaml file {} : {} " , file.getAbsolutePath(), e.getMessage());
}
}else{
log.warn("File Object is null while parsing yaml file");
}
}
}
Took me 2-3 days to get this working, in order to have the same url that work for both Jar or in local, the url (or path) needs to be a relative path from the repository root.
..meaning, the location of your file or folder from your src folder.
could be "/main/resources/your-folder/" or "/client/notes/somefile.md"
Whatever it is, in order for your JAR file to find it, the url must be a relative path from the repository root.
it must be "src/main/resources/your-folder/" or "src/client/notes/somefile.md"
Now you get the drill, and luckily for Intellij Idea users, you can get the correct path with a right-click on the folder or file -> copy Path/Reference.. -> Path From Repository Root (this is it)
Last, paste it and do your thing.
Simple ... use OSGi. In OSGi you can iterate over your Bundle's entries with findEntries and findPaths.
Inside my jar file I had a folder called Upload, this folder had three other text files inside it and I needed to have an exactly the same folder and files outside of the jar file, I used the code below:
URL inputUrl = getClass().getResource("/upload/blabla1.txt");
File dest1 = new File("upload/blabla1.txt");
FileUtils.copyURLToFile(inputUrl, dest1);
URL inputUrl2 = getClass().getResource("/upload/blabla2.txt");
File dest2 = new File("upload/blabla2.txt");
FileUtils.copyURLToFile(inputUrl2, dest2);
URL inputUrl3 = getClass().getResource("/upload/blabla3.txt");
File dest3 = new File("upload/Bblabla3.txt");
FileUtils.copyURLToFile(inputUrl3, dest3);

Qt Installer Framework Change Installation path and add subfolder

How to change the installer path and add subfolder using qt installer framework.
Default output:
C:\Program Files (x86)\Subfolder
I want to path to example output.
Example output:
D:\Subfolder
C:\Desktop\Subfolder
C:\Documents\Subfolder
I know this is old but maybe is usefull for someone.
I changed a Qt Installer Framework example called dynamicpage (look in QtIfw examples dir), where the target directory is selected from a custom widget called targetwidgetui. To avoid the user write directly in the line edit I added in my file config/controllerscript.qs this code:
Controller.prototype.TargetDirectoryPageCallback = function()
{
currentPage.TargetDirectoryLineEdit.enabled = false;
}
I also added #ApplicationsDir#/MyAppFolder in config.xml so this is the default install path.
When the user change the destination folder I take the path and append "/MyAppFolder". To do this I changed a function in the dynamicpage example, in file installscript.qs. This is how my function look like now:
Component.prototype.chooseTarget = function () {
var widget = gui.pageWidgetByObjectName("DynamicTargetWidget");
if (widget != null) {
var newTarget = QFileDialog.getExistingDirectory("Choose your target directory.", widget
.targetDirectory.text);
if (newTarget != "")
{
newTarget += "/MyAppFolder"; // The same subfolder of TargetDir in config.xml
widget.targetDirectory.text = Dir.toNativeSparator(newTarget);
}
}
}
Using this you will append always your folder to the installation path.
In your config.xml file you can add
<TargetDir>*YOUR_PATH*/subfolder</TargetDir>
To install to a custom directory.
From Qt Installer Framework documentation:
TargetDir
Default target directory for installation. On Linux, this is usually the user's home directory.
Note that you can use predefined variables like #ApplicationsDir# or #DesktopDir# as stated here.

Where is SQLite database stored in Windows phone 8.1

I have a SQLite database in my Windows phone 8.1 application. I am copying it by using this code
public async void UpDatabase()
{
bool isDatabaseExisting = false;
try
{
StorageFile storageFile = await ApplicationData.Current.LocalFolder.GetFileAsync("ComplainSys.db");
isDatabaseExisting = true;
}
catch
{
isDatabaseExisting = false;
}
if (!isDatabaseExisting)
{
StorageFile databaseFile = await Package.Current.InstalledLocation.GetFileAsync("ComplainSys.db");
await databaseFile.CopyAsync(ApplicationData.Current.LocalFolder);
}
}
I want to access that location where it is stored . When I put breakpoint and check that path and try to access that it shown this error.
How do I access that?
ApplicationData.Current.LocalFolder is the folder. But I don't really know how did you try to access the folder using the breakpoint, are you using Windows Explorer to open that folder? The path is local to phone storage, not your computer's one.
I use the other software, i think it's more good than isolated storage and don't need add external classes or same in your project... I used this: http://isostorespy.codeplex.com/downloads/get/835310
Just unzip folder and open your emulator, when emulator is opened, execute .exe and select your emulator, then u can explore local ,roaming and temp folder. Finally this software work with windows phone 8+ (8,8.1). It's too easy!
PD: If u had problems advise me, Good Luck!

Download Multiple Files from http using Powershell with proper names

I have searched for something similar and I keep running across the FTP download answers. This is helpful information, but ultimately proving to be difficult to translate. I have found a powershell script and it works, but I am wondering if it can be tweaked for my needs. I don't have much experience with powershell scripting, but I'm trying to learn.
The need is this. I need to download and install a series of files to a remote machine, unattended. The files are distributed via email via tinyurls. I currently throw those into a .txt file, then have a powershell script read the list and download each file.
Requirements of the project and why I have turned to powershell (and not other utilities), is that these are very specialized machines. The only tools available are ones that are baked into Windows 7 embedded.
The difficulties I run into are:
The files download one at the time. I would like to grab as many downloads at the same time that the web server will allow. (usually 6)
The current script creates file names based off the tinyurl. I need the actual file name from the webserver.
Thanks in advance for any suggestions.
Below is the script I’m currently using.
# Copyright (C) 2011 by David Wright (davidwright#digitalwindfire.com)
# All Rights Reserved.
# Redistribution and use in source and binary forms, with or without
# modification or permission, are permitted.
# Additional information available at http://www.digitalwindfire.com.
$folder = "d:\downloads\"
$userAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:7.0.1) Gecko/20100101 Firefox/7.0.1"
$web = New-Object System.Net.WebClient
$web.Headers.Add("user-agent", $userAgent)
Get-Content "d:\downloads\files.txt" |
Foreach-Object {
"Downloading " + $_
try {
$target = join-path $folder ([io.path]::getfilename($_))
$web.DownloadFile($_, $target)
} catch {
$_.Exception.Message
}
}
If you do the web request before you decide on file name you should be able to get the expanded path (otherwise you would have to make two web requests, one to get the extended path and one to download the file).
When I tried this, I found that the BaseResponse property of the Microsoft.PowerShell.Commands.HtmlWebResponseObject returned by the Invoke-WebRequest cmdlet had a ResponseUri property which was the extended path we are looking for.
If you get the correct response, just save the file using the name from the extended path, something like the following (this sample code does not look at HTTP response codes or similar, but expects everything to go well):
function Save-TinyUrlFile
{
PARAM (
$TinyUrl,
$DestinationFolder
)
$response = Invoke-WebRequest -Uri $TinyUrl
$filename = [System.IO.Path]::GetFileName($response.BaseResponse.ResponseUri.OriginalString)
$filepath = [System.IO.Path]::Combine($DestinationFolder, $filename)
try
{
$filestream = [System.IO.File]::Create($filepath)
$response.RawContentStream.WriteTo($filestream)
$filestream.Close()
}
finally
{
if ($filestream)
{
$filestream.Dispose();
}
}
}
This method could be called using something like the following, given that the $HOME\Documents\Temp folder exists:
Save-TinyUrlFile -TinyUrl http://tinyurl.com/ojt3lgz -DestinationFolder $HOME\Documents\Temp
On my computer, that saves a file called robots.txt, taken from a github repository, to my computer.
If you want to download many files at the same time, you could let PowerShell make this happen for you. Either use PowerShell workflows parallel functionality or simply start a Job for each url. Here's a sample on how you could do it using PowerShell Jobs:
Get-Content files.txt | Foreach {
Start-Job {
function Save-TinyUrlFile
{
PARAM (
$TinyUrl,
$DestinationFolder
)
$response = Invoke-WebRequest -Uri $TinyUrl
$filename = [System.IO.Path]::GetFileName($response.BaseResponse.ResponseUri.OriginalString)
$filepath = [System.IO.Path]::Combine($DestinationFolder, $filename)
try
{
$filestream = [System.IO.File]::Create($filepath)
$response.RawContentStream.WriteTo($filestream)
$filestream.Close()
}
finally
{
if ($filestream)
{
$filestream.Dispose();
}
}
}
Save-TinyUrlFile -TinyUrl $args[0] -DestinationFolder $args[1]
} -ArgumentList $_, "$HOME\documents\temp"
}

Resources