Can anyone tell me why this c# console command not running on Java?
I've made a C# console program as given below:
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
namespace face
{
class Program
{
public static void Main(string[] args)
{
String path = args[0];
byte[] imageBytes = File.ReadAllBytes(path);
MemoryStream ms = new MemoryStream(imageBytes, 0, imageBytes.Length);
// Convert byte[] to Image
ms.Write(imageBytes, 0, imageBytes.Length);
Image image = Image.FromStream(ms, true);
Bitmap S1 = new Bitmap(image);
Console.WriteLine(S1.GetPixel(2, 10));
}
}
}
When I run Program.exe image.jpg, I get:
Color [A=255, R=128, G=32, B=128]
Then I created a simple Java application to run the Program.exe executable:
class project
{
public static void main(String[] args)
{
String comman="C:\\WINXP\\system32\\Program.exe Sunset.jpg";
try
{
Process process = Runtime.getRuntime().exec(comman);
System.out.println(process.getOutputStream());
} catch (Exception e)
{e.printStackTrace(System.err);}
}
}
When I try to run the Java application, I get the following error:
Program.exe has encountered a problem and needs to close. We are sorry for the inconvenience.
You probably want to change
String comman = "C:\\WINXP\\system32\\Program.exe Sunset.jpg";
to
String[] comman = { "C:\\WINXP\\system32\\Program.exe", "Sunset.jpg" };
As a comment said, it's probably because the C# program can't open the file: you should specify an absolute path for it, since getting the actual working directory to work right can be an unnecessary pain in this situation. Also it wouldn't hurt to catch exceptions in the C# program (for example for the "no arguments" and "file not found" cases).
The C# process is a child process of the java process, and killed automatically then the java VM terminates. Because the process is started asynchronously, that will happen immediately. If you're interested in the output, replace
System.out.println(process.getOutputStream());
with (for instance)
InputStream inputStream = process.getInputStream();
int c;
while ((c = inputStream.read()) >= 0) {
System.out.print((char) c);
}
if not, write
process.getInputStream().close();
process.waitFor();
Apart from what others have said, I don't think that System.out.println(process.getOutputStream()); will output what you want here - namely the output of the executed C# executable.
System.out.println() has no overload for OutputStream, the return type of Process.getOutputStream(). So the System.out.println(Object) overload will be choosen, which will call OutputStream.ToString(), which is not the output of the C# program, but (most likely, bear with me here) the fully qualified typename of the output stream instance.
Check this SO question/answer, for example, for more information.
You need to check path of exe and image file that you have provided. As I check this code and execute it then I get following output
java.io.BufferedOutputStream#c17164
Here I provide you your modified code
public class Test
{
public static void main(String[] args)
{
String path="C:\\C#Sample\\ImageDisplayDemo\\ImageDisplayDemo\\bin\\Debug\\ImageDisplayDemo.exe E:\\Users\\Public\\Pictures\\Sample Pictures\\Desert.jpg";
try
{
Process proc=Runtime.getRuntime().exec(path);
System.out.println(proc.getOutputStream());
}
catch(Exception ex)
{
}
}
}
Related
I am using this code to compress files:
public class GzipCompressor : ICompressor
{
public void Compress(string input, string output)
{
using (FileStream originalFileStream = File.OpenRead(input))
using (FileStream compressedFileStream = File.OpenWrite(output))
using (GZipStream compressor = new GZipStream(compressedFileStream, CompressionMode.Compress))
originalFileStream.CopyTo(compressor);
}
}
The problem is that if someone closes the application while the file is compressing, the file will be saved to the destination path, but it will be invalid (it will not even be able to open it). Is there a way to avoid this? I would prefer such a file not to be created at all in such a situation.
You can try to use Application.ApplicationExit to perform logic when the application is attempting to close down. Keep in mind that there's still a chance something catastrophic is occurring and you wont be able to clean everything up (if the computer is forcibly shut down, there's not much you can do). The documentation also mentions the following got'cha:
Because this is a static event, you must detach any event handlers attached to this event in the ApplicationExit event handler itself. If you do not detach these handlers, they will remain attached to the event and continue to consume memory.
It can be solved by using GetTempFileName. I will provide an example based on your example.
private FileInfo? _tmpFileInfo;
public void Compress(string input, string output)
{
_tmpFileInfo = CreateTempFile();
using (FileStream originalFileStream = File.OpenRead(input))
using (FileStream compressedFileStream = File.OpenWrite(_tmpFileInfo!.FullName))
using (GZipStream compressor = new GZipStream(compressedFileStream, CompressionMode.Compress))
{
originalFileStream.CopyTo(compressor);
}
File.Copy(_tmpFileInfo.FullName, output);
File.Delete(_tmpFileInfo.FullName);
}
So basically what we do, is we create a temporary file and zip it to it, when it is done successfully, we copy it back to the output location. Here is CreateTempFile method:
public FileInfo? CreateTempFile()
{
var fileName = Path.GetTempFileName();
FileInfo? fileInfo = new FileInfo(fileName)
{
Attributes = FileAttributes.Temporary
};
return fileInfo;
}
That is it.
If you need to delete the temp file while the application makes an unhandled exception or process exists or other events, you can create an event like this:
public static void Main(string[] args)
{
AppDomain.CurrentDomain.ProcessExit += new EventHandler(GzipCompressor.ActionOnExit);
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(GzipCompressor.ActionOnExit);
var zip = new GzipCompressor();
zip.Compress(#"C:\temp\in\file1.txt", #"C:\temp\out\file1.txt.gz");
}
Then in your GzipCompressor class make FileInfo static.
private static FileInfo? _tmpFileInfo;
and create a static method to delete the temp file:
public static void ActionOnExit(object? sender, EventArgs e)
{
File.Delete(_tmpFileInfo.FullName);
}
There is, of course, no 100% guarantee that the temp file is deleted, let's say if you turn the computer forcibly by powering it off. The same scenario is valid while it is copying the file.
note: what regards the event in my answer, I tried it with a console app in dot net 6, but this should be cross-compatible with a dot net core, dot net framework, etc. read more about the AppDomian events.
I left the full answer on github: https://github.com/maythamfahmi/BlogExamples/tree/main/Stackoverflow/TempFiles
With std::filesystem::resize_file in C++, it is possible to change the size of a file without opening the file.
Is there any similar function in C#, which allows changing the size of a file without opening it?
I think opening a file as a FileStream and saving it again with a new size will be slower.
Using FileStream.SetLength() will be about as fast as you can make it.
It ends up calling the Windows API to set the length of the file, the same as the std::filesystem::resize_file().
So you just need to do something like this, and it will be fast enough:
using (var file = File.Open(myFilePath, FileMode.Open))
{
file.SetLength(myRequiredFileSize);
}
The implementation of FileStream.SetLength() is:
private void SetLengthCore(long value)
{
Contract.Assert(value >= 0, "value >= 0");
long origPos = _pos;
if (_exposedHandle)
VerifyOSHandlePosition();
if (_pos != value)
SeekCore(value, SeekOrigin.Begin);
if (!Win32Native.SetEndOfFile(_handle)) {
int hr = Marshal.GetLastWin32Error();
if (hr==__Error.ERROR_INVALID_PARAMETER)
throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_FileLengthTooBig"));
__Error.WinIOError(hr, String.Empty);
}
// Return file pointer to where it was before setting length
if (origPos != value) {
if (origPos < value)
SeekCore(origPos, SeekOrigin.Begin);
else
SeekCore(0, SeekOrigin.End);
}
}
(Note that SeekCore() just calls the the Windows API SetFilePointer() function.)
Doing this does NOT read the file into memory.
Also, the Windows API function SetEndOfFile() does not write to the extended region, so it is fast. The documentation states If the file is extended, the contents of the file between the old end of the file and the new end of the file are not defined. - this is as a result of data not being written to the extended region.
As test, I tried the following code:
using System;
using System.Diagnostics;
using System.IO;
namespace Demo
{
public class Program
{
public static void Main()
{
string filename = #"e:\tmp\test.bin";
File.WriteAllBytes(filename, new byte[0]); // Create empty file.
var sw = Stopwatch.StartNew();
using (var file = File.Open(filename, FileMode.Open))
{
file.SetLength(1024*1024*1024);
}
Console.WriteLine(sw.Elapsed);
}
}
}
My E:\ drive is a hard drive, not an SSD.
The output was: 00:00:00.0003574
So it took less than a hundreth of a second to extend the file to 1GB in size.
My application App is using other my application SubApp.
When App needs SubApp it is creating process with SubApp, putting data to SubApp stdin and reading from SubApp stdout.
The problem is that SubApp is using some library which sometimes writes to stdout.
Fragment of SubApp code:
OutsideLibrary.DoSomeInitialization(); // <-- this sometimes writes to stdout
Stream input = Console.OpenStandardInput();
Stream output = Console.OpenStandardOutput();
data = (dataFormat)formatter.Deserialize(input);
//do some job
formatter.Serialize(output, result);
Is there any way to prevent code I don't have from writing to stdout?
Assuming you want to disable third party component output and you have control over the rest of SubApp code you can do following trick: Redirect standard output to null at application bootstrap. When you need to write something to stdout temporary set standard output back to normal, write and set to null again.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace stdio
{
class Program
{
static void Main(string[] args)
{
Console.SetOut(System.IO.TextWriter.Null);
Console.WriteLine("This will go to > null");
WriteOutput("This is written to standard output");
Console.WriteLine("This will also go to > null");
Console.ReadKey();
}
static void WriteOutput(String someString)
{
Console.SetOut(Console.Out);
Stream output = Console.OpenStandardOutput();
StreamWriter sw = new StreamWriter(output);
sw.Write(someString);
sw.Flush();
sw.Close();
output.Close();
Console.SetOut(System.IO.TextWriter.Null);
}
}
}
I've tried this:
StreamWriter sw = new StreamWriter(#"c:\nul");
Console.SetOut(sw);
Console.WriteLine("hello!");
But it throws an exception in new StreamWriter().
The following might work (call it before your external module becomes active):
StreamWriter sw = new StreamWriter(Stream.Null);
Console.SetOut(sw);
A workaround would be to open a real text file and delete it.
Im trying to decompress a bz2 file via code using the ICSharpCode.SharpZipLib.
It seems no matter where I make my file, even though I have FULL ACCESS control over it, I keep getting this Exception. Any help greatly appreciated.
using System;
using System.IO;
using ICSharpCode.SharpZipLib.BZip2;
namespace decompressor
{
class MainClass
{
public static void Main(string[] args)
{
string filePath = "C:\\FreeBase\\opinions.tsv.bz2";
string decompressPath = "C:\\Users\\mike\\Desktop\\Decompressed";
Console.WriteLine("Decompressing {0} to {1}", file, path);
BZip2.Decompress(File.OpenRead(filePath),File.OpenWrite(decompressPath), true);
}
}
}
Your code can have no access to create new paths at your desktop.
Check the permissions for the "C:\\Users\\mike\\Desktop\\Decompressed".
Maybe, you should write so:
string decompressPath = "C:\\Users\\mike\\Desktop\\Decompressed\\opinions.tsv";
Does anyone know of a way to (reasonably simple) create a file without actually opening/locking it? In File class, the methods for file creation always return a FileStream. What I want to do is to create a file, rename it (with File.Move) and then use it.
Now I have to:
Create it
Close
Rename
Reopen for use
Maybe you can try using File.WriteAllText Method (String, String)
with the file name and an empty string.
Creates a new file, writes the
specified string to the file, and then
closes the file. If the target file
already exists, it is overwritten.
using (File.Create(...)) { }
While this will briefly open your file (but close it again right away), the code should look quite unobtrusive.
Even if you did some P/Invoke call to a Win32 API function, you would get a file handle. I don't think there's a way to silently create a file without having it open right afterwards.
I think the real issue here is why you go about creating your file in the way you've planned. Creating a file in one place simply to move it to another location doesn't seem very efficient. Is there a particular reason for it?
What about using File.WriteAllBytes method?
// Summary:
// Creates a new file, writes the specified byte array to the file, and then
// closes the file. If the target file already exists, it is overwritten.
Another way is to use FileStream and Close it after creating the file. It will not lock the file. The code will look like:
FileStream fs = new FileStream(filePath, FileMode.Create);
fs.Flush(true);
fs.Close();
You just after this you can rename it as well or move it some other location.
Below is the Test program to test functionality.
using System;
using System.Collections.Generic;
using System.IO; using
System.Linq;
using System.Text;
namespace FileLocking {
class Program
{
static void Main(string[] args)
{
string str = #"C:\Test\TestFileLocking.Processing";
FileIOTest obj = new FileIOTest();
obj.CreateFile(str);
}
}
class FileIOTest
{
internal void CreateFile(string filePath)
{
try
{
//File.Create(filePath);
FileStream fs = new FileStream(filePath, FileMode.Create);
fs.Flush(true);
fs.Close();
TryToAccessFile(filePath);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
void TryToAccessFile(string filePath)
{
try
{
string newFile = Path.ChangeExtension(filePath, ".locked");
File.Move(filePath, newFile);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
} }
If you use File.Create(commented in above code) then it will give error saying file is being used by another process.
Incredibly grotty hack, probably the most complicated way to achieve your goal:
use Process class
processInfo = new ProcessStartInfo("cmd.exe", "/C " + Command);
processInfo.CreateNoWindow = true;
processInfo.UseShellExecute = false;
process = process.Start(processInfo);
process.WaitForExit();
where Command would be echo 2>> yourfile.txt