FileOutputStream throw FileNotFoundException when get File with Japanese in path - spring-boot

When using Google Drive API, I'm having this downloadMetadataFile() here to handle file:
public void downloadMetadataFile(String fileId, String folderStorePath, String fileName) throws IOException, GeneralSecurityException, GoogleException {
String path = folderStorePath + "/" + fileName
java.io.File file = new java.io.File(path);
try (FileOutputStream fileOutputStream = new FileOutputStream(file)) {
Drive drive = createDrive();
drive.files().get(fileId)
.executeMediaAndDownloadTo(fileOutputStream);
}
}
When using above method with folder exists (izakayaTemplate + 居酒屋):
When path=/reports/template/izakayaTemplate/template3.png, the method working file and download template3.png successful from Google Drive
When path=/reports/template/居酒屋/template3.png, the method throw a FileNotFoundException at line try (FileOutputStream fileOutputStream = new FileOutputStream(file))
Can somebody please explain for me about this behavior?
Note:
I'm using SpringBoot 2.5, Java 8, Drive API v3
I'm running this project on Amazon linux 1 as a service by DaemonTool.
In the run config file, I have set
-Dfile.encoding=UTF-8
-Dsun.jnu.encoding=UTF-8 -Dfile.encoding=UTF-8 \
Update 1:
After debug for a while, I found out that the CanonicalPath is wrong for the new file I create but I don't know why it happen.
getPath: /reports/template/居酒屋/template3.png
getAbsolutePath: /reports/template/居酒屋/template3.png
getCanonicalPath: /reports/template/???/template3.png

After searching, I have found the solution for this problem:
Solution: Add export LANG=ja_JP.UTF-8 to the file run
Explanation: canonicalPath is the path file system considers the canonical means to reference the file system object to which it points. So in order for the system to get the canonicalPath to be correct, the environment must have set up correct language environment like in this document: https://docs.oracle.com/cd/E23824_01/html/E26033/glset.html. In my question, the correct language environment is ja_JP.UTF-8

Related

How to save a PDF file downloaded as byte[] array obtained from a Rest WS

I trying to save a PDF file, previously obtained from a REST WS as byte[] array.
byte[] response = await caller.DownloadFile(url);
string documentPath = FileSystem.CacheDirectory;
string fileName = "downloadfile.pdf";
string path = Path.Combine(documentPath, fileName);
File.WriteAllBytes(path, response);
My actual implementation don't shows any errors but when I looking for the file on cache folder, nothing are there, just a empty folder. Also try put the file in FileSystem.AppDataDirectory and Environment.GetFolderPath(Environment.SpecialFolder.Personal) but there are no files in any folder
What I'm missing?
Thank's in advance.
string documentPath = FileSystem.CacheDirectory;
string fileName = "downloadfile.pdf";
string path = Path.Combine(documentPath, fileName);
the path will like
"/data/user/0/packagename/cache/downloadfile.pdf"
As you save it to Internal Storage,you couldn't see the files without root permission,if you want to view it,you could use adb tool (application signed by Android Debug)
adb shell
run-as packagename
cd /data/data/packagename
cd cache
ls
then you could see the downloadfile.pdf
or you could save it to External storage,then you could find it in your device File Manager:
//"/storage/emulated/0/Android/data/packagename/files/downloadfile.pdf"
string path = Android.App.Application.Context.GetExternalFilesDir(null).ToString();

Using SystemCommandTasklet to split file

I want to run System Commands via SystemCommandTasklet.Itried this with the sample code below but I get an error.
I think this because of command parameter,But I could not fix it.
I would be very glad if it will help.
Reference Examples ;
Using SystemCommandTasklet for split the large flat file into small files
Trying to split files using SystemCommandTasklet - Execution of system command did not finish within the timeout
Error Detail ;
"CreateProcess error=2, The system cannot find the file specified"
Code Sample ;
#Bean
#StepScope
public SystemCommandTasklet fileSplitterSystemCommandTasklet(#Value("#{jobParameters['file']}") File file) throws Exception {
final String fileSeparator = System.getProperty("file.separator");
String outputDirectory = file.getPath().substring(0, file.getPath().lastIndexOf(fileSeparator)) + fileSeparator + "out" + fileSeparator;
File output = new File(outputDirectory);
if (!output.exists()) {
output.mkdir();
}
final String command = String.format("split -a 5 -l 10000 %s %s",file.getName(),outputDirectory);
var fileSplitterTasklet = new SystemCommandTasklet();
fileSplitterTasklet.setCommand(command);
fileSplitterTasklet.setTimeout(60000L);
fileSplitterTasklet.setWorkingDirectory(outputDirectory);
fileSplitterTasklet.setTaskExecutor(new SimpleAsyncTaskExecutor());
fileSplitterTasklet.setSystemProcessExitCodeMapper(touchCodeMapper());
fileSplitterTasklet.afterPropertiesSet();
fileSplitterTasklet.setInterruptOnCancel(true);
fileSplitterTasklet.setEnvironmentParams(new String[]{
"JAVA_HOME=/java",
"BATCH_HOME=/Users/batch"});
return fileSplitterTasklet;
}
You need to use file.getAbsolutePath() instead of file.getPath().
Also, you are using file.getName() in the command:
final String command = String.format("split -a 5 -l 10000 %s %s",file.getName(),outputDirectory);
You should pass the absolute path of the file or make sure to set
the working directory correctly so that the split command is executed
in the same directory as the file.

How to use java program in bean pre-processor

The below program reads the XML file and compress into gzip.
I have a couple of questions here.
Can I use the following program directly in JMeter BeanShell pre-processor?
I want to use the output variable as input to JSON request. Is it possible in Jmeter?
Screen shot and details will be appreciated.
public static void main(String[] args) throws Exception {
String line = null;
String sb = "";
File f=new File("D:\\RetailTransactionLog_9419_001_590.xml");
FileReader fr=new FileReader(f);
BufferedReader br=new BufferedReader(fr);
while((line=br.readLine())!=null)
{
sb= sb + line;
}
br.close();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
GZIPOutputStream gzos = new GZIPOutputStream(baos);
gzos.write(sb.getBytes("UTF-8"));
gzos.close();
String base64CompressedString = Base64.getEncoder().encodeToString(baos.toByteArray());
System.out.println(base64CompressedString);
Of course, you can put your piece of java code directly in a JMeter BeanShell pre-processor and much more !
Insert you pre-processor component as child of your JSON request (as in my script example in attachment).
You don’t need to import java.io package like BufferedReader, ByteArrayOutputStream, File, FileReader, IOException, Base64…
Remove also the main signature public static void main(String[] args) …
You only have to import "java.util.zip.GZIPOutputStream" (A)
I’ve also replace your System.out.println(base64CompressedString) by log.info(base64CompressedString) just to visualize in the jmeter console your output (B)…
And finally add at the end, the code (C) to reference your result in the variable of your choice ("a" in my example).
You just have to call your variable after with ${a} in your json request like in my JMX script :
Unzip attachments http://uplea.com/dl/9F734367B43FB93 :
"ReadAndCompressMyFile.jmx" under /bin and put "test.xml" under C: or change the path in your code.
I’ve used a dummy sampler instead of your json request.
After running my script, you can see in View Result Tree (Request tab) and in the console, the value of "a" (corresponding to base64CompressedString).
PS : To run my script with the "dummy sampler", you need to add jmeter-plugins-dummy-0.1.jar under /lib/ext of your jmeter directory.
Hope to help you...
GZIP compression is rather "heavy" operation, if you will have lots of virtual users - it may become a bottleneck so consider using other approaches:
There is __base64Encode() function available via JMeter plugins
If for any reason it is not enough - go for JSR223 Sampler and Groovy language, Groovy is mostly compatible with Java so your code should work fine (just remove main method)

Insert into a local Sql Server CE don't insert

Hi I have A local database named Database1.sdf.
I´m accessing it with following code to insert some data into a table:
public string DoLocalDbCmd(string Command)
{
int NumeroAffetto;
string ConnString = #"Data Source=|DataDirectory|\Database1.sdf";
SqlCeConnection Conn = new SqlCeConnection(ConnString);
SqlCeCommand Comando = new SqlCeCommand(Command, Conn);
Comando.CommandType = System.Data.CommandType.Text;
try
{
Comando.Connection.Open();
NumeroAffetto = Comando.ExecuteNonQuery();
return NumeroAffetto.ToString();
}
catch (Exception ex)
{
return ex.Message;
}
finally
{
Comando.Connection.Close();
}
}
private void button1_Click(object sender, EventArgs e)
{
DoLocalDbCmd cmd = new DoLocalDbCmd();
string cmdex = cmd.RunSqlCmd("insert into TBL_PROVA (BELLO) VALUES ('VERO')");
MessageBox.Show(cmdex);
}
The execution of code happen without errors, I retrieve the number of affected row = 1.
But after if I query the database there is not inserted no row.
Somebody can suggest to me what can be wrong ?
Thankyou in advance
Piercarlo
It is a common scenario when these conditions are all or partially present in your project.
You have a connection string with the DataDirectory substitution
string.
You have a connection on the Server Explorer that point to an SDF
file located in your project directory.
You have the property Copy To Output Directory set to Copy Always
on your SDF file listed in your project items.
When you run the program inside the IDE of VS the SDF file present in your project folder is copied to the Output Directory (BIN\DEBUG) following the setting of Copy To Output Directory and this could result in the overwriting of the file eventually already present in BIN\DEBUG.
You run your code and insert correctly your data into the file in the BIN\DEBUG folder.
You stop your program and checks if the record is present using the Server Explorer and you don't see any new record because you are looking at the file in the Project Folder.
You start a new debug session and the file in the BIN\DEBUG is overwritten again with the empty one.
So... change the property Copy to the Output Directory to Copy Never to stop this copying, change the connection in the server explorer to point to your database in the BIN\DEBUG folder (Or add another one keeping the old one for schema changes and the new one to verify your DML operations)

Find absolute java.exe path programmatically from java code

If I have a java jar or class file which is launched by the user (assuming java path is set in environment variables), so how can i from within the code, figure out absolute path of java.exe/javaw.exe from which this file is being launched.
Like on ubuntu we can run: % which java and it shows the path.
However on windows, if i check System.getenv() it may happen that there are multiple path's found e.g for old or new version. If through cmd line, I run java -version it does not show the path.
Can you tell me either through pure java or command line on windows how is it possible to find out the location of javaw.exe?
String javaHome = System.getProperty("java.home");
Can you tell me either through pure Java ... on windows how is it possible to find out the location of javaw.exe?
E.G.
import java.io.File;
class JavawLocation {
public static void main(String[] args) {
String javaHome = System.getProperty("java.home");
File f = new File(javaHome);
f = new File(f, "bin");
f = new File(f, "javaw.exe");
System.out.println(f + " exists: " + f.exists());
}
}
Output
C:\Program Files (x86)\Java\jdk1.6.0_29\jre\bin\javaw.exe exists: true
Press any key to continue . . .
And yes, I am confident that will work in a JRE.
On Windows, the java.library.path System Property begins with the path to the bin directory containing whichever java.exe was used to run your jar file.
This makes sense, because on Windows the first place any executable looks for DLL files is the directory containing the executable itself. So naturally, when the JVM runs, the first place it looks for DLLs is the directory containing java.exe.
You can acquire the path to java.exe as follows:
final String javaLibraryPath = System.getProperty("java.library.path");
final File javaExeFile = new File(
javaLibraryPath.substring(0, javaLibraryPath.indexOf(';')) + "\\java.exe"
);
final String javaExePath =
javaExeFile.exists() ? javaExeFile.getAbsolutePath() : "java";
This code is Windows-specific - I hard-coded the path separator (;) and the file separator (). I also put in a fallback to just "java" in case the library path trick somehow doesn't work.
I have tested this with Java 6 and 7 on Windows 7. I tried a 32-bit and 64-bit version of Java.
Here's a slightly more generalised solution that I came up with. Maybe useful:
private static String javaExe()
{
final String JAVA_HOME = System.getProperty("java.home");
final File BIN = new File(JAVA_HOME, "bin");
File exe = new File(BIN, "java");
if (!exe.exists())
{
// We might be on Windows, which needs an exe extension
exe = new File(BIN, "java.exe");
}
if (exe.exists())
{
return exe.getAbsolutePath();
}
try
{
// Just try invoking java from the system path; this of course
// assumes "java[.exe]" is /actually/ Java
final String NAKED_JAVA = "java";
new ProcessBuilder(NAKED_JAVA).start();
return NAKED_JAVA;
}
catch (IOException e)
{
return null;
}
}
an issue with using "System.getProperty("java.home");", is that it is not always the java exe that the jar is running on, if you want to get that, you can use "System.getProperty("sun.boot.library.path");", from there you can find "java", "java.exe", "javaw", or "javaw.exe"... However there is still an issue with this, java will run just fine if the executable has been renamed, and the actual java executable's structure changes from different JRE's/JDKS's, so there is not much way to find the java exe if it has been renamed. unless someone else has a method ofc, in which case, can you share? :)
(Also, I have seen some people suggest using the first index of System.getProperty("java.library.path");, note, this might not work if the user/launcher has manually set the library path, something which is not too uncommon)
Compilation of All above methods
static String getJavaPath(){
String tmp1 = System.getProperty("java.home") + "\\bin\\java.exe";
String tmp2 = System.getProperty("sun.boot.library.path") + "\\java.exe";
String tmp3 = System.getProperty("java.library.path")+ "\\java.exe";
if(new File(tmp1).exists()) {
return tmp1;
}else if(new File(tmp2).exists()){
return tmp2;
}else if(new File(tmp3).exists()) {
return tmp3;
}else{
String[] paths = System.getenv("PATH").split(";");
for(String path:paths){
if(new File(path + "\\java.exe").exists()){
return path + "\\java.exe";
}
}
}
return "";
}

Resources