Reverting Replace in a text file - c#

I have a template I'm using to print labels, what I'm currently doing is a Replace() on the variable parts of my template and print it as is.
What is the best way to recover the original template after printing ? Revert manually all the changes ? Not modifying the template at first but create a copy that I modify, print and delete ?
The template looks like :
data1 : $1
data2 : $2
data3 : $3
data4 : $4
and then Replace() + print with :
string text = File.ReadAllText(filePath);
text = text.Replace("$1", textBoxNumOF.Text);
text = text.Replace("$2", designation);
text = text.Replace("$3", textBoxNumOF.Text.Substring(textBoxNumOF.Text.Length - 4));
text = text.Replace("$4", "1");
File.WriteAllText(filePath, text, UTF8Encoding.UTF8);
PrintDialog pd1 = new PrintDialog();
pd1.PrinterSettings = new PrinterSettings();
EnvoiImpression.SendFileToPrinter(#"Datamax-O'Neil H-4310 (Copie 1)", filePath);

Read your template and write the output which you are sending to the printer into a temp file inside the temp directory of windows.
Please see the following function:
public static string GetTempFile()
{
// get temporary path
var tempPath = Path.GetTempPath();
// get temporary filename
string tempFileName = Path.GetRandomFileName();
//combine
return Path.Combine(tempPath, tempFileName);
}
This way you do not need to revert your template and comply with the rules for temporary files on Windows. I suggest that you remember the files for deleting all your temporary files again from disk after your program / method was successful.
The function
EnvoiImpression.SendFileToPrinter(#"Datamax-O'Neil H-4310 (Copie 1)", filePath);
is sadly unknown to my. But perhaps there is also an overload which does accept a Stream? If so, you could edit your template in a MemoryStream and do not even need to write to the disk.

Related

iPad can't read text file

In my Unity3D project I have several text fields. I saved my text in some text files.
When I test my project on the computer everything works fine, and my code reads the text files. But if I upload to my iPad it won't work and the text fields stay empty.
In the image you can see where I have saved my text files.
To read my text files I use the following code:
public Text infoText;
void Update()
{
readTextFile("FileName", "StepNumber")
}
public void readTextFile(string fileName, string stepNumber)
{
StreamReader txt_Reader = new StreamReader("Assets/Resources/Text_Files/" + fileName + ".txt");
while(!txt_Reader.EndOfStream)
{
string txt_String = txt_Reader.ReadLine();
if(txt_String.Contains(stepNumber))
{
string[] separator = { "_" };
string[] strList = txt_String.Split(separator, System.StringSplitOptions.RemoveEmptyEntries);
infoText.text = string.Join("\n", strList.Skip(1));
}
}
}
What do I have to change that my iPad can read from the text files?
EDIT:
My text files looks like this:
Step 1:
* Some Text
* Some Text
Step 2:
* Some Text
* Some Text
* Some Text
Step 3:
* Some Text
Step 4:
* Some Text
So each * should be a new line in my text field. With my old c# code this was no problem, but with
var lines = textFiles.text.Split(new char[] { `*` });
foreach(var line in lines)
{
...
}
i do not know how I can do that, that my text field shows all two lines for step one.
First of all from the Best Practices for the Resources folder
**Don't use it!
Please read the reasons there.
In general for system paths do never use simple string concatenation + "/" +!
Rather use Path.Combine which automatically uses the correct path separators according to the executing platform
Path.Combine(Application.dataPath, "Resources", "Text_Files", fileName + ".txt");
However, you don't/can't simply use a StreamReader to access the Resources folders (See Resources API since it is packed into the build so you have to go through Resources.Load like
// Here you can use / since this is how Unity stores internal paths
// for load you omit the suffix
TextAsset textFile = Resources.Load<TextAsset>("Text_Files/" + filename);
string fileContent = textFile.text;
Or also have a look at Resources.LoadAsync to not block the main thread meanwhile.
BUT
Speaking about blocking the main thread: What you definitely do not want to do is using any of these within Update thus doing heavy FileIO/Loading every frame!
Store the content of that file once as it won't change afterwards anyway!
Depending on your needs you could also simply put your file in any other folder inside the Assets and simply use a TextAsset field directly and drag it into according slot via the Inspector
public TextAsset textFile;
Finally you can then go through the lines one by one using e.g.
var lines = textFile.text.Split(new char[]{'/n'});
foreach(var line in lines)
{
...
}
Note that also that Split is a quite heavy operation since it has to parse every single character in the string and create new substrings so even store these results somewhere in a field of you need them multiple times during runtime!
Typed on smartphone but I hope the idea gets clear
In your case, StreamReader txt_Reader = new StreamReader("Assets/Resources/Text_Files/" + fileName + ".txt"); points to a file on your computer. Assets/Resources/Text_Files/ only exists on your computer.
You need to access a folder that exists on your iPad. It's likely you also didn't save your data to a folder existing on your IPad.
For other devices you could use : Application.persistentDataPath + "/" + fileName
Source: https://docs.unity3d.com/ScriptReference/Application-dataPath.html

How to delete the last character of a file with C#

Hello I'm beginner with C# and I want to delete the last character of my file to inject JSON objects to this file manually (I know that's not the best way to do that), so I can get the right format I tried with multiple ways like open the file, manipulating the string (deleting the last character) and when I try to replace the text in that same file I have errors like IOException: The process cannot access the file 'file path' because it is being used by another process or System.UnauthorizedAccessException : 'Access to the path 'C:\Users\ASUS\Desktop\Root' is denied.
I'll show you the code :
StoreLogs Log = new StoreLogs()
{
Id = ID,
DateTime = dateT,
TaskName = task,
SrcAddress = srcPath,
DstAddress = path,
FileSize = DirSize(new DirectoryInfo(srcPath)),
DelayTransfer = ts.Milliseconds,
};
// Record JSON data in the variable
string strResultJson = JsonConvert.SerializeObject(Log);
// Show the JSON Data
// Console.WriteLine(strResultJson);
// Write JSON Data in another file
string MyJSON = null;
string strPath = #"C:\Users\ASUS\Desktop\Backup\logs\log.json";
if (File.Exists(strPath))
{
//FileInfo table = new FileInfo(strPath);
//string strTable = table.OpenText().ReadToEnd();
//string erase = strTable.Remove(strTable.LastIndexOf(']'));
//Console.WriteLine(erase);
//StreamReader r1 = new StreamReader(strPath);
//string strTable = r1.OpenText().ReadToEnd();
//string erase = strTable.Remove(strTable.LastIndexOf(']'));
//r1.Close();
using (StreamReader sr = File.OpenText(strPath))
{
string table = sr.ReadToEnd();
string erase = table.Remove(table.LastIndexOf(']'));
sr.Close();
File.WriteAllText(strPath, erase);
}
//MyJSON = "," + strResultJson;
//File.AppendAllText(strPath, MyJSON + "]");
//Console.WriteLine("The file exists.");
}
else if (!File.Exists(strPath))
{
MyJSON = "[" + strResultJson + "]";
File.WriteAllText(strPath, MyJSON);
Console.WriteLine("The file doesn't exists.");
}
else
{
Console.WriteLine("Error");
}
// End
Console.WriteLine("JSON Object generated !");
Console.ReadLine();
And that's the result I want :
[{"Id":"8484","DateTime":"26 novembre 2019 02:33:35 ","TaskName":"dezuhduzhd","SrcAddress":"C:\\Users\\ASUS\\Desktop\\Root","DstAddress":"C:\\Users\\ASUS\\Desktop\\Backup","FileSize":7997832.0,"DelayTransfer":0.0},{"Id":"8484","DateTime":"26 novembre 2019 02:33:35 ","TaskName":"dezuhduzhd","SrcAddress":"C:\\Users\\ASUS\\Desktop\\Root","DstAddress":"C:\\Users\\ASUS\\Desktop\\Backup","FileSize":7997832.0,"DelayTransfer":0.0},{"Id":"8484","DateTime":"26 novembre 2019 02:33:35 ","TaskName":"dezuhduzhd","SrcAddress":"C:\\Users\\ASUS\\Desktop\\Root","DstAddress":"C:\\Users\\ASUS\\Desktop\\Backup","FileSize":7997832.0,"DelayTransfer":0.0}]
Edit :
Thank you all for your advices
Solution:
FileStream fs = new FileStream(strPath, FileMode.Open, FileAccess.ReadWrite);
fs.SetLength(fs.Length - 1);
fs.Close();
In the code example you have posted you are opening a stream to read the file. A using block will dispose the stream after you exit the block. You are trying to write to the file, while the read stream is still accessing it (the read stream still exists). You've basically opened the file, you read from it, and are trying to write back to it while still holding it open. The reason this is a problem is that you are not using the stream to write. So your second, write, process is unable to access the file. I see you are closing the stream prior to write, but I'm willing to bet it's still holding the reference open.
I would try this method:
How to both read and write a file in C#
what it says is the access to the path (C:\Users\ASUS\Desktop\Root) denied for the user who is running the application. for ex: If you are running from Visual studio on user1 windows login then user1 should have appropriate rights to that root folder. If the code is running by itself (exe) then check the access for that user who is invoking that exe.
Based on the errors you posted seems that:
Maybe you're leaving some stream open pointing to the file you want to edit, use the 'using' statement to avoid this (see this link for more info)
You're trying to access a file when you don't have needed permissions (you aren't a system admin or file is read-only), try changing file ubication or setting it to be writeable (see this link for mor info about the UnauthorizedAccessException exception)
Hope this helps you!

Pass more arguments to an already opened cmd prompt in C#

I want to loop through all images in a folder, retrieve each image's name and pass an argument using the name. This is what I have:
foreach (string imageFile in Directory.EnumerateFiles(filePath))
{
//Get image name and save it as string
string args = "something"; //a line of argument with image name in it
Process.Start("cmd", #"/c cd C:\Tesseract-OCR && " + args);
}
The problem with above code is that, for each image file, it will open up a new command prompt. Instead, I want something like:
Process.Start("cmd", #"/k cd C:\Tesseract-OCR");
foreach (string imageFile in Directory.EnumerateFiles(filePath))
{
//For each imageFile I have, pass an argument to the opened cmd prompt
}
There are a few methods, but generally the simplest is to create a batch file with all of the commands you want to execute then pass that as a parameter to cmd.
Something like this:
string imageFolder = #"C:\Path\To\Images";
string batchFile = #"C:\Temp\cmds.cmd";
string outputFile = #"C:\Temp\cmds.log";
// substitute your own command here. "{0}" will be substituted for filename
string command = #"attrib ""{0}"" >> """ + outputFile + #"""";
// delete the batch file if it exists
if (File.Exists(batchFile))
File.Delete(batchFile);
// create batch file from content of image folder
using (var writer = File.CreateText(batchFile))
{
writer.WriteLine("#echo off");
foreach (var file in Directory.EnumerateFiles(imageFolder, "*.jpg"))
writer.WriteLine(command, file);
}
// Delete the output file if it exists
if (File.Exists(outputFile))
File.Delete(outputFile);
// Execute the batch
var p = Process.Start("cmd", #"/c """ + batchFile + #"""");
p.WaitForExit();
After that completes you can grab the content of the output file and parse it for results. If you need a break between the outputs, just echo something distinctive between each one. Maybe something like:
// create batch file from content of image folder
using (var writer = File.CreateText(batchFile))
{
writer.WriteLine("#echo off");
foreach (var file in Directory.EnumerateFiles(imageFolder, "*.jpg"))
{
writer.WriteLine(#"echo -----Start: {0}>>""{1}""", file, outputFile);
writer.WriteLine(command, file);
writer.WriteLine(#"echo -----End: {0}>>""{1}""", file, outputFile);
}
}
That way you get the filename in the output as well to help with parsing.
Another option is to use full stream redirection to streams that you can write commands to and read responses from. This would allow you to have a command prompt running somewhere in the background that you can issue commands to. Seems simple, but honestly it takes a lot of work to get just right. If you want to go this way I'd suggest redirecting all three standard streams.
Why not have the program create a batch file containing all the files/commands to be executed, then use Process.Start to execute the batch file?
You can use Directory.GetFiles() to get a string array of all the files in a directory. Then use String.Join() to merge the array into one long string of file names separated by space. I would also wrap each item in quotes if your path or files contain spaces.
const string QUOTE = "\"";
const string SPACE = " ";
const string SEPARATOR = QUOTE + SPACE + QUOTE;
string[] files = Directory.GetFiles(filePath, "*.png");
string allFiles = QUOTE + String.Join(SEPARATOR, files) + QUOTE;
Console.WriteLine(#"cmd.exe /c cd C:\Tesseract-OCR && " + allFiles);

How to prepend a header in a text file

How to prepend/append text beginning of the existing data in a text file.
Basically i need to provide a header before this data in a text file. This header is a dynamic data. Please note this data is coming from external source or SQL package or from somewhere. So After getting data in a text file then i want to provide a header text with comma separated in the existing entries/data of a text file.
I've sample data in a text file as below:
123,"SAV","CBS123",2010-10-10 00:00:00
456,"CUR","CBS456",2012-02-01 00:00:00
Header text to Prepend:
HDR<TableName><DateTime>
Output i need as below:
TableName: Account
DateTime: 2012-05-09 12:52:00
HDRAccount2012-05-09 12:52:00
123,"SAV","CBS123",2010-10-10 00:00:00
456,"CUR","CBS456",2012-02-01 00:00:00
Please help me how to get the same in both languages VB6.0, C#.NET
Note that you can't technically 'insert' into a file and have all contents 'shift' down. Best you can do is read the file and rewrite it with a new line. Here's one way to do it efficiently:
static void InsertHeader(string filename, string header)
{
var tempfile = Path.GetTempFileName();
using (var writer = new StreamWriter(tempfile))
using (var reader = new StreamReader(filename))
{
writer.WriteLine(header);
while (!reader.EndOfStream)
writer.WriteLine(reader.ReadLine());
}
File.Copy(tempfile, filename, true);
File.Delete(tempfile);
}
Credits to this answer for the idea but improved enough to make it worth posting separately.
Now if you want something that accepts the table name and date time, just add this as a second function:
static void InsertTableHeader(string filename, string tableName, DateTime dateTime)
{
InsertHeader(filename,
String.Format("HDR{0}{1:yyyy-MM-dd HH:MM:ss}",
tableName,
dateTime));
}
So just call InsertHeader(filename, "Account", DateTime.Now) or similar as needed.
var fn = #"c:\temp\log.csv";
var hdr1 = "Account";
var hdr2 = "2012-05-09 12:52:00";
System.IO.File.WriteAllText(fn, System.String.Format("HDR {0} {1}\n{2}", hdr1, hdr2, System.IO.File.ReadAllText(fn)))
String[] headerLines = new String[]{"HDR<TableName><DateTime>"};
String filename = "1.txt";
var newContent = headerLines.Union(File.ReadAllLines(filename));
File.WriteAllLines(filename, newContent);
VB6 translation of yamen's answer. Air code! I haven't compiled this, much less run
it!
Sub InsertHeader(ByVal filename As String, ByVal header As String)
Dim tempfile As String
Dim readUnit As Integer
Dim writeUnit As Integer
tempfile = "c:\tempfile" '' TODO generate better temporary filename -
'' here is a link to help with getting path of temporary directory
'' http://vb.mvps.org/samples/SysFolders
readUnit = FreeFile
Open filename For Input As #readUnit
writeUnit = FreeFile
Open tempfile For Output As #writeUnit
Print #writeUnit, header
Do Until Eof(readUnit)
Dim nextLine As String
Line Input #readUnit, nextLine
Print #writeUnit, nextLine
Loop
Close readUnit
Close writeUnit
Kill filename
FileCopy tempfile, filename
Kill tempfile
End sub
You can do it in the reverse order of the 1st answere, meanse first your write the header in text file then open that text file in append mode and then woirite the data ..for opening the file in append mode use following code line:
FileStream aFile = new FileStream(filePath, FileMode.Append,
FileAccess.Write);
StreamWriter sw = new StreamWriter(aFile);
sw.Write(text);
sw.Close();
aFile.Close();

listing files using C#, file with % wont open

I am listing pdf files using C#, but some files wont open because they have percentage(%) signs on their filenames, the user still wants the % to be shown on the filename, but I can't get it to work.
DirectoryInfo directory = new DirectoryInfo("mydirectory/News Files");
FileSystemInfo[] files = directory.GetFiles("*.pdf");
var orderedFiles = files.OrderByDescending(f => f.Name);
foreach (FileSystemInfo file in orderedFiles)
{
var link = new HyperLink { ID = file.FullName };
link.NavigateUrl ="/News Files/"+ file.Name;
link.Text = Regex.Split(file.Name, ".pdf")[0];
link.CssClass = "linkpdf";
newsListContainer.Controls.Add(link);
}
But with this code file with the name like my20%sign.pdf will not open in the browser.
You could try Uri.EscapeUriString.
Also, you shouldn't construct urls/filenames using string concatenation with /. You should usually use a Uri/filename parsing library, such as the Uri class
That's not surprising. The %20 is interpreted by the browser as a "white space", as it is the url encoded equivalent value. So if your file is named "My%20File.pdf", the browser will decode the url and actually look for "My File.pdf".
For further reference, check this: http://www.w3schools.com/tags/ref_urlencode.asp
You can replace %20 with " ". filename.replace("%20"," ");

Categories

Resources