I'm working with an API that produces images in BMP or JPG format. The API method in question requires a path and filename. However, in some cases, I would like to simply put the image into the Clipboard.
I know I can save to a file, then open the file and copy the Stream's data to the Clipboard:
private void SaveSnapshot(string path)
{
var pathWasblank = path.IsNullOrBlank();
path = path.NullIfBlank() ?? Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyPictures),"tempFile.jpg");
myApiInstance.ExportJPG(path, 100, true);
//to ensure the file has made it to the filesystem
while(!File.Exists(path)) Thread.Sleep(100);
if (pathWasblank) //it should be on the Clipboard and not in a file
{
using (var stream = File.OpenRead(path))
Clipboard.SetImage(Image.FromStream(stream));
File.Delete(path); //cleanup;
}
}
What I want to know is if there is a way to skip having to reopen, copy and then delete the file, and instead "save" directly to the Clipboard by specifying some file path that corresponds to the Clipboard. If not, no big deal; I have a working solution.
Related
I am trying to copy data of one file and pasting it into the same file which means overwriting it. I learn that overwrite the file data using file.copy() cannot be possible. but from the one of the post says that if I use File.Copy(Source file, destination file, true) than overwrite is possible. I tried to use but it didn't work. if anyone have solution for that than it will be big help.
public void EditRole(string oldRole, string newRole)
{
if (File.Exists(roleXMLLoc))
{
XDocument doc = XDocument.Load(roleXMLLoc);
var edit = doc.Element("Roles").Elements("Role").Where(x => x.Value == oldRole).SingleOrDefault();
edit.Value = newRole;
doc.Save(roleXMLLoc);
if (File.Exists(userPermissionLoc))
{
File.Copy(userPermissionLoc, userPermissionLoc, true); SaveData();
}
}
}
To read or write files you should open a Stream (https://learn.microsoft.com/en-us/dotnet/standard/io/). If you need to read and write in the same time, then you should use 2 separate streams for reading and writing into 2 separate files. Operating system will protect file from being opened by 2nd stream, otherwise you would fall into problems of concurrency: you read the inactual data that is already being changed by writing stream.
The logic can be:
Read file and close Reading stream. Then open file for writing and do what you need.
OR
Open Reading stream for fileToRead.xml and open Writing stream for temporary fileToWrite.xml. After you done, you can close both streams, remove the source file and rename the new file.
I have a compressed file (.osz) stored on an S3 Bucket which contains a .os file which I need to read the contents of.
I need to be able to extract/decompress and read the contents of the compressed file without downloading the file directly to the PC due to security reasons.
I am able to retrieve the compressed file (.osz) using the URL address of it's S3 Bucket path. Then using ZipArchive I am able to access the files contained within the compressed file. I am then able to extract the file I require by using the 'ExtractToFile' function as seen below. However, this function extracts the file (.os) and saves it locally in the path specified.
WebClient client = new WebClient();
byte[] bytes = client.DownloadData(OSZFilepath); // Read the .osz file contents into a byte array
using (MemoryStream zipStream = new MemoryStream(bytes))
{
// Create the zip containing the file from the stream
ZipArchive zip = new ZipArchive(zipStream);
// extract the compressed file and download the .os file contained within
var fileName = Guid.NewGuid().ToString() + ".OS";
var baseDirectory = Environment.ExpandEnvironmentVariables(System.Web.Configuration.WebConfigurationManager.AppSettings["DataStorage"].ToString());
zip.Entries[0].ExtractToFile(Path.Combine(baseDirectory, "ProjectFiles", fileName));
Although this extracted file can be successfully read and imported by my program, I cannot use this method as I am not able to save the file onto the user's computer due to security restrictions and program requirements.
Therefore I need to programmatically extract/decompress the file I need in order to read the contents and programmatically import it into my program.
I have tried to use the following code to do this:
ZipArchiveEntry entry = zip.GetEntry(zip.Entries[0].Name);
Stream stream = entry.Open();
StreamReader reader = new StreamReader(stream);
string contents = reader.ReadToEnd();
However the resulting contents throws up an error when I try to import it, indicating that the contents is different to the contents of the file that gets saved using 'ExtractToFile'.
This is confirmed when I save this contents as a seperate file and compare it to the file saved using 'ExtractToFile'. The 'ExtractToFile' file is bigger than the latter.
So my question is: is there another way to successfully decompress/extract a compressed file and obtain the contents without using the 'ExtractToFile' method and having to save the extracted file somewhere?
Thanks for your help.
I've had 3 reports now of user's machines crashing while using my software.. the crashes are not related to my program but when they restart the config files my program writes are all corrupt.
There is nothing special to how the files are being written, simply creating a Json representation and dumping it to disk using File.WriteAllText()
// save our contents to the disk
string json = JsonConvert.SerializeObject(objectInfo, Formatting.Indented);
// write the contents
File.WriteAllText(path, json);
I've had a user send me one of the files and the length looks about right (~3kb) but the contents are all 0x00.
According to the post below File.WriteAllText should close the file handle, flushing any unwritten contents to the disk:
In my C# code does the computer wait until output is complete before moving on?
BUT, as pointed out by Alberto in the comments:
System.IO.File.WriteAllText when completes, will flush all the text to
the filesystem cache, then, it will be lazily written to the drive.
So I presume what is happening here is that the file is being cleared and initialized with 0x00 but the data is not yet written when the system crashes.
I was thinking of maybe using some sort of temp file so the process would be like this:
Write new contents to temp file
Delete original file
Rename temp file to original
I don't think that will solve the problem as I presume Windows will just move the file even though the IO is still pending.
Is there any way I can force the machine to dump that data to disk instead of it deciding when to do it or perhaps a better way to update a file?
UPDATE:
Based on suggestions by #usr, #mikez and #llya luzyanin I've created a new WriteAllText function that performs the write using the following logic:
Create a temp file with the new contents using the FileOptions.WriteThrough flag
Writes the data to disk (won't return until the write has completed)
File.Replace to copy the contents of the new temp file to the real file, making a backup
With that logic, if the final file fails to load, my code an check for a backup file and load that instead
Here is the code:
public static void WriteAllTextWithBackup(string path, string contents)
{
// generate a temp filename
var tempPath = Path.GetTempFileName();
// create the backup name
var backup = path + ".backup";
// delete any existing backups
if (File.Exists(backup))
File.Delete(backup);
// get the bytes
var data = Encoding.UTF8.GetBytes(contents);
// write the data to a temp file
using (var tempFile = File.Create(tempPath, 4096, FileOptions.WriteThrough))
tempFile.Write(data, 0, data.Length);
// replace the contents
File.Replace(tempPath, path, backup);
}
You can use FileStream.Flush to force the data to disk. Write to a temp file and use File.Replace to atomically replace the target file.
I believe this is guaranteed to work. File systems give weak guarantees. These guarantees are hardly ever documented and they are complex.
Alternatively, you can use Transactional NTFS if available. It is available for .NET.
FileOptions.WriteThrough can replace Flush but you still need the temp file if your data can exceed a single cluster in size.
I have been trying to make sense of this http://msdn.microsoft.com/en-us/library/sfezx97z.aspx which uses the SaveFileDialog, but it is hard for me to understand. I have the following code:
FileInfo existingFile = new FileInfo("C:\\Users\\cle1394\\Desktop\\Apple Foreign Tax Payment Sample Layout Proposed - Sample Data.xlsx");
ConsoleApplication2.Program.ExcelData data = ConsoleApplication2.Program.GetExcelData(existingFile);
var json = new JavaScriptSerializer().Serialize(data);
How can I output the contents of json to a .json or .txt file?
I would like to let the user either see a link/ button to click to download/ save the file to a location on their computer, or, simply display the save file dialog box so that they can save the file to a location on their computer.
EDIT (to let OP comment on what parts are not clear):
SaveFileDialog saveFileDialog1 = new SaveFileDialog();
saveFileDialog1.ShowDialog();
if(saveFileDialog1.FileName != "")
{
File.WriteAllText(saveFileDialog1.FileName,json);
}
You are looking for this, then:
File.WriteAllText(#"c:\some\path\json.txt",json);
And note that it will save the file using UTF8-encoding without a Byte Order Mark. If you need the BOM, you need to use the File.WriteAllText(path, content, Enconding);
See here.
Update - adding sample with SaveFileDialog:
if(!string.IsNullOrEmpty(saveFileDialog.FileName))
{
//saveFileDialog.FileName should contain the full path
//according to the documentation: http://msdn.microsoft.com/en-us/library/system.windows.forms.filedialog.filename.aspx
File.WriteAllText(saveFileDialog.FileName,json);
}
Hello I am trying to save a bitmap image in a basic image editor program.
Here's the code:
// then save it
ImageBoxInApp.Image.Save(filename);
[EDIT] And I am opening the image with this
openFileDialog1.Title = "Select an Image";
openFileDialog1.Filter = "All Files|*.*|Windows Bitmaps|*.bmp|JPEG Files|*.jpg";
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
filename = openFileDialog1.FileName;
Image img = System.Drawing.Image.FromFile(filename);
So when I try this I receive a Generic GDI+ error. So I found a solution to this and it looks like this:
// Delete existing file first
System.IO.File.Delete(filename);
// then save it
ImageBoxInApp.Image.Save(filename);
But when I try to do this I receive another error saying that the file I am deleting is currently open. This is because that is the file that I am trying to edit.
How do I "close" the file without actually closing the application? Or is there an alternative solution?
Thanks!
Its hard to say without seeing some context around how your loading the file, but here are a couple of suggestions:
Before saving, copy the existing image into a new Image, close the original, perform the delete, and save the copy.
Save the file to a random filename, delete the original, rename the randomly named file to the original name.
Load the file into a memory stream and use the in memory copy to initialize the image.
I'd personally go with option #3 for most cases. Be sure to dispose of the image when you've finished using it - it is best if you can wrap it in a using ( ) block.