Async Task outputting in chinese characters instead of readable text - c#

I am attempting to search files for specific text using an async Task. The output I receive is in chinese characters instead of what is actually in the text file I am parsing. Here is the code:
public async void ProcessRead(string fileLocation)
{
string filePath = fileLocation;
if (File.Exists(filePath) == false)
{
Debug.WriteLine("file not found: " + filePath);
}
else
{
try
{
string text = await ReadTextAsync(filePath);
Debug.WriteLine(text);
if (text.Contains(inputContentPattern))
{
addToDataGrid(Path.GetFileName(filePath), filePath, "");
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
}
findButton.Enabled = true;
cancelFindButton.Enabled = false;
}
private async Task<string> ReadTextAsync(string filePath)
{
using (FileStream sourceStream = new FileStream(filePath,
FileMode.Open, FileAccess.Read, FileShare.Read,
bufferSize: 4096, useAsync: true))
{
StringBuilder sb = new StringBuilder();
byte[] buffer = new byte[0x1000];
int numRead;
while ((numRead = await sourceStream.ReadAsync(buffer, 0, buffer.Length)) != 0)
{
string text = Encoding.Unicode.GetString(buffer, 0, numRead);
sb.Append(text);
}
return sb.ToString();
}
}

You are reading the file using Unicode encoding (in an incorrect way). Find out what encoding the file actually has and use that encoding. Simply use File.ReadAllText and delete ReadTextAsync.
Async IO brings you zero performance benefits here so just don't do it. If this is a UI app use await Task.Run(() => File.ReadAllText(...)).

Related

Task.Run still freezing UI

So, i'm trying to convert a large byte array into it's base64 encoded variant. But no matter what i try, it seems to freeze up my UI every time it runs.
This is what i've got currently:
private async void TxtOutput_DragDrop(object sender, DragEventArgs e)
{
string outputText = String.Empty;
if (e.Data.GetDataPresent(DataFormats.FileDrop))
{
string[] path = (string[])e.Data.GetData(DataFormats.FileDrop);
byte[] fileBytes = File.ReadAllBytes(path[0]);
txtOutput.Text = await Task.Run(() => {return Convert.ToBase64String(fileBytes);});
_ = fileBytes;
_ = path;
}
}
So, the line that freezes everything up is:
txtOutput.Text = await Task.Run(() => {return Convert.ToBase64String(fileBytes);});
File.ReadAllBytes(path[0])
Could be a bottle neck you can use async operation for read files
Here is an example how to read file async
public async Task ProcessReadAsync()
{
string filePath = #"temp2.txt";
if (File.Exists(filePath) == false)
{
Debug.WriteLine("file not found: " + filePath);
}
else
{
try
{
string text = await ReadTextAsync(filePath);
Debug.WriteLine(text);
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
}
}
private async Task<string> ReadTextAsync(string filePath)
{
using (FileStream sourceStream = new FileStream(filePath,
FileMode.Open, FileAccess.Read, FileShare.Read,
bufferSize: 4096, useAsync: true))
{
StringBuilder sb = new StringBuilder();
byte[] buffer = new byte[0x1000];
int numRead;
while ((numRead = await sourceStream.ReadAsync(buffer, 0, buffer.Length)) != 0)
{
string text = Encoding.Unicode.GetString(buffer, 0, numRead);
sb.Append(text);
}
return sb.ToString();
}
}
Right, so it turns out that my problem was using a textbox for writing the string to instead of a richtextbox. This fixed my problem. Thanks for your answers.

How to async MD5 Calculate? C#

How can i use Calculate MD5 Hash as Async?
I have this code:
static string CalculateMD5(string filename)
{
using (var md5 = MD5.Create())
{
using (var stream = File.OpenRead(filename))
{
var hash = md5.ComputeHash(stream);
return BitConverter.ToString(hash).Replace("-", "").ToUpperInvariant();
}
}
}
I want to hash a file of 1GB and then it freezes my app for 20 sec.
As you are reading from a file you can use IO-bound asynchronicity. Unfortunarely neither the File class nor the MD5 class support it out of the box. But it can be manually done:
static async Task<string> CalculateMD5Async(string filename)
{
using (var md5 = System.Security.Cryptography.MD5.Create())
{
using (var stream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, true)) // true means use IO async operations
{
byte[] buffer = new byte[4096];
int bytesRead;
do
{
bytesRead = await stream.ReadAsync(buffer, 0, 4096);
if (bytesRead > 0)
{
md5.TransformBlock(buffer, 0, bytesRead, null, 0);
}
} while (bytesRead > 0);
md5.TransformFinalBlock(buffer, 0, 0);
return BitConverter.ToString(md5.hash).Replace("-", "").ToUpperInvariant();
}
}
For performance reasons you may want to increase the buffer size.
Try this:
private async void CalculateMd5_Click(object sender, EventArgs e)
{
var filePath = "Path/to/your/file";
var md5hash = await CalculateMd5ForFileAsync(filePath);
}
private Task<string> CalculateMd5ForFileAsync(string filePath)
{
return new Task<string>(() => ComputeMd5HashForFile(filePath));
}
private string ComputeMd5HashForFile(string filePath)
{
using (var md5 = MD5.Create())
{
using (var stream = File.OpenRead(filePath))
{
var hash = md5.ComputeHash(stream);
return BitConverter.ToString(hash).Replace("-", "").ToUpperInvariant();
}
}
}

Download PNG file to local machine using Dropbox.NET on UWP platform

I am able to upload PNG image to Dropbox folder however, I don't know how to download the PNG (or other images) from Dropbox. What I get from the tutorial page is:
async Task Download(DropboxClient dbx, string folder, string file)
{
using (var response = await dbx.Files.DownloadAsync(folder + "/" + file))
{
Console.WriteLine(await response.GetContentAsStringAsync());
}
}
Do anyone have the sample code for downloading file to local drive? Thanks.
After some findings and tryings, finally I found the solution:
public static async Task Download(string folder, string file)
{
StorageFolder storeFolder = ApplicationData.Current.LocalFolder;
CreationCollisionOption options = CreationCollisionOption.ReplaceExisting;
StorageFile outputFile = await storeFolder.CreateFileAsync("temp.png", options);
using (var dbx = new DropboxClient(yourAccessToken))
{
var response = await dbx.Files.DownloadAsync(downloadFolder);
{
using (var file = await outputFile.OpenStreamForWriteAsync())
{
Stream imageStream = await response.GetContentAsStreamAsync();
CopyStream(imageStream, file);
}
}
}
}
With a helper function:
public static void CopyStream(Stream input, Stream output)
{
byte[] buffer = new byte[8 * 1024];
int len;
while ((len = input.Read(buffer, 0, buffer.Length)) > 0)
{
output.Write(buffer, 0, len);
}
}
To upload file:
public static async Task Upload(string filename, string filePath)
{
try
{
string TargetPath = "/data/" + filename + ".png";
const int ChunkSize = 4096 * 1024;
using (var dbx = new DropboxClient(yourAccessToken))
{
using (var fileStream = File.Open(filePath, FileMode.Open))
{
if (fileStream.Length <= ChunkSize)
{
await dbx.Files.UploadAsync(TargetPath, null, false, null, false, body: fileStream);
}
else
{
MessageDialog dialog = new MessageDialog("File is too big");
await dialog.ShowAsync();
}
}
}
}
catch (Exception ex)
{
MessageDialog dialog = new MessageDialog("Error uploading file. " + ex.Message);
await dialog.ShowAsync();
}
}
Hope it helps. Thanks.
The Dropbox API .NET SDK DownloadAsync method gives you a IDownloadResponse which offers three methods for getting the file content:
GetContentAsByteArrayAsync
GetContentAsStreamAsync
GetContentAsStringAsync
For example, to save the file content to a local file, you can do something like:
public async Task Download(string remoteFilePath, string localFilePath)
{
using (var response = await client.Files.DownloadAsync(remoteFilePath))
{
using (var fileStream = File.Create(localFilePath))
{
response.GetContentAsStreamAsync().Result.CopyTo(fileStream);
}
}
}
That would download the file content from a file at remote Dropbox file path remoteFilePath to the local path localFilePath.
What #Greg said is correct. I would like to make a small change that localFilePath mentioned in the code, should have an extension also. For example it should be something like C:\Code\image.jgp and not something like C:\Code. If the filelocation specified does not exist, it will be created automatically and this code will work perfectly.
public async Task Download(string remoteFilePath, string localFilePath)
{
using (var response = await client.Files.DownloadAsync(remoteFilePath))
{
using (var fileStream = File.Create(localFilePath))
{
response.GetContentAsStreamAsync().Result.CopyTo(fileStream);
}
}
}
Here is my logic to download a file using Dropbox.Net API:
private async Task Download(DropboxClient dbx, string remoteFilePath, string localFilePath) {
using(var response = await dbx.Files.DownloadAsync(remoteFilePath)) {
var fileSize = response.Response.Size;
var bufferSize = 1024 * 1024;
var buffer = new byte[bufferSize];
using(var stream = await response.GetContentAsStreamAsync()) {
using(System.IO.FileStream file = new System.IO.FileStream(localFilePath, FileMode.OpenOrCreate)) {
var length = stream.Read(buffer, 0, bufferSize);
while (length > 0) {
file.Write(buffer, 0, length);
var percentage = 100 * file.Length / (double) fileSize;
Console.WriteLine(percentage);
length = stream.Read(buffer, 0, bufferSize);
}
}
}
}
}
And you can call it like:
Await(Download(dbx, url, #"yourDestinationFolder\" + item.Name));
Where item.Name is the full name of the downloaded file e.g. setup.exe

C# using LoadFile or ReadallLines on RichTextBox

I have a problem on a few systems that when we are trying to load the RichTextBox the program becomes unresponsive, we cannot do anything and will have to kill it via Taskmanager.
its working on most systems but a few systems located in a different country there seems to be problem.
we have tried something as simple as :
private void testing4()
{
richTextBox1.LoadFile(#"C:\testing.logs", RichTextBoxStreamType.PlainText);
}
If we decide to use a normal TextBox it appears to be working using .net 4.5, but it still becomes unresponsive. Any ideas?
This may help you:
foreach(var line in File.ReadLines(#"C:\testing.logs"))
{
richTextBox1.AppendText(line+Environment.NewLine);
}
Since you are using framework 4.5, you can do it async, as in MSDN example:
public async void ReadFile()
{
string filePath = #"C:\testing.logs";
if (File.Exists(filePath) == false)
{
Debug.WriteLine("file not found: " + filePath);
}
else
{
try
{
string text = await ReadTextAsync(filePath);
richTextBox1.AppendText(text);
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
}
}
private async Task<string> ReadTextAsync(string filePath)
{
using (FileStream sourceStream = new FileStream(filePath,
FileMode.Open, FileAccess.Read, FileShare.Read,
bufferSize: 4096, useAsync: true))
{
StringBuilder sb = new StringBuilder();
byte[] buffer = new byte[0x1000];
int numRead;
while ((numRead = await sourceStream.ReadAsync(buffer, 0, buffer.Length)) != 0)
{
string text = Encoding.Unicode.GetString(buffer, 0, numRead);
sb.Append(text);
}
return sb.ToString();
}
}
Source: Using Async for File Access

How to Zip a folder with encrypt password using ICSharplib

How to Zip a folder using ICSharplib.
Is there any way I can add a encrypt password while zipping it ?
There is no option that I can use any other dll. Have to use only ICSharplib.
Currently I am using this code block
private static void CompressFiles(string folderPath) {
string zipOutput = #"C:\temp\myoutput.zip";
try {
using (ZipOutputStream zs = new ZipOutputStream(File.Create(zipOutput))) {
zs.SetLevel(9); // 0-9 (9 being best compression)
foreach (string file in Directory.GetFiles(folderPath)) {
ZipEntry entry = new ZipEntry(Path.GetFileName(file));
entry.DateTime = DateTime.Now;
using (FileStream fs = File.OpenRead(file)) {
byte[] buffer = new byte[fs.Length];
fs.Read(buffer, 0, buffer.Length);
entry.Size = buffer.Length; // This is very important
zs.PutNextEntry(entry);
zs.Write(buffer, 0, buffer.Length);
}
}
zs.Finish();
zs.Close();
}
}
catch { throw; }
}
It can zip all the files in the folder.
But What I want is to zip the whole folder.
Like the folders in side that folder also be included in the zip file .
Thanks in advance
Use the FastZip object.
ICSharpCode.SharpZipLib.Zip.FastZip z = new ICSharpCode.SharpZipLib.Zip.FastZip();
z.CreateEmptyDirectories = true;
z.CreateZip("F:\\ZipTest.zip", "F:\\ZipTest\\", true, "");
if (File.Exists("F:\\ZipTest.zip"))
Console.WriteLine("Done");
else
Console.WriteLine("Failed");
I use following code:
public static bool ZipIt(string sourcePath, string destinationPath)
{
List<string> ListOfFiles = GetListOfFiles(sourcePath);
try
{
string OutPath = destinationPath + ".zip";
int TrimLength = (Directory.GetParent(sourcePath)).ToString().Length;
TrimLength += 1;
//remove '\'
FileStream ostream;
byte[] obuffer;
ZipOutputStream oZipStream = new ZipOutputStream(System.IO.File.Create(OutPath));
oZipStream.Password = EncodePassword("Password");
oZipStream.SetLevel(9);
// 9 = maximum compression level
ZipEntry oZipEntry;
foreach (string Fil in ListOfFiles.ToArray()) // for each file, generate a zipentry
{
oZipEntry = new ZipEntry(Fil.Remove(0, TrimLength));
oZipStream.PutNextEntry(oZipEntry);
if (!Fil.EndsWith(#"/")) // if a file ends with '/' its a directory
{
ostream = File.OpenRead(Fil);
obuffer = new byte[ostream.Length];
ostream.Read(obuffer, 0, obuffer.Length);
oZipStream.Write(obuffer, 0, obuffer.Length);
ostream.Close();
}
}
oZipStream.Finish();
oZipStream.Close();
return true;
}
catch (Exception ex)
{
return false;
}
}
public static string EncodePassword(string originalPassword)
{
Byte[] encodedBytes;
encodedBytes = ASCIIEncoding.Default.GetBytes(originalPassword);
return BitConverter.ToString(encodedBytes);
}

Categories